22 Commits
Author SHA1 Message Date
Thomas StoddardandKyle Schwarz 4db27aa187 Bindings: Python: Add ISO-TP 2026-10-20 21:15:12 -04:00
Thomas StoddardandKyle Schwarz 1d3039775d Device: Refactor T1S settings 2026-10-06 15:16:33 -04:00
Max BrombachandKyle Schwarz fb241dc5cd EventManager: Fix potential ABBA deadlock if callback contains locks 2026-10-02 15:38:59 -04:00
Max BrombachandKyle Schwarz 3932b54947 Device: RAD-Gigastar and RAD-Gigastar 2: Fix bootloader pipeline 2026-10-02 14:28:40 -04:00
Nicholas ZamoraandKyle Schwarz f4836f279f Device: RAD-Gemini to RAD-Argos 2026-10-02 13:53:55 -04:00
Thomas StoddardandKyle Schwarz 7ef57e6737 Device: Improve TC10 message filtering 2026-09-30 13:07:13 -04:00
David RebbeandKyle Schwarz 4c0781190e Message: EthPhyMessage: Add Status 2026-09-29 15:01:36 -04:00
Kyle Schwarz 0a67c9cf5d Platform: Servd: Add address configuration 2026-09-28 12:02:40 -04:00
David RebbeandKyle Schwarz f310938684 Message: Validate PHY register batches 2026-09-24 20:13:48 -04:00
Thomas StoddardandKyle Schwarz f0b1341cdf Device: Write MACsec configs by network ID 2026-09-24 19:49:23 -04:00
Max BrombachandKyle Schwarz b54bf80c40 EventManager: Always run callbacks on event 2026-09-24 13:26:13 -04:00
Bryant JonesandKyle Schwarz 0164cef376 NeoVIFIRE3FlexRay: Fix incorrect FlexRay controllers 2026-09-23 16:46:37 -04:00
Thomas StoddardandKyle Schwarz 8cd907250d Bindings: Python: Add Main51MessageFilter support 2026-09-21 13:39:27 -04:00
David RebbeandKyle Schwarz bb892bfd9b Bindings: Python: Support multi-config generators for stubgen 2026-09-17 11:27:23 -04:00
William SkellengerandKyle Schwarz 8801e949da CI: Enable interruptible 2026-09-15 17:37:51 -04:00
Samuel BejkoandKyle Schwarz d95a17b360 LIN: Add wakeup request 2026-09-14 17:13:23 -04:00
Kurt WachowskiandKyle Schwarz 3a6501d116 Device: Add ISO-15765 hardware acceleration 2026-09-10 20:52:01 -04:00
Bryant JonesandKyle Schwarz 34875129ee Gigastar: Add FLEXRAY_01 network 2026-09-10 14:18:24 -04:00
Jonathan SchwartzandKyle Schwarz 236c6ad089 Device: Add manufacturing config message 2026-09-10 12:56:55 -04:00
Max Brombach cf58f819cb Platform: Darwin: Replace deprecate kIOMasterPortDefault with kIOMainPortDefault 2026-08-27 18:33:01 +00:00
Kyle Schwarz 07e4eca14a Heartbeat: Include DeviceStatus 2026-08-17 15:34:16 -04:00
Max BrombachandKyle Schwarz 936566170f Communication: Add GenericAPIDataMessage and GenericAPIStatusMessage types 2026-08-17 10:30:35 -04:00
88 changed files with 3621 additions and 1567 deletions
+5
View File
@@ -1,3 +1,6 @@
default:
interruptible: true
variables: variables:
DEBIAN_FRONTEND: noninteractive DEBIAN_FRONTEND: noninteractive
LIBICSNEO_ICSPB_REPO: https://gitlab-ci-token:${CI_JOB_TOKEN}@${LIBICSNEO_ICSPB_GIT} LIBICSNEO_ICSPB_REPO: https://gitlab-ci-token:${CI_JOB_TOKEN}@${LIBICSNEO_ICSPB_GIT}
@@ -335,6 +338,7 @@ build python/windows:
deploy python/pypi: deploy python/pypi:
stage: deploy stage: deploy
interruptible: false
variables: variables:
TWINE_USERNAME: __token__ TWINE_USERNAME: __token__
TWINE_PASSWORD: $PYPI_TOKEN TWINE_PASSWORD: $PYPI_TOKEN
@@ -359,6 +363,7 @@ deploy python/pypi:
push github: push github:
stage: deploy stage: deploy
interruptible: false
tags: tags:
- linux-build - linux-build
image: alpine:latest image: alpine:latest
+9
View File
@@ -234,8 +234,14 @@ set(SRC_FILES
communication/message/ethernetstatusmessage.cpp communication/message/ethernetstatusmessage.cpp
communication/message/networkmutexmessage.cpp communication/message/networkmutexmessage.cpp
communication/message/clientidmessage.cpp communication/message/clientidmessage.cpp
communication/message/mfgconfigmessage.cpp
communication/message/transmitmessage.cpp communication/message/transmitmessage.cpp
communication/message/spiportkeymessage.cpp communication/message/spiportkeymessage.cpp
communication/message/genericapidatamessage.cpp
communication/message/genericapistatusmessage.cpp
communication/message/iso15765message.cpp
communication/packet/flexraypacket.cpp communication/packet/flexraypacket.cpp
communication/packet/canpacket.cpp communication/packet/canpacket.cpp
communication/packet/a2bpacket.cpp communication/packet/a2bpacket.cpp
@@ -564,9 +570,12 @@ if(LIBICSNEO_BUILD_UNIT_TESTS)
test/unit/a2bencoderdecodertest.cpp test/unit/a2bencoderdecodertest.cpp
test/unit/mdioencoderdecodertest.cpp test/unit/mdioencoderdecodertest.cpp
test/unit/livedataencoderdecodertest.cpp test/unit/livedataencoderdecodertest.cpp
test/unit/macsectest.cpp
test/unit/ringbuffertest.cpp test/unit/ringbuffertest.cpp
test/unit/apperrordecodertest.cpp test/unit/apperrordecodertest.cpp
test/unit/icsneoc2.cpp test/unit/icsneoc2.cpp
test/unit/ethphyregistertest.cpp
test/unit/tc10test.cpp
test/unit/windowsstrings.cpp test/unit/windowsstrings.cpp
test/unit/periodictest.cpp test/unit/periodictest.cpp
) )
+1 -1
View File
@@ -30,13 +30,13 @@ Instructions for installing each API can be found in its respective documentatio
- neoVI PLASMA - neoVI PLASMA
- neoVI RED 2 - neoVI RED 2
- RAD-A2B - RAD-A2B
- RAD-Argos
- RAD-Comet 2 - RAD-Comet 2
- RAD-Comet 3 - RAD-Comet 3
- RAD-Epsilon - RAD-Epsilon
- RAD-EpsilonXL - RAD-EpsilonXL
- RAD-Galaxy - RAD-Galaxy
- RAD-Galaxy 2 - RAD-Galaxy 2
- RAD-Gemini
- RAD-Gigastar - RAD-Gigastar
- RAD-Gigastar 2 - RAD-Gigastar 2
- RAD-Moon 2 - RAD-Moon 2
+1
View File
@@ -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.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.BusRecovered) *status_flags |= ICSNEOC2_LIN_STATUS_BUS_RECOVERED;
if(lin_msg->statusFlags.BreakOnly) *status_flags |= ICSNEOC2_LIN_STATUS_BREAK_ONLY; 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; return icsneoc2_error_success;
} }
+2 -2
View File
@@ -706,7 +706,7 @@ icsneoc2_error_t icsneoc2_settings_t1s_burst_timer_set(icsneoc2_device_t* device
return icsneoc2_error_success; return icsneoc2_error_success;
} }
icsneoc2_error_t icsneoc2_settings_t1s_max_burst_timer_for_get(icsneoc2_device_t* device, icsneoc2_netid_t netid, uint8_t* value) { icsneoc2_error_t icsneoc2_settings_t1s_max_burst_get(icsneoc2_device_t* device, icsneoc2_netid_t netid, uint8_t* value) {
// Make sure the device is valid // Make sure the device is valid
auto res = icsneoc2_device_is_valid(device); auto res = icsneoc2_device_is_valid(device);
if(res != icsneoc2_error_success) { if(res != icsneoc2_error_success) {
@@ -725,7 +725,7 @@ icsneoc2_error_t icsneoc2_settings_t1s_max_burst_timer_for_get(icsneoc2_device_t
} }
} }
icsneoc2_error_t icsneoc2_settings_t1s_max_burst_timer_for_set(icsneoc2_device_t* device, icsneoc2_netid_t netid, uint8_t value) { icsneoc2_error_t icsneoc2_settings_t1s_max_burst_set(icsneoc2_device_t* device, icsneoc2_netid_t netid, uint8_t value) {
// Make sure the device is valid // Make sure the device is valid
auto res = icsneoc2_device_is_valid(device); auto res = icsneoc2_device_is_valid(device);
if(res != icsneoc2_error_success) { if(res != icsneoc2_error_success) {
+3
View File
@@ -117,6 +117,7 @@ static constexpr const char* GPTP_NOT_SUPPORTED = "GPTP clock synchronization is
static constexpr const char* SETTING_NOT_AVAILABLE = "Requested a setting that is not available on this device"; static constexpr const char* SETTING_NOT_AVAILABLE = "Requested a setting that is not available on this device";
static constexpr const char* DISK_FORMAT_NOT_SUPPORTED = "Disk formatting is not supported on this device."; static constexpr const char* DISK_FORMAT_NOT_SUPPORTED = "Disk formatting is not supported on this device.";
static constexpr const char* DISK_FORMAT_INVALID_COUNT = "Disk format config disk count is mismatched with device disk count."; static constexpr const char* DISK_FORMAT_INVALID_COUNT = "Disk format config disk count is mismatched with device disk count.";
static constexpr const char* TC10_REQUEST_FAILED = "The device rejected the TC10 request.";
// Transport Errors // Transport Errors
static constexpr const char* FAILED_TO_READ = "A read operation failed."; static constexpr const char* FAILED_TO_READ = "A read operation failed.";
@@ -381,6 +382,8 @@ const char* APIEvent::DescriptionForType(Type type) {
return DISK_FORMAT_NOT_SUPPORTED; return DISK_FORMAT_NOT_SUPPORTED;
case Type::DiskFormatInvalidCount: case Type::DiskFormatInvalidCount:
return DISK_FORMAT_INVALID_COUNT; return DISK_FORMAT_INVALID_COUNT;
case Type::TC10RequestFailed:
return TC10_REQUEST_FAILED;
// VSA // VSA
case Type::VSABufferCorrupted: case Type::VSABufferCorrupted:
+8 -5
View File
@@ -65,7 +65,6 @@ void EventManager::add(APIEvent event) {
std::lock_guard<std::mutex> eventsLock(eventsMutex); std::lock_guard<std::mutex> eventsLock(eventsMutex);
addEventInternal(event); addEventInternal(event);
} // free the lock so that callbacks may modify events } // free the lock so that callbacks may modify events
runCallbacks(event);
} else { } else {
std::lock_guard<std::mutex> errorsLock(errorsMutex); std::lock_guard<std::mutex> errorsLock(errorsMutex);
lastUserErrors[std::this_thread::get_id()] = event; lastUserErrors[std::this_thread::get_id()] = event;
@@ -75,8 +74,8 @@ void EventManager::add(APIEvent event) {
std::lock_guard<std::mutex> eventsLock(eventsMutex); std::lock_guard<std::mutex> eventsLock(eventsMutex);
addEventInternal(event); addEventInternal(event);
} // free the lock so that callbacks may modify events } // free the lock so that callbacks may modify events
runCallbacks(event);
} }
runCallbacks(event);
} }
void EventManager::addEventInternal(APIEvent event) { void EventManager::addEventInternal(APIEvent event) {
@@ -100,9 +99,13 @@ void EventManager::addEventInternal(APIEvent event) {
} }
void EventManager::runCallbacks(APIEvent event) { void EventManager::runCallbacks(APIEvent event) {
std::lock_guard<std::mutex> lk(callbacksMutex); std::map<int, icsneo::EventCallback> tempCallbacks;
for(auto& i : callbacks) {
i.second.callIfMatch(std::make_shared<APIEvent>(event)); std::lock_guard<std::mutex> lk(callbacksMutex);
tempCallbacks = callbacks;
}
for(auto& i : tempCallbacks)
i.second.callIfMatch(std::make_shared<APIEvent>(event));
} }
void EventManager::setEventLimit(size_t newLimit) { void EventManager::setEventLimit(size_t newLimit) {
+9 -2
View File
@@ -20,9 +20,16 @@ Heartbeat::~Heartbeat() {
void Heartbeat::run() { void Heartbeat::run() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread(); EventManager::GetInstance().downgradeErrorsOnCurrentThread();
auto filter = std::make_shared<MessageFilter>(Message::Type::ResetStatus); auto filter = std::make_shared<MessageFilter>();
filter->includeInternalInAny = true;
bool status = false; bool status = false;
auto cbHandle = device.com->addMessageCallback(std::make_shared<MessageCallback>(filter, [&](std::shared_ptr<Message>) { 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); std::lock_guard lk(mutex);
status = true; status = true;
+19 -23
View File
@@ -545,15 +545,13 @@ int LegacyDLLExport icsneoGetTimeStampForMsg(void* hObject, icsSpyMessage* pMsg,
void LegacyDLLExport icsneoGetISO15765Status(void* hObject, int lNetwork, int lClearTxStatus, int lClearRxStatus, void LegacyDLLExport icsneoGetISO15765Status(void* hObject, int lNetwork, int lClearTxStatus, int lClearRxStatus,
int* lTxStatus, int* lRxStatus) int* lTxStatus, int* lRxStatus)
{ {
// TODO Implement // Not supported
return;
} }
void LegacyDLLExport icsneoSetISO15765RxParameters(void* hObject, int lNetwork, int lEnable, spyFilterLong* pFF_CFMsgFilter, void LegacyDLLExport icsneoSetISO15765RxParameters(void* hObject, int lNetwork, int lEnable, spyFilterLong* pFF_CFMsgFilter,
icsSpyMessage* pTxMsg, int lCFTimeOutMs, int lFlowCBlockSize, int lUsesExtendedAddressing, int lUseHardwareIfPresent) icsSpyMessage* pTxMsg, int lCFTimeOutMs, int lFlowCBlockSize, int lUsesExtendedAddressing, int lUseHardwareIfPresent)
{ {
// TODO Implement // Not supported
return;
} }
int LegacyDLLExport icsneoGetRTC(void* hObject, icsSpyTime* time) int LegacyDLLExport icsneoGetRTC(void* hObject, icsSpyTime* time)
@@ -835,26 +833,25 @@ int LegacyDLLExport icsneoGetErrorInfo(int lErrorNumber, char* szErrorDescriptio
//ISO15765-2 Functions //ISO15765-2 Functions
int LegacyDLLExport icsneoISO15765_EnableNetworks(void* hObject, unsigned long ulNetworks) int LegacyDLLExport icsneoISO15765_EnableNetworks(void* hObject, unsigned long ulNetworks)
{ {
// TODO Implement // Not supported
return false; return false;
} }
int LegacyDLLExport icsneoISO15765_DisableNetworks(void* hObject) int LegacyDLLExport icsneoISO15765_DisableNetworks(void* hObject)
{ {
// TODO Implement // Not supported
return false; return false;
} }
int LegacyDLLExport icsneoISO15765_TransmitMessage(void* hObject, unsigned long ulNetworkID, stCM_ISO157652_TxMessage* pMsg, int LegacyDLLExport icsneoISO15765_TransmitMessage(void* hObject, unsigned long ulNetworkID, stCM_ISO157652_TxMessage* pMsg, unsigned long ulBlockingTimeout)
unsigned long ulBlockingTimeout)
{ {
// TODO Implement // Not supported
return false; return false;
} }
int LegacyDLLExport icsneoISO15765_ReceiveMessage(void* hObject, int ulNetworkID, stCM_ISO157652_RxMessage* pMsg) int LegacyDLLExport icsneoISO15765_ReceiveMessage(void* hObject, int ulNetworkID, stCM_ISO157652_RxMessage* pMsg)
{ {
// TODO Implement // Not supported
return false; return false;
} }
@@ -1076,8 +1073,8 @@ int LegacyDLLExport icsneoGetDeviceSettingsType(void* hObject, EPlasmaIonVnetCha
case NEODEVICE_RADMOON3: case NEODEVICE_RADMOON3:
*pDeviceSettingsType = DeviceRADMoon3SettingsType; *pDeviceSettingsType = DeviceRADMoon3SettingsType;
break; break;
case NEODEVICE_RADGEMINI: case NEODEVICE_RADARGOS:
*pDeviceSettingsType = DeviceRADGeminiSettingsType; *pDeviceSettingsType = DeviceRADArgosSettingsType;
break; break;
case NEODEVICE_RED2: case NEODEVICE_RED2:
*pDeviceSettingsType = DeviceRed2SettingsType; *pDeviceSettingsType = DeviceRed2SettingsType;
@@ -1285,10 +1282,11 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
return false; return false;
neodevice_t* device = reinterpret_cast<neodevice_t*>(hObject); neodevice_t* device = reinterpret_cast<neodevice_t*>(hObject);
const auto& cmd = static_cast<icsneo::J2534Command>(*CmdBuf);
switch (*CmdBuf) switch (cmd)
{ {
case J2534NVCMD_SetNetworkBaudRate: case icsneo::J2534Command::SetNetworkBaudRate:
pTmp = (uint64_t *)&CmdBuf[1]; pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp; NetworkID = (uint16_t)*pTmp;
@@ -1298,7 +1296,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
iRetVal = 0; iRetVal = 0;
break; break;
case J2534NVCMD_GetNetworkBaudRate: case icsneo::J2534Command::GetNetworkBaudRate:
{ {
pTmp = (uint64_t *)&CmdBuf[1]; pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp; NetworkID = (uint16_t)*pTmp;
@@ -1311,7 +1309,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
*pTmp = static_cast<uint64_t>(ret); *pTmp = static_cast<uint64_t>(ret);
break; break;
} }
case J2534NVCMD_SetCANFDRate: case icsneo::J2534Command::SetCANFDRate:
pTmp = (uint64_t *)&CmdBuf[1]; pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp; NetworkID = (uint16_t)*pTmp;
@@ -1322,7 +1320,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
iRetVal = 0; iRetVal = 0;
break; break;
case J2534NVCMD_GetCANFDRate: case icsneo::J2534Command::GetCANFDRate:
pTmp = (uint64_t *)&CmdBuf[1]; pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp; NetworkID = (uint16_t)*pTmp;
@@ -1332,7 +1330,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
*pTmp = icsneo_getFDBaudrate(device, NetworkID); *pTmp = icsneo_getFDBaudrate(device, NetworkID);
break; break;
case J2534NVCMD_GetCANFDTermination: case icsneo::J2534Command::GetCANFDTermination:
pTmp = (uint64_t *)&CmdBuf[1]; pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp; NetworkID = (uint16_t)*pTmp;
@@ -1368,7 +1366,7 @@ int LegacyDLLExport icsneoJ2534Cmd(void* hObject, unsigned char* CmdBuf, short L
} }
break; break;
case J2534NVCMD_SetCANFDTermination: case icsneo::J2534Command::SetCANFDTermination:
pTmp = (uint64_t *)&CmdBuf[1]; pTmp = (uint64_t *)&CmdBuf[1];
NetworkID = (uint16_t)*pTmp; NetworkID = (uint16_t)*pTmp;
@@ -1422,11 +1420,9 @@ int LegacyDLLExport icsneoEnableBusVoltageMonitor(void* hObject, unsigned int en
return false; return false;
} }
int LegacyDLLExport icsneoISO15765_TransmitMessageEx(void* hObject, int LegacyDLLExport icsneoISO15765_TransmitMessageEx(void* hObject, unsigned long ulNetworkID, ISO15765_2015_TxMessage* pMsg, unsigned long ulBlockingTimeout)
unsigned long ulNetworkID,
ISO15765_2015_TxMessage* pMsg,
unsigned long ulBlockingTimeout)
{ {
// Not supported
return false; return false;
} }
+12 -1
View File
@@ -26,6 +26,7 @@ pybind11_add_module(icsneopy
icsneopy/communication/message/message.cpp icsneopy/communication/message/message.cpp
icsneopy/communication/message/canmessage.cpp icsneopy/communication/message/canmessage.cpp
icsneopy/communication/message/canerrormessage.cpp icsneopy/communication/message/canerrormessage.cpp
icsneopy/communication/message/iso15765message.cpp
icsneopy/communication/message/ethernetmessage.cpp icsneopy/communication/message/ethernetmessage.cpp
icsneopy/communication/message/linmessage.cpp icsneopy/communication/message/linmessage.cpp
icsneopy/communication/message/tc10statusmessage.cpp icsneopy/communication/message/tc10statusmessage.cpp
@@ -40,6 +41,9 @@ pybind11_add_module(icsneopy
icsneopy/communication/message/livedatamessage.cpp icsneopy/communication/message/livedatamessage.cpp
icsneopy/communication/message/callback/messagecallback.cpp icsneopy/communication/message/callback/messagecallback.cpp
icsneopy/communication/message/filter/messagefilter.cpp icsneopy/communication/message/filter/messagefilter.cpp
icsneopy/communication/message/filter/main51messagefilter.cpp
icsneopy/communication/message/main51message.cpp
icsneopy/communication/command.cpp
icsneopy/core/macseccfg.cpp icsneopy/core/macseccfg.cpp
icsneopy/flexray/flexray.cpp icsneopy/flexray/flexray.cpp
icsneopy/disk/diskdriver.cpp icsneopy/disk/diskdriver.cpp
@@ -57,7 +61,14 @@ install(TARGETS icsneopy LIBRARY DESTINATION icsneopy)
find_program(STUBGEN_EXE stubgen) find_program(STUBGEN_EXE stubgen)
if(STUBGEN_EXE) 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) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/icsneopy.pyi py.typed DESTINATION icsneopy)
endif() endif()
+1
View File
@@ -92,6 +92,7 @@ void init_event(pybind11::module_& m) {
.value("SettingNotAvaiableDevice", APIEvent::Type::SettingNotAvaiableDevice) .value("SettingNotAvaiableDevice", APIEvent::Type::SettingNotAvaiableDevice)
.value("DiskFormatNotSupported", APIEvent::Type::DiskFormatNotSupported) .value("DiskFormatNotSupported", APIEvent::Type::DiskFormatNotSupported)
.value("DiskFormatInvalidCount", APIEvent::Type::DiskFormatInvalidCount) .value("DiskFormatInvalidCount", APIEvent::Type::DiskFormatInvalidCount)
.value("TC10RequestFailed", APIEvent::Type::TC10RequestFailed)
.value("FailedToRead", APIEvent::Type::FailedToRead) .value("FailedToRead", APIEvent::Type::FailedToRead)
.value("FailedToWrite", APIEvent::Type::FailedToWrite) .value("FailedToWrite", APIEvent::Type::FailedToWrite)
.value("DriverFailedToOpen", APIEvent::Type::DriverFailedToOpen) .value("DriverFailedToOpen", APIEvent::Type::DriverFailedToOpen)
@@ -0,0 +1,40 @@
#include <pybind11/pybind11.h>
#include <pybind11/native_enum.h>
#include "icsneo/communication/command.h"
namespace icsneo {
void init_command(pybind11::module_& m) {
pybind11::native_enum<Command>(m, "Command", "enum.IntEnum")
.value("Main51RxBufferOverflow", Command::Main51RxBufferOverflow)
.value("Main51StartCmd", Command::Main51StartCmd)
.value("Main51TxFifoOverflow", Command::Main51TxFifoOverflow)
.value("Main51BulkInNoData", Command::Main51BulkInNoData)
.value("Main51SetModeComplete", Command::Main51SetModeComplete)
.value("Main51ReadEeprom", Command::Main51ReadEeprom)
.value("Main51CmdDone", Command::Main51CmdDone)
.value("Main51ErrStatus", Command::Main51ErrStatus)
.value("Main51ReadSectorBuff", Command::Main51ReadSectorBuff)
.value("Main51WriteSectorBuff", Command::Main51WriteSectorBuff)
.value("Main51MmcProcessDone", Command::Main51MmcProcessDone)
.value("Main51ReInitDone", Command::Main51ReInitDone)
.value("EnableNetworkCommunication", Command::EnableNetworkCommunication)
.value("EnableNetworkCommunicationEx", Command::EnableNetworkCommunicationEx)
.value("KeepAlive", Command::KeepAlive)
.value("RequestSerialNumber", Command::RequestSerialNumber)
.value("GetMainVersion", Command::GetMainVersion)
.value("SetSettings", Command::SetSettings)
.value("SaveSettings", Command::SaveSettings)
.value("SetDefaultSettings", Command::SetDefaultSettings)
.value("ReadSettings", Command::ReadSettings)
.value("ScriptStatus", Command::ScriptStatus)
.value("WiVICommand", Command::WiVICommand)
.value("Extended", Command::Extended)
.value("ExtendedData", Command::ExtendedData)
.value("FlexRayControl", Command::FlexRayControl)
.value("CoreMiniPreload", Command::CoreMiniPreload)
.finalize();
}
} // namespace icsneo
@@ -0,0 +1,13 @@
#include <pybind11/pybind11.h>
#include "icsneo/communication/message/filter/main51messagefilter.h"
namespace icsneo {
void init_main51messagefilter(pybind11::module_& m) {
pybind11::classh<Main51MessageFilter, MessageFilter>(m, "Main51MessageFilter")
.def(pybind11::init<>())
.def(pybind11::init<Command>());
}
} // namespace icsneo
@@ -0,0 +1,48 @@
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#include "icsneo/communication/message/iso15765message.h"
namespace icsneo {
void init_iso15765message(pybind11::module_& m) {
auto args = pybind11::classh<Iso15765MessageArgs>(m, "Iso15765MessageArgs");
pybind11::classh<Iso15765MessageArgs::ArbId>(args, "ArbId")
.def(pybind11::init<uint32_t, bool>(), pybind11::arg("id") = 0, pybind11::arg("is_29bit") = false)
.def_readwrite("id", &Iso15765MessageArgs::ArbId::Id)
.def_readwrite("is_29bit", &Iso15765MessageArgs::ArbId::Is29Bit);
args.def(pybind11::init<>())
.def_property("tx_index", &Iso15765MessageArgs::getTxIndex, &Iso15765MessageArgs::setTxIndex)
.def_property("arb_id",
[](Iso15765MessageArgs& self) -> Iso15765MessageArgs::ArbId& {
return const_cast<Iso15765MessageArgs::ArbId&>(self.getArbId());
},
&Iso15765MessageArgs::setArbId,
pybind11::return_value_policy::reference_internal)
.def_property("flow_control_arb_id",
[](Iso15765MessageArgs& self) -> Iso15765MessageArgs::ArbId& {
return const_cast<Iso15765MessageArgs::ArbId&>(self.getFlowControlArbId());
},
&Iso15765MessageArgs::setFlowControlArbId,
pybind11::return_value_policy::reference_internal)
.def_property("flow_control_arb_id_mask", &Iso15765MessageArgs::getFlowControlArbIdMask, &Iso15765MessageArgs::setFlowControlArbIdMask)
.def_property("is_can_fd", &Iso15765MessageArgs::getIsCanFd, &Iso15765MessageArgs::setIsCanFd)
.def_property("is_brs_enabled", &Iso15765MessageArgs::getIsBrsEnabled, &Iso15765MessageArgs::setIsBrsEnabled)
.def_property("tx_dl", &Iso15765MessageArgs::getTxDl, &Iso15765MessageArgs::setTxDl)
.def_property("st_min", &Iso15765MessageArgs::getStMin, &Iso15765MessageArgs::setStMin)
.def_property("block_size", &Iso15765MessageArgs::getBlockSize, &Iso15765MessageArgs::setBlockSize)
.def_property("extended_address", &Iso15765MessageArgs::getExtendedAddress, &Iso15765MessageArgs::setExtendedAddress)
.def_property("flow_control_extended_address", &Iso15765MessageArgs::getFlowControlExtendedAddress, &Iso15765MessageArgs::setFlowControlExtendedAddress)
.def_property("padding_value", &Iso15765MessageArgs::getPaddingValue, &Iso15765MessageArgs::setPaddingValue)
.def_property("fs_timeout", &Iso15765MessageArgs::getFsTimeout, &Iso15765MessageArgs::setFsTimeout)
.def_property("fs_wait_timeout", &Iso15765MessageArgs::getFsWaitTimeout, &Iso15765MessageArgs::setFsWaitTimeout)
.def_property("cf_timeout", &Iso15765MessageArgs::getCfTimeout, &Iso15765MessageArgs::setCfTimeout)
.def_property("data",
&Iso15765MessageArgs::getData,
[](Iso15765MessageArgs& self, std::vector<uint8_t> data) { self.setData(std::move(data)); })
.def_property("is_flow_control_enabled", &Iso15765MessageArgs::getIsFlowControlEnabled, &Iso15765MessageArgs::setIsFlowControlEnabled);
}
} // namespace icsneo
@@ -28,7 +28,8 @@ void init_linmessage(pybind11::module_& m) {
.def_readwrite("UpdateResponderOnce", &LINStatusFlags::UpdateResponderOnce) .def_readwrite("UpdateResponderOnce", &LINStatusFlags::UpdateResponderOnce)
.def_readwrite("HasUpdatedResponderOnce", &LINStatusFlags::HasUpdatedResponderOnce) .def_readwrite("HasUpdatedResponderOnce", &LINStatusFlags::HasUpdatedResponderOnce)
.def_readwrite("BusRecovered", &LINStatusFlags::BusRecovered) .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"); 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_BREAK_ONLY", LINMessage::Type::LIN_BREAK_ONLY)
.value("LIN_SYNC_ONLY", LINMessage::Type::LIN_SYNC_ONLY) .value("LIN_SYNC_ONLY", LINMessage::Type::LIN_SYNC_ONLY)
.value("LIN_UPDATE_RESPONDER", LINMessage::Type::LIN_UPDATE_RESPONDER) .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 linMessage
.def(pybind11::init<>()) .def(pybind11::init<>())
@@ -0,0 +1,13 @@
#include <pybind11/pybind11.h>
#include "icsneo/communication/message/main51message.h"
namespace icsneo {
void init_main51message(pybind11::module_& m) {
pybind11::classh<Main51Message, RawMessage>(m, "Main51Message")
.def(pybind11::init<>())
.def_readonly("command", &Main51Message::command);
}
} // namespace icsneo
@@ -154,7 +154,6 @@ void init_macsecconfig(pybind11::module_ & m)
.def("set_storage", &MACsecConfig::setStorage, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("set_storage", &MACsecConfig::setStorage, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("clear", &MACsecConfig::clear, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("clear", &MACsecConfig::clear, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("serialize", &MACsecConfig::serialize, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("serialize", &MACsecConfig::serialize, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_bin_index", &MACsecConfig::getBinIndex, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_type", &MACsecConfig::getType, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_type", &MACsecConfig::getType, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_max_num_rule", &MACsecConfig::getMaxNumRule, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_max_num_rule", &MACsecConfig::getMaxNumRule, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_max_num_secy", &MACsecConfig::getMaxNumSecY, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_max_num_secy", &MACsecConfig::getMaxNumSecY, pybind11::call_guard<pybind11::gil_scoped_release>())
+1 -1
View File
@@ -134,7 +134,7 @@ void init_chipid(pybind11::module_& m) {
.value("SFPModule_lan8670_MCHIP", ChipID::SFPModule_lan8670_MCHIP) .value("SFPModule_lan8670_MCHIP", ChipID::SFPModule_lan8670_MCHIP)
.value("RADGigastar2_ZYNQ", ChipID::RADGigastar2_ZYNQ) .value("RADGigastar2_ZYNQ", ChipID::RADGigastar2_ZYNQ)
.value("SFPModule_ent11100_MCHIP", ChipID::SFPModule_ent11100_MCHIP) .value("SFPModule_ent11100_MCHIP", ChipID::SFPModule_ent11100_MCHIP)
.value("RADGemini_MCHIP", ChipID::RADGemini_MCHIP) .value("RADArgos_MCHIP", ChipID::RADArgos_MCHIP)
.value("Invalid", ChipID::Invalid) .value("Invalid", ChipID::Invalid)
.finalize(); .finalize();
} }
+6 -1
View File
@@ -34,6 +34,7 @@ void init_device(pybind11::module_& m) {
.def("get_serial", &Device::getSerial) .def("get_serial", &Device::getSerial)
.def("get_pcb_serial", &Device::getPCBSerial, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_pcb_serial", &Device::getPCBSerial, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_mac_addresses", &Device::getMACAddresses, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_mac_addresses", &Device::getMACAddresses, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_macsec_networks", &Device::getMACsecNetworks)
.def("get_supported_rx_networks", &Device::getSupportedRXNetworks, pybind11::return_value_policy::reference) .def("get_supported_rx_networks", &Device::getSupportedRXNetworks, pybind11::return_value_policy::reference)
.def("get_supported_tx_networks", &Device::getSupportedTXNetworks, pybind11::return_value_policy::reference) .def("get_supported_tx_networks", &Device::getSupportedTXNetworks, pybind11::return_value_policy::reference)
.def("get_tc10_status", &Device::getTC10Status, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_tc10_status", &Device::getTC10Status, pybind11::call_guard<pybind11::gil_scoped_release>())
@@ -44,6 +45,10 @@ void init_device(pybind11::module_& m) {
.def("is_online_supported", &Device::isOnlineSupported) .def("is_online_supported", &Device::isOnlineSupported)
.def("is_online", &Device::isOnline) .def("is_online", &Device::isOnline)
.def("is_open", &Device::isOpen) .def("is_open", &Device::isOpen)
.def("iso15765_enable", &Device::iso15765Enable, pybind11::arg("network"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("iso15765_disable_all", &Device::iso15765DisableAll, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("iso15765_transmit_message", &Device::iso15765TransmitMessage, pybind11::arg("network"), pybind11::arg("message"), pybind11::arg("timeout"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("iso15765_setup_rx_flow_control", &Device::iso15765SetupRxFlowControl, pybind11::arg("network"), pybind11::arg("message"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("open", [](Device& device) { return device.open(); }, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("open", [](Device& device) { return device.open(); }, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("prepare_script_load", &Device::prepareScriptLoad, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("prepare_script_load", &Device::prepareScriptLoad, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("remove_message_callback", &Device::removeMessageCallback, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("remove_message_callback", &Device::removeMessageCallback, pybind11::call_guard<pybind11::gil_scoped_release>())
@@ -64,7 +69,7 @@ void init_device(pybind11::module_& m) {
.def("set_value_live_data", &Device::setValueLiveData, pybind11::arg("message"), pybind11::call_guard<pybind11::gil_scoped_release>()) .def("set_value_live_data", &Device::setValueLiveData, pybind11::arg("message"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("transmit", pybind11::overload_cast<std::shared_ptr<Frame>>(&Device::transmit), pybind11::call_guard<pybind11::gil_scoped_release>()) .def("transmit", pybind11::overload_cast<std::shared_ptr<Frame>>(&Device::transmit), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("upload_coremini", [](Device& device, std::string& path, Disk::MemoryType memType) { std::ifstream ifs(path, std::ios::binary); return device.uploadCoremini(ifs, memType); }, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("upload_coremini", [](Device& device, std::string& path, Disk::MemoryType memType) { std::ifstream ifs(path, std::ios::binary); return device.uploadCoremini(ifs, memType); }, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("write_macsec_config", &Device::writeMACsecConfig, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("write_macsec_config", &Device::writeMACsecConfig, pybind11::arg("config"), pybind11::arg("network"), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("send_eth_phy_msg", &Device::sendEthPhyMsg, pybind11::arg("message"), pybind11::arg("timeout") = std::chrono::milliseconds(50), pybind11::call_guard<pybind11::gil_scoped_release>()) .def("send_eth_phy_msg", &Device::sendEthPhyMsg, pybind11::arg("message"), pybind11::arg("timeout") = std::chrono::milliseconds(50), pybind11::call_guard<pybind11::gil_scoped_release>())
.def("get_chip_versions", &Device::getChipVersions, pybind11::arg("refreshComponents") = true, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("get_chip_versions", &Device::getChipVersions, pybind11::arg("refreshComponents") = true, pybind11::call_guard<pybind11::gil_scoped_release>())
.def("supports_disk_formatting", &Device::supportsDiskFormatting, pybind11::call_guard<pybind11::gil_scoped_release>()) .def("supports_disk_formatting", &Device::supportsDiskFormatting, pybind11::call_guard<pybind11::gil_scoped_release>())
@@ -38,7 +38,7 @@ void init_devicetype(pybind11::module_& m) {
.value("RADGalaxy2", DeviceType::Enum::RADGalaxy2) .value("RADGalaxy2", DeviceType::Enum::RADGalaxy2)
.value("RADwBMS", DeviceType::Enum::RADwBMS) .value("RADwBMS", DeviceType::Enum::RADwBMS)
.value("RADMoon3", DeviceType::Enum::RADMoon3) .value("RADMoon3", DeviceType::Enum::RADMoon3)
.value("RADGemini", DeviceType::Enum::RADGemini) .value("RADArgos", DeviceType::Enum::RADArgos)
.value("RADComet2", DeviceType::Enum::RADComet2) .value("RADComet2", DeviceType::Enum::RADComet2)
.value("FIRE3_FlexRay", DeviceType::Enum::FIRE3_FlexRay) .value("FIRE3_FlexRay", DeviceType::Enum::FIRE3_FlexRay)
.value("FIRE3_T1S_LIN", DeviceType::Enum::FIRE3_T1S_LIN) .value("FIRE3_T1S_LIN", DeviceType::Enum::FIRE3_T1S_LIN)
+8
View File
@@ -15,6 +15,7 @@ void init_devicetype(pybind11::module_&);
void init_message(pybind11::module_&); void init_message(pybind11::module_&);
void init_canmessage(pybind11::module_&); void init_canmessage(pybind11::module_&);
void init_canerrormessage(pybind11::module_&); void init_canerrormessage(pybind11::module_&);
void init_iso15765message(pybind11::module_&);
void init_ethernetmessage(pybind11::module_&); void init_ethernetmessage(pybind11::module_&);
void init_linmessage(pybind11::module_&); void init_linmessage(pybind11::module_&);
void init_tc10statusmessage(pybind11::module_&); void init_tc10statusmessage(pybind11::module_&);
@@ -32,7 +33,10 @@ void init_deviceextension(pybind11::module_&);
void init_chipid(pybind11::module_&); void init_chipid(pybind11::module_&);
void init_versionreport(pybind11::module_&); void init_versionreport(pybind11::module_&);
void init_device(pybind11::module_&); void init_device(pybind11::module_&);
void init_command(pybind11::module_&);
void init_main51message(pybind11::module_&);
void init_messagefilter(pybind11::module_&); void init_messagefilter(pybind11::module_&);
void init_main51messagefilter(pybind11::module_&);
void init_messagecallback(pybind11::module_&); void init_messagecallback(pybind11::module_&);
void init_version(pybind11::module_&); void init_version(pybind11::module_&);
void init_flexray(pybind11::module_& m); void init_flexray(pybind11::module_& m);
@@ -57,6 +61,7 @@ PYBIND11_MODULE(icsneopy, m) {
init_message(m); init_message(m);
init_canmessage(m); init_canmessage(m);
init_canerrormessage(m); init_canerrormessage(m);
init_iso15765message(m);
init_ethernetmessage(m); init_ethernetmessage(m);
init_linmessage(m); init_linmessage(m);
init_tc10statusmessage(m); init_tc10statusmessage(m);
@@ -69,7 +74,10 @@ PYBIND11_MODULE(icsneopy, m) {
init_scriptstatusmessage(m); init_scriptstatusmessage(m);
init_spimessage(m); init_spimessage(m);
init_livedatamessage(m); init_livedatamessage(m);
init_command(m);
init_main51message(m);
init_messagefilter(m); init_messagefilter(m);
init_main51messagefilter(m);
init_messagecallback(m); init_messagecallback(m);
init_diskdriver(m); init_diskdriver(m);
init_diskdetails(m); init_diskdetails(m);
+21
View File
@@ -26,7 +26,10 @@
#include "icsneo/communication/message/ethernetstatusmessage.h" #include "icsneo/communication/message/ethernetstatusmessage.h"
#include "icsneo/communication/message/networkmutexmessage.h" #include "icsneo/communication/message/networkmutexmessage.h"
#include "icsneo/communication/message/clientidmessage.h" #include "icsneo/communication/message/clientidmessage.h"
#include "icsneo/communication/message/mfgconfigmessage.h"
#include "icsneo/communication/message/spiportkeymessage.h" #include "icsneo/communication/message/spiportkeymessage.h"
#include "icsneo/communication/message/genericapidatamessage.h"
#include "icsneo/communication/message/genericapistatusmessage.h"
#include "icsneo/communication/command.h" #include "icsneo/communication/command.h"
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/communication/packet/canpacket.h" #include "icsneo/communication/packet/canpacket.h"
@@ -41,6 +44,7 @@
#include "icsneo/communication/packet/i2cpacket.h" #include "icsneo/communication/packet/i2cpacket.h"
#include "icsneo/communication/packet/scriptstatuspacket.h" #include "icsneo/communication/packet/scriptstatuspacket.h"
#include "icsneo/communication/packet/linpacket.h" #include "icsneo/communication/packet/linpacket.h"
#include "icsneo/communication/message/iso15765message.h"
#include "icsneo/communication/packet/componentversionpacket.h" #include "icsneo/communication/packet/componentversionpacket.h"
#include "icsneo/communication/packet/supportedfeaturespacket.h" #include "icsneo/communication/packet/supportedfeaturespacket.h"
#include "icsneo/communication/packet/mdiopacket.h" #include "icsneo/communication/packet/mdiopacket.h"
@@ -345,6 +349,12 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
case ExtendedCommand::ExecuteSPIPortKeyOperation: case ExtendedCommand::ExecuteSPIPortKeyOperation:
result = SPIPortKeyMessage::DecodeToMessage(packet->data); result = SPIPortKeyMessage::DecodeToMessage(packet->data);
return true; 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: case ExtendedCommand::GetTC10Status:
result = TC10StatusMessage::DecodeToMessage(packet->data); result = TC10StatusMessage::DecodeToMessage(packet->data);
return true; return true;
@@ -363,6 +373,9 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
); );
protoapi::Id protoId = protoapi::getProtoId(responseBody.data(), responseBody.size()); protoapi::Id protoId = protoapi::getProtoId(responseBody.data(), responseBody.size());
switch(protoId) { switch(protoId) {
case protoapi::Id::MfgConfig:
result = MfgConfigMessage::DecodeToMessage(responseBody);
return true;
case protoapi::Id::NetworkMutex: case protoapi::Id::NetworkMutex:
result = NetworkMutexMessage::DecodeToMessage(responseBody); result = NetworkMutexMessage::DecodeToMessage(responseBody);
return true; return true;
@@ -467,6 +480,14 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
return true; return true;
} }
case Command::J2534Command: {
result = J2534CommandMessage::decodeToMessage(packet->data);
if(!result) {
report(APIEvent::Type::PacketDecodingError, APIEvent::Severity::Error);
return false;
}
return true;
}
default: default:
auto msg = std::make_shared<Main51Message>(); auto msg = std::make_shared<Main51Message>();
msg->command = Command(packet->data[0]); msg->command = Command(packet->data[0]);
@@ -0,0 +1,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;
}
+337
View File
@@ -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);
}
@@ -137,6 +137,7 @@ static std::vector<uint8_t> EncodeFromMessageLIN(std::shared_ptr<Frame> frame, c
linpacket->CoreMiniBitsLIN.TXResponder = 1; linpacket->CoreMiniBitsLIN.TXResponder = 1;
break; break;
case LINMessage::Type::LIN_BREAK_ONLY: case LINMessage::Type::LIN_BREAK_ONLY:
linpacket->CoreMiniBitsLIN.TXCommander = 1;
linpacket->CoreMiniBitsLIN.BreakOnly = 1; linpacket->CoreMiniBitsLIN.BreakOnly = 1;
break; break;
default: default:
+25 -3
View File
@@ -20,7 +20,7 @@ std::shared_ptr<EthPhyMessage> HardwareEthernetPhyRegisterPacket::DecodeToMessag
if( if(
(PhyPacketVersion == pHeader->version) && (PhyPacketVersion == pHeader->version) &&
(sizeof(PhyRegisterPacket_t) == pHeader->entryBytes) && (sizeof(PhyRegisterPacket_t) == pHeader->entryBytes) &&
(numEntries <= MaxPhyEntries) && (numEntries > 0 && numEntries <= MaxPhyEntries) &&
((bytestream.size() - sizeof(PhyRegisterHeader_t)) ((bytestream.size() - sizeof(PhyRegisterHeader_t))
== (sizeof(PhyRegisterPacket_t) * numEntries)) == (sizeof(PhyRegisterPacket_t) * numEntries))
) )
@@ -30,11 +30,16 @@ std::shared_ptr<EthPhyMessage> HardwareEthernetPhyRegisterPacket::DecodeToMessag
for(size_t entryIdx{0}; entryIdx < numEntries; ++entryIdx) for(size_t entryIdx{0}; entryIdx < numEntries; ++entryIdx)
{ {
const PhyRegisterPacket_t* pEntry = (pFirstEntry + entryIdx); const PhyRegisterPacket_t* pEntry = (pFirstEntry + entryIdx);
if(pEntry->version != PhyPacketVersion) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
}
auto phyMessage = std::make_shared<PhyMessage>(); auto phyMessage = std::make_shared<PhyMessage>();
phyMessage->Enabled = (pEntry->Enabled != 0u); phyMessage->Enabled = (pEntry->Enabled != 0u);
phyMessage->WriteEnable = (pEntry->WriteEnable != 0u); phyMessage->WriteEnable = (pEntry->WriteEnable != 0u);
phyMessage->Clause45Enable = (pEntry->Clause45Enable != 0u); phyMessage->Clause45Enable = (pEntry->Clause45Enable != 0u);
phyMessage->BusIndex = static_cast<uint8_t>(pEntry->BusIndex); phyMessage->BusIndex = static_cast<uint8_t>(pEntry->BusIndex);
phyMessage->Status = static_cast<uint8_t>(pEntry->status);
phyMessage->Version = static_cast<uint8_t>(pEntry->version); phyMessage->Version = static_cast<uint8_t>(pEntry->version);
if(phyMessage->Clause45Enable) if(phyMessage->Clause45Enable)
phyMessage->Clause45 = pEntry->clause45; phyMessage->Clause45 = pEntry->clause45;
@@ -43,6 +48,10 @@ std::shared_ptr<EthPhyMessage> HardwareEthernetPhyRegisterPacket::DecodeToMessag
msg->messages.push_back(phyMessage); msg->messages.push_back(phyMessage);
} }
} }
else {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
}
return msg; return msg;
} }
@@ -59,7 +68,20 @@ bool HardwareEthernetPhyRegisterPacket::EncodeFromMessage(const EthPhyMessage& m
report(APIEvent::Type::MessageMaxLengthExceeded, APIEvent::Severity::Error); report(APIEvent::Type::MessageMaxLengthExceeded, APIEvent::Severity::Error);
return false; return false;
} }
auto byteSize = (messageCount * sizeof(PhyRegisterPacket_t)) + sizeof(PhyRegisterHeader_t); // Validate every entry before touching the caller's output or submitting a command.
for(const auto& entry : message.messages) {
if(!entry) {
report(APIEvent::Type::RequiredParameterNull, APIEvent::Severity::Error);
return false;
}
if(entry->BusIndex > 15 || entry->Version != PhyPacketVersion ||
(entry->Clause45Enable ? (entry->Clause45.port > FiveBits || entry->Clause45.device > FiveBits) :
(entry->Clause22.phyAddr > FiveBits || entry->Clause22.regAddr > FiveBits))) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
}
auto byteSize = bytestream.size() + (messageCount * sizeof(PhyRegisterPacket_t)) + sizeof(PhyRegisterHeader_t);
bytestream.reserve(byteSize); bytestream.reserve(byteSize);
bytestream.push_back(static_cast<uint8_t>(messageCount & 0xFF)); bytestream.push_back(static_cast<uint8_t>(messageCount & 0xFF));
bytestream.push_back(static_cast<uint8_t>((messageCount >> 8) & 0xFF)); bytestream.push_back(static_cast<uint8_t>((messageCount >> 8) & 0xFF));
@@ -67,7 +89,7 @@ bool HardwareEthernetPhyRegisterPacket::EncodeFromMessage(const EthPhyMessage& m
bytestream.push_back(static_cast<uint8_t>(sizeof(PhyRegisterPacket_t))); bytestream.push_back(static_cast<uint8_t>(sizeof(PhyRegisterPacket_t)));
for(auto& phyMessage : message.messages) for(auto& phyMessage : message.messages)
{ {
PhyRegisterPacket_t tempPacket; PhyRegisterPacket_t tempPacket{};
tempPacket.Enabled = phyMessage->Enabled ? 0x1u : 0x0u; tempPacket.Enabled = phyMessage->Enabled ? 0x1u : 0x0u;
tempPacket.WriteEnable = phyMessage->WriteEnable ? 0x1u : 0x0u; tempPacket.WriteEnable = phyMessage->WriteEnable ? 0x1u : 0x0u;
tempPacket.BusIndex = (phyMessage->BusIndex & 0xF); tempPacket.BusIndex = (phyMessage->BusIndex & 0xF);
+17 -5
View File
@@ -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.UpdateResponderOnce),
static_cast<bool>(packet->CoreMiniBitsLIN.HasUpdatedResponderOnce), static_cast<bool>(packet->CoreMiniBitsLIN.HasUpdatedResponderOnce),
static_cast<bool>(packet->CoreMiniBitsLIN.BusRecovered), 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; msg->linMsgType = LINMessage::Type::LIN_COMMANDER_MSG;
else if(msg->statusFlags.BreakOnly) else if(msg->statusFlags.BreakOnly)
msg->linMsgType = LINMessage::Type::LIN_BREAK_ONLY; 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.ErrTxRxMismatch || msg->errFlags.ErrRxBreakNotZero ||
msg->errFlags.ErrRxBreakTooShort || msg->errFlags.ErrRxSyncNot55 || msg->errFlags.ErrRxBreakTooShort || msg->errFlags.ErrRxSyncNot55 ||
msg->errFlags.ErrRxDataLenOver8 || msg->errFlags.ErrFrameSync || msg->errFlags.ErrRxDataLenOver8 || msg->errFlags.ErrFrameSync ||
msg->errFlags.ErrFrameMessageID || msg->errFlags.ErrChecksumMatch || msg->errFlags.ErrFrameMessageID || msg->errFlags.ErrChecksumMatch ||
msg->errFlags.ErrFrameResponderData ) msg->errFlags.ErrFrameResponderData) )
{ msg->linMsgType = LINMessage::Type::LIN_ERROR; } { msg->linMsgType = LINMessage::Type::LIN_ERROR; }
msg->timestamp = packet->timestamp; msg->timestamp = packet->timestamp;
@@ -103,7 +115,7 @@ bool HardwareLINPacket::EncodeFromMessage(LINMessage& message, std::vector<uint8
} }
case LINMessage::Type::LIN_BREAK_ONLY: case LINMessage::Type::LIN_BREAK_ONLY:
{ {
size |= 0x20u; size |= 0x80u | 0x20u;
break; break;
} }
case LINMessage::Type::NOT_SET: case LINMessage::Type::NOT_SET:
+2 -6
View File
@@ -231,16 +231,16 @@ MACsecConfig::MACsecConfig(const DeviceType& deviceType) : type(deviceType) {
case icsneo::DeviceType::Enum::RADMoon3: case icsneo::DeviceType::Enum::RADMoon3:
case icsneo::DeviceType::Enum::RADEpsilon: case icsneo::DeviceType::Enum::RADEpsilon:
case icsneo::DeviceType::Enum::RADGigastar2: case icsneo::DeviceType::Enum::RADGigastar2:
case icsneo::DeviceType::Enum::RADComet2:
case icsneo::DeviceType::Enum::RADComet3:
maxSecY = 2; maxSecY = 2;
maxRule = 2; maxRule = 2;
maxSa = 4; maxSa = 4;
binIndex = 0;
break; break;
default: default:
maxSecY = 0; maxSecY = 0;
maxSa = 0; maxSa = 0;
maxRule = 0; maxRule = 0;
binIndex = 0;
ReportEvent(APIEvent::Type::MACsecNotSupported, APIEvent::Severity::Error); ReportEvent(APIEvent::Type::MACsecNotSupported, APIEvent::Severity::Error);
return; return;
} }
@@ -515,10 +515,6 @@ MACsecConfig::operator bool() const {
return (maxSa != 0) || (maxSecY != 0) || (maxRule != 0); return (maxSa != 0) || (maxSecY != 0) || (maxRule != 0);
} }
uint16_t MACsecConfig::getBinIndex() const {
return binIndex;
}
DeviceType MACsecConfig::getType() const { DeviceType MACsecConfig::getType() const {
return type; return type;
} }
+329 -17
View File
@@ -8,6 +8,7 @@
#include "icsneo/disk/fat.h" #include "icsneo/disk/fat.h"
#include "icsneo/communication/message/filter/extendedresponsefilter.h" #include "icsneo/communication/message/filter/extendedresponsefilter.h"
#include "icsneo/communication/message/networkmutexmessage.h" #include "icsneo/communication/message/networkmutexmessage.h"
#include "icsneo/communication/message/mfgconfigmessage.h"
#include "icsneo/communication/message/transmitmessage.h" #include "icsneo/communication/message/transmitmessage.h"
#ifdef _MSC_VER #ifdef _MSC_VER
@@ -238,12 +239,12 @@ std::vector<VersionReport> Device::getChipVersions(bool refreshComponents) {
auto& version = chipVersions.back(); auto& version = chipVersions.back();
auto disectedVersion = disectVersion(component.dotVersion); auto disectedVersion = disectVersion(component.dotVersion);
version.id = chipInfo.id; version.id = chipInfo.id;
version.name = chipInfo.name; version.name = chipInfo.name;
version.major = disectedVersion[0]; version.major = disectedVersion[0];
version.minor = disectedVersion[1]; version.minor = disectedVersion[1];
version.maintenance = disectedVersion[2]; version.maintenance = disectedVersion[2];
version.build = disectedVersion[3]; version.build = disectedVersion[3];
} }
} }
} }
@@ -263,12 +264,12 @@ std::vector<VersionReport> Device::getChipVersions(bool refreshComponents) {
chipVersions.emplace_back(); chipVersions.emplace_back();
auto& version = chipVersions.back(); auto& version = chipVersions.back();
version.id = chipInfo.id; version.id = chipInfo.id;
version.name = chipInfo.name; version.name = chipInfo.name;
version.major = appVer->major; version.major = appVer->major;
version.minor = appVer->minor; version.minor = appVer->minor;
version.maintenance = 0; version.maintenance = 0;
version.build = 0; version.build = 0;
} }
} }
return chipVersions; return chipVersions;
@@ -923,6 +924,36 @@ std::shared_ptr<HardwareInfo> Device::getHardwareInfo(std::chrono::milliseconds
return hardwareInfo; return hardwareInfo;
} }
std::shared_ptr<MfgConfigMessage> Device::getMfgConfig() {
if(!isOpen()) {
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
return nullptr;
}
std::vector<uint8_t> payload = MfgConfigMessage::EncodeArgumentsForGet();
auto response = com->waitForMessageSync(
[this, payload]() {
return com->sendCommand(ExtendedCommand::ProtobufAPI, payload);
},
std::make_shared<MessageFilter>(Message::Type::MfgConfig),
std::chrono::milliseconds(250)
);
if(!response) {
report(APIEvent::Type::Timeout, APIEvent::Severity::Error);
return nullptr;
}
auto mfgConfig = std::dynamic_pointer_cast<MfgConfigMessage>(response);
if(!mfgConfig) {
report(APIEvent::Type::UnexpectedResponse, APIEvent::Severity::Error);
return nullptr;
}
return mfgConfig;
}
std::optional<uint64_t> Device::readLogicalDisk(uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, Disk::MemoryType memType) { std::optional<uint64_t> Device::readLogicalDisk(uint64_t pos, uint8_t* into, uint64_t amount, std::chrono::milliseconds timeout, Disk::MemoryType memType) {
if(!into || timeout <= std::chrono::milliseconds(0)) { if(!into || timeout <= std::chrono::milliseconds(0)) {
@@ -2022,7 +2053,12 @@ std::optional<EthPhyMessage> Device::sendEthPhyMsg(const EthPhyMessage& message,
} }
std::vector<uint8_t> bytes; std::vector<uint8_t> bytes;
HardwareEthernetPhyRegisterPacket::EncodeFromMessage(message, bytes, report); if(timeout.count() <= 0) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return std::nullopt;
}
if(!HardwareEthernetPhyRegisterPacket::EncodeFromMessage(message, bytes, report))
return std::nullopt;
std::shared_ptr<Message> response = com->waitForMessageSync( std::shared_ptr<Message> response = com->waitForMessageSync(
[this, bytes](){ return com->sendCommand(Command::PHYControlRegisters, bytes); }, [this, bytes](){ return com->sendCommand(Command::PHYControlRegisters, bytes); },
std::make_shared<MessageFilter>(Message::Type::EthernetPhyRegister), timeout); std::make_shared<MessageFilter>(Message::Type::EthernetPhyRegister), timeout);
@@ -3623,7 +3659,7 @@ bool Device::requestTC10Wake(Network::NetID network) {
*(Network::NetID*)args.data() = network; *(Network::NetID*)args.data() = network;
auto msg = com->waitForMessageSync([&] { auto msg = com->waitForMessageSync([&] {
return com->sendCommand(ExtendedCommand::RequestTC10Wake, args); return com->sendCommand(ExtendedCommand::RequestTC10Wake, args);
}, std::make_shared<MessageFilter>(Message::Type::ExtendedResponse), std::chrono::milliseconds(1000)); }, std::make_shared<ExtendedResponseFilter>(ExtendedCommand::RequestTC10Wake), std::chrono::milliseconds(1000));
if(!msg) { if(!msg) {
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error); report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
@@ -3636,7 +3672,11 @@ bool Device::requestTC10Wake(Network::NetID network) {
return false; return false;
} }
return resp->response == ExtendedResponse::OK; if(resp->response != ExtendedResponse::OK) {
report(APIEvent::Type::TC10RequestFailed, APIEvent::Severity::Error);
return false;
}
return true;
} }
bool Device::requestTC10Sleep(Network::NetID network) { bool Device::requestTC10Sleep(Network::NetID network) {
@@ -3648,7 +3688,7 @@ bool Device::requestTC10Sleep(Network::NetID network) {
*(Network::NetID*)args.data() = network; *(Network::NetID*)args.data() = network;
auto msg = com->waitForMessageSync([&] { auto msg = com->waitForMessageSync([&] {
return com->sendCommand(ExtendedCommand::RequestTC10Sleep, args); return com->sendCommand(ExtendedCommand::RequestTC10Sleep, args);
}, std::make_shared<MessageFilter>(Message::Type::ExtendedResponse), std::chrono::milliseconds(1000)); }, std::make_shared<ExtendedResponseFilter>(ExtendedCommand::RequestTC10Sleep), std::chrono::milliseconds(1000));
if(!msg) { if(!msg) {
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error); report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
@@ -3661,7 +3701,11 @@ bool Device::requestTC10Sleep(Network::NetID network) {
return false; return false;
} }
return typed->response == ExtendedResponse::OK; if(typed->response != ExtendedResponse::OK) {
report(APIEvent::Type::TC10RequestFailed, APIEvent::Severity::Error);
return false;
}
return true;
} }
bool Device::reboot(bool safe) { bool Device::reboot(bool safe) {
@@ -3730,7 +3774,15 @@ std::optional<GPTPStatus> Device::getGPTPStatus(std::chrono::milliseconds timeou
return *retMsg; return *retMsg;
} }
bool Device::writeMACsecConfig(const MACsecConfig& cfg) { std::vector<Network> Device::getMACsecNetworks() const {
std::vector<Network> networks;
for(const auto& network : getMACsecNetworkMap()) {
networks.emplace_back(network.first);
}
return networks;
}
bool Device::writeMACsecConfig(const MACsecConfig& cfg, Network::NetID network) {
if(!cfg) { if(!cfg) {
report(APIEvent::Type::MACsecNotSupported, APIEvent::Severity::Error); report(APIEvent::Type::MACsecNotSupported, APIEvent::Severity::Error);
return false; return false;
@@ -3741,8 +3793,15 @@ bool Device::writeMACsecConfig(const MACsecConfig& cfg) {
return false; return false;
} }
const auto& networks = getMACsecNetworkMap();
const auto binaryIndex = networks.find(network);
if(binaryIndex == networks.end()) {
report(APIEvent::Type::MACsecNotSupported, APIEvent::Severity::Error);
return false;
}
std::vector<uint8_t> raw = cfg.serialize(); std::vector<uint8_t> raw = cfg.serialize();
return writeBinaryFile(raw, cfg.getBinIndex()); return writeBinaryFile(raw, binaryIndex->second);
} }
bool Device::enableNetworkCommunication(bool enable, uint32_t timeout) { bool Device::enableNetworkCommunication(bool enable, uint32_t timeout) {
@@ -4096,3 +4155,256 @@ void Device::restartHeartbeat() {
stopHeartbeat(); stopHeartbeat();
startHeartbeat(); startHeartbeat();
} }
bool Device::iso15765Enable(const Network& network) {
return J2534_EnableIso15765(network, true);
}
bool Device::iso15765DisableAll(void) {
bool ok = true;
for(const auto& slot : iso15765FirmwareEnabled)
{
if (slot.second)
{
if (!J2534_EnableIso15765(slot.first, false))
ok = false;
}
}
return ok;
}
bool Device::iso15765TransmitMessage(const Network& network, const Iso15765MessageArgs& msg, const std::chrono::milliseconds& timeout) {
if (!isOnline())
return false;
if(iso15765FirmwareEnabled.find(network) == iso15765FirmwareEnabled.end() || !iso15765FirmwareEnabled[network])
return false;
bool result;
Iso15765TxSetupMessage setupMsg;
//Set the network ID to use
if(const auto& coreMiniId = network.getCoreMini())
setupMsg.setCoreMiniId((uint16_t)*coreMiniId);
const uint8_t txIndex = msg.getTxIndex();
setupMsg.setIdx(txIndex);
setupMsg.setId(msg.getArbId().Id);
setupMsg.setFcId(msg.getFlowControlArbId().Id);
setupMsg.setFcIdMask(msg.getFlowControlArbIdMask());
setupMsg.setFsTimeout(msg.getFsTimeout());
setupMsg.setFsWait(msg.getFsWaitTimeout());
const uint32_t messageLength = (uint32_t)msg.getData().size();
setupMsg.setMessageLength(messageLength);
setupMsg.setIs29BitEnabled(msg.getArbId().Is29Bit);
setupMsg.setIsFc29BitEnabled(msg.getFlowControlArbId().Is29Bit);
if(const auto& extAddress = msg.getExtendedAddress())
{
setupMsg.setExtAddressEnabled(true);
setupMsg.setExtendedAddress(*extAddress);
}
if(const auto& extFcAddress = msg.getFlowControlExtendedAddress())
{
setupMsg.setFcExtAddressEnabled(true);
setupMsg.setFlowControlExtendedAddress(*extFcAddress);
}
if(const auto& stMin = msg.getStMin())
{
setupMsg.setOverrideStMin(true);
setupMsg.setStMin(*stMin);
}
if(const auto& blockSize = msg.getBlockSize())
{
setupMsg.setOverrideBlockSize(true);
setupMsg.setBlockSize(*blockSize);
}
if(const auto& padding = msg.getPaddingValue())
{
setupMsg.setPaddingEnabled(true);
setupMsg.setPadding(*padding);
}
setupMsg.setIsBrsEnabled(msg.getIsBrsEnabled());
setupMsg.setIsCanFd(msg.getIsCanFd());
setupMsg.setTxDl(msg.getTxDl());
{
uint32_t octetsToSend = messageLength;
const uint8_t* payload = msg.getData().data();
uint32_t offset = 0;
result = J2534_Transaction(network, std::move(setupMsg), timeout);
while(result && octetsToSend)
{
const uint16_t chunkSize = (uint16_t)std::min((uint32_t)Iso15765TxDataMessage::MaxDataLength, octetsToSend);
Iso15765TxDataMessage dataMsg;
dataMsg.setIdx(txIndex);
dataMsg.setOffset(offset);
dataMsg.setData(&payload[offset], chunkSize);
result = J2534_Transaction(network, std::move(dataMsg), timeout);
offset += chunkSize;
octetsToSend -= chunkSize;
}
}
return result;
}
bool Device::iso15765SetupRxFlowControl(const Network& network, const Iso15765MessageArgs& msg) {
if (!isOnline())
return false;
if(iso15765FirmwareEnabled.find(network) == iso15765FirmwareEnabled.end() || !iso15765FirmwareEnabled[network])
return false;
J2534SetupIso15765FlowControlMessage rxFlowControl;
rxFlowControl.setIsBrsEnabled(msg.getIsBrsEnabled());
rxFlowControl.setIsCanFd(msg.getIsCanFd());
rxFlowControl.setIdx(msg.getTxIndex());
if(const auto& coreMiniId = network.getCoreMini())
rxFlowControl.setCoreMiniId((uint16_t)*coreMiniId);
rxFlowControl.setEnable(true);
if(const auto& blockSize = msg.getBlockSize())
{
rxFlowControl.setBlockSize(*blockSize);
}
rxFlowControl.setCfTimeout(msg.getCfTimeout());
rxFlowControl.setFlowControlTransmissionEnabled(msg.getIsFlowControlEnabled());
if(const auto& extAddress = msg.getExtendedAddress())
{
rxFlowControl.setExtendedAddress(*extAddress);
rxFlowControl.setExtAddressEnabled(true);
}
if(const auto& fcExtAddress = msg.getFlowControlExtendedAddress())
{
rxFlowControl.setFlowControlExtendedAddress(*fcExtAddress);
rxFlowControl.setFcExtAddressEnabled(true);
}
rxFlowControl.setFcId(msg.getFlowControlArbId().Id);
rxFlowControl.setIsFc29BitEnabled(msg.getFlowControlArbId().Is29Bit);
rxFlowControl.setIs29BitEnabled(msg.getArbId().Is29Bit);
rxFlowControl.setId(msg.getArbId().Id);
rxFlowControl.setIdMask(msg.getFlowControlArbIdMask());
if(const auto& padding = msg.getPaddingValue())
{
rxFlowControl.setPadding(*padding);
rxFlowControl.setPaddingEnabled(true);
}
if(const auto& stMin = msg.getStMin())
{
rxFlowControl.setStMin(*stMin);
}
return J2534_Transaction(network, std::move(rxFlowControl), std::chrono::milliseconds(0));
}
bool Device::J2534_Transaction(const Network& network, J2534CommandMessage&& msg, const std::chrono::milliseconds& timeout) {
msg.network = network;
if (timeout.count())
{
static std::shared_ptr<MessageFilter> filter = std::make_shared<Main51MessageFilter>(Command::J2534Command);
const auto& response = com->waitForMessageSync([&](void)
{
return com->sendCommand(msg.command, msg.getArgumentData());
}, filter, timeout);
if (!response)
{
report(APIEvent::Type::NoDeviceResponse, APIEvent::Severity::Error);
return false;
}
auto responseMsg = std::dynamic_pointer_cast<Main51Message>(response);
if (!responseMsg || responseMsg->command != Command::J2534Command)
{
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
return false;
}
}
else
{
return com->sendCommand(msg.command, msg.getArgumentData());
}
// NOTE: responseMsg->data.front()
return true;
}
bool Device::J2534_ClearRxFilters(const Network& network)
{
return J2534_Transaction(network, J2534CommandMessage(J2534CommandMessage::J2534Command::SetupClearCanRxFilters, { (uint8_t)0 /* is this necessary? */}), std::chrono::milliseconds(0));
}
bool Device::J2534_SetupCanRxFilter(const Network& network, const J2534_RxCanFilter& rxCanFilter)
{
return J2534_Transaction(network, J2534SetupCanRxFilteringMessage(rxCanFilter), std::chrono::milliseconds(0));
}
bool Device::J2534_EnableFiltering(const Network& network, const bool enable)
{
return J2534_Transaction(network, J2534EnableFilteringMessage(enable), std::chrono::milliseconds(0));
}
bool Device::J2534_EnableIso15765(const Network& network, const bool enable)
{
if (iso15765FirmwareEnabled[network] == enable)
return true;
if (!J2534_Transaction(network, J2534EnableMessage(enable), std::chrono::milliseconds(0)))
return false;
iso15765FirmwareEnabled[network] = enable;
if (enable)
{
// Turn OFF filtering of CAN messages in the firmware
return J2534_EnableFirmwareUsbPassFilters(network, false);
}
return true;
}
bool Device::J2534_ClearRxFilter(const Network& network, unsigned int iIndex)
{
if (const auto& slot = iso15765FirmwareEnabled.find(network); slot != iso15765FirmwareEnabled.end() && slot->second)
{
J2534_RxCanFilter rxFilter;
memset(&rxFilter, 0, sizeof(rxFilter));
rxFilter.idx = (uint16_t)iIndex;
return J2534_SetupCanRxFilter(network, rxFilter);
}
return false;
}
bool Device::J2534_EnableFirmwareUsbPassFilters(const Network& network, const bool enable)
{
const auto& slot = iso15765FirmwareEnabled.find(network);
if (slot == iso15765FirmwareEnabled.end())
return false;
//check for disconnect here!
if (!slot->second)
{
// Tried to shut-off Rx table message filtering but FW ISO15765 was not enabled
return true; //just ignore it, no filtering can occur anyway
}
if (enable) //turning ON filtering in the Firmware based on the rx table
{
//Rx table message filtering is on by default in the firmware when m_bISO15765_FW_Enabled is true
//need to check here to see if we set index 0 to a PASS all filter (i.e. turned off USB filtering)
if (!J2534_ClearRxFilters(network))
return false;
}
// New "filtering enable" mechanism - old firmware ignores this frame
return J2534_EnableFiltering(network, enable);
}
+4 -4
View File
@@ -221,8 +221,8 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
makeIfSerialMatches<RADMoon3>(dev, newFoundDevices); makeIfSerialMatches<RADMoon3>(dev, newFoundDevices);
#endif #endif
#ifdef __RADGEMINI_H_ #ifdef __RADARGOS_H_
makeIfSerialMatches<RADGemini>(dev, newFoundDevices); makeIfSerialMatches<RADArgos>(dev, newFoundDevices);
#endif #endif
#ifdef __RADMOONDUO_H_ #ifdef __RADMOONDUO_H_
@@ -388,8 +388,8 @@ const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
RADMoon3::DEVICE_TYPE, RADMoon3::DEVICE_TYPE,
#endif #endif
#ifdef __RADGEMINI_H_ #ifdef __RADARGOS_H_
RADGemini::DEVICE_TYPE, RADArgos::DEVICE_TYPE,
#endif #endif
#ifdef __RADMOONDUO_H_ #ifdef __RADMOONDUO_H_
+174
View File
@@ -1113,3 +1113,177 @@ bool IDeviceSettings::setLinuxConfigurationPort(LinuxConfigurationPort port) {
(*os)->ethConfigurationPort = static_cast<uint8_t>(port); (*os)->ethConfigurationPort = static_cast<uint8_t>(port);
return true; return true;
} }
namespace {
void reportT1SUnavailable(const icsneo::device_eventhandler_t& report) {
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
}
std::optional<bool> t1sFlag(const ETHERNET10T1S_SETTINGS* t1s, uint8_t flag, const icsneo::device_eventhandler_t& report) {
if(t1s == nullptr) {
reportT1SUnavailable(report);
return std::nullopt;
}
return (t1s->flags & flag) != 0;
}
bool setT1SFlag(ETHERNET10T1S_SETTINGS* t1s, uint8_t flag, bool enable, const icsneo::device_eventhandler_t& report) {
if(t1s == nullptr) {
reportT1SUnavailable(report);
return false;
}
if(enable)
t1s->flags |= flag;
else
t1s->flags = static_cast<uint8_t>(t1s->flags & ~flag);
return true;
}
std::optional<uint8_t> t1sByte(const uint8_t* field, const icsneo::device_eventhandler_t& report) {
if(field == nullptr) {
reportT1SUnavailable(report);
return std::nullopt;
}
return *field;
}
bool setT1SByte(uint8_t* field, uint8_t value, const icsneo::device_eventhandler_t& report) {
if(field == nullptr) {
reportT1SUnavailable(report);
return false;
}
*field = value;
return true;
}
} // namespace
std::optional<bool> IDeviceSettings::isT1SPLCAEnabledFor(Network net) const {
return t1sFlag(getT1SSettingsFor(net), ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA, report);
}
bool IDeviceSettings::setT1SPLCAFor(Network net, bool enable) {
return setT1SFlag(getMutableT1SSettingsFor(net), ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA, enable, report);
}
std::optional<uint8_t> IDeviceSettings::getT1SLocalIDFor(Network net) const {
const auto* t1s = getT1SSettingsFor(net);
return t1sByte(t1s == nullptr ? nullptr : &t1s->local_id, report);
}
bool IDeviceSettings::setT1SLocalIDFor(Network net, uint8_t id) {
auto* t1s = getMutableT1SSettingsFor(net);
return setT1SByte(t1s == nullptr ? nullptr : &t1s->local_id, id, report);
}
std::optional<uint8_t> IDeviceSettings::getT1SMaxNodesFor(Network net) const {
const auto* t1s = getT1SSettingsFor(net);
return t1sByte(t1s == nullptr ? nullptr : &t1s->max_num_nodes, report);
}
bool IDeviceSettings::setT1SMaxNodesFor(Network net, uint8_t nodes) {
auto* t1s = getMutableT1SSettingsFor(net);
return setT1SByte(t1s == nullptr ? nullptr : &t1s->max_num_nodes, nodes, report);
}
std::optional<uint8_t> IDeviceSettings::getT1STxOppTimerFor(Network net) const {
const auto* t1s = getT1SSettingsFor(net);
return t1sByte(t1s == nullptr ? nullptr : &t1s->to_timer, report);
}
bool IDeviceSettings::setT1STxOppTimerFor(Network net, uint8_t timer) {
auto* t1s = getMutableT1SSettingsFor(net);
return setT1SByte(t1s == nullptr ? nullptr : &t1s->to_timer, timer, report);
}
std::optional<uint8_t> IDeviceSettings::getT1SMaxBurstFor(Network net) const {
const auto* t1s = getT1SSettingsFor(net);
return t1sByte(t1s == nullptr ? nullptr : &t1s->max_burst_count, report);
}
bool IDeviceSettings::setT1SMaxBurstFor(Network net, uint8_t burst) {
auto* t1s = getMutableT1SSettingsFor(net);
return setT1SByte(t1s == nullptr ? nullptr : &t1s->max_burst_count, burst, report);
}
std::optional<uint8_t> IDeviceSettings::getT1SBurstTimerFor(Network net) const {
const auto* t1s = getT1SSettingsFor(net);
return t1sByte(t1s == nullptr ? nullptr : &t1s->burst_timer, report);
}
bool IDeviceSettings::setT1SBurstTimerFor(Network net, uint8_t timer) {
auto* t1s = getMutableT1SSettingsFor(net);
return setT1SByte(t1s == nullptr ? nullptr : &t1s->burst_timer, timer, report);
}
std::optional<uint8_t> IDeviceSettings::getT1SLocalIDAlternateFor(Network net) const {
const auto* t1s = getT1SSettingsFor(net);
return t1sByte(t1s == nullptr ? nullptr : &t1s->local_id_alternate, report);
}
bool IDeviceSettings::setT1SLocalIDAlternateFor(Network net, uint8_t id) {
auto* t1s = getMutableT1SSettingsFor(net);
return setT1SByte(t1s == nullptr ? nullptr : &t1s->local_id_alternate, id, report);
}
std::optional<bool> IDeviceSettings::isT1STerminationEnabledFor(Network net) const {
return t1sFlag(getT1SSettingsFor(net), ETHERNET10T1S_SETTINGS_FLAG_TERMINATION, report);
}
bool IDeviceSettings::setT1STerminationFor(Network net, bool enable) {
return setT1SFlag(getMutableT1SSettingsFor(net), ETHERNET10T1S_SETTINGS_FLAG_TERMINATION, enable, report);
}
std::optional<bool> IDeviceSettings::isT1SBusDecodingBeaconsEnabledFor(Network net) const {
return t1sFlag(getT1SSettingsFor(net), ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS, report);
}
bool IDeviceSettings::setT1SBusDecodingBeaconsFor(Network net, bool enable) {
return setT1SFlag(getMutableT1SSettingsFor(net), ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS, enable, report);
}
std::optional<bool> IDeviceSettings::isT1SBusDecodingAllEnabledFor(Network net) const {
return t1sFlag(getT1SSettingsFor(net), ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL, report);
}
bool IDeviceSettings::setT1SBusDecodingAllFor(Network net, bool enable) {
return setT1SFlag(getMutableT1SSettingsFor(net), ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL, enable, report);
}
std::optional<uint8_t> IDeviceSettings::getT1SMultiIDEnableMaskFor(Network net) const {
const auto* ext = getT1SSettingsExtFor(net);
return t1sByte(ext == nullptr ? nullptr : &ext->enable_multi_id, report);
}
bool IDeviceSettings::setT1SMultiIDEnableMaskFor(Network net, uint8_t mask) {
auto* ext = getMutableT1SSettingsExtFor(net);
return setT1SByte(ext == nullptr ? nullptr : &ext->enable_multi_id, mask, report);
}
std::optional<uint8_t> IDeviceSettings::getT1SMultiIDFor(Network net, uint8_t index) const {
const auto* ext = getT1SSettingsExtFor(net);
if(ext == nullptr) {
reportT1SUnavailable(report);
return std::nullopt;
}
if(index >= sizeof(ext->multi_id)) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return std::nullopt;
}
return ext->multi_id[index];
}
bool IDeviceSettings::setT1SMultiIDFor(Network net, uint8_t index, uint8_t id) {
auto* ext = getMutableT1SSettingsExtFor(net);
if(ext == nullptr) {
reportT1SUnavailable(report);
return false;
}
if(index >= sizeof(ext->multi_id)) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
ext->multi_id[index] = id;
return true;
}
+11
View File
@@ -107,3 +107,14 @@ Analog Output Control
.. literalinclude:: ../../examples/python/analog_out/analog_out_basic.py .. literalinclude:: ../../examples/python/analog_out/analog_out_basic.py
:language: python :language: python
ISO-TP CAN1 Loopback
====================
Two devices, CAN1 wired together. ``--raw`` checks the cable, ``--sf`` sends one
firmware single frame, ``--both`` sends a segmented payload with firmware flow control.
:download:`Download example <../../examples/python/iso15765/iso15765_loopback.py>`
.. literalinclude:: ../../examples/python/iso15765/iso15765_loopback.py
:language: python
+5
View File
@@ -36,6 +36,7 @@ option(LIBICSNEO_BUILD_CPP_ANALOG_OUT_EXAMPLE "Build the analog output example."
option(LIBICSNEO_BUILD_CPP_DISKFORMAT_EXAMPLE "Build the disk format example." ON) option(LIBICSNEO_BUILD_CPP_DISKFORMAT_EXAMPLE "Build the disk format example." ON)
option(LIBICSNEO_BUILD_CPP_T1S_EXAMPLE "Build the T1S example." ON) option(LIBICSNEO_BUILD_CPP_T1S_EXAMPLE "Build the T1S example." ON)
option(LIBICSNEO_BUILD_CPP_GPTP_EXAMPLE "Build the C++ gPTP settings example." ON) option(LIBICSNEO_BUILD_CPP_GPTP_EXAMPLE "Build the C++ gPTP settings example." ON)
option(LIBICSNEO_BUILD_CPP_ISO15765_LOOPBACK_EXAMPLE "Build the C++ ISO15765 two-device CAN1 loopback example." ON)
add_compile_options(${LIBICSNEO_COMPILER_WARNINGS}) add_compile_options(${LIBICSNEO_COMPILER_WARNINGS})
@@ -190,3 +191,7 @@ endif()
if(LIBICSNEO_BUILD_CPP_GPTP_EXAMPLE) if(LIBICSNEO_BUILD_CPP_GPTP_EXAMPLE)
add_subdirectory(cpp/gptp) add_subdirectory(cpp/gptp)
endif() endif()
if(LIBICSNEO_BUILD_CPP_ISO15765_LOOPBACK_EXAMPLE)
add_subdirectory(cpp/iso15765_loopback)
endif()
+1 -1
View File
@@ -378,7 +378,7 @@ static int configure_t1s_port(icsneoc2_device_t* device, icsneoc2_netid_t netid,
if(res != icsneoc2_error_success) return print_error_code("Failed to set T1S TX opportunity timer", res); if(res != icsneoc2_error_success) return print_error_code("Failed to set T1S TX opportunity timer", res);
res = icsneoc2_settings_t1s_burst_timer_set(device, netid, T1S_BURST_TIMER); res = icsneoc2_settings_t1s_burst_timer_set(device, netid, T1S_BURST_TIMER);
if(res != icsneoc2_error_success) return print_error_code("Failed to set T1S burst timer", res); if(res != icsneoc2_error_success) return print_error_code("Failed to set T1S burst timer", res);
res = icsneoc2_settings_t1s_max_burst_timer_for_set(device, netid, T1S_MAX_BURST); res = icsneoc2_settings_t1s_max_burst_set(device, netid, T1S_MAX_BURST);
if(res != icsneoc2_error_success) return print_error_code("Failed to set T1S max burst", res); if(res != icsneoc2_error_success) return print_error_code("Failed to set T1S max burst", res);
res = icsneoc2_settings_t1s_is_termination_enabled_for(device, netid, &termination); res = icsneoc2_settings_t1s_is_termination_enabled_for(device, netid, &termination);
@@ -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;
}
+1 -1
View File
@@ -77,7 +77,7 @@ int main(int, char**) {
cfg.setTxEnable(true); cfg.setTxEnable(true);
// Write config to the device // Write config to the device
if(!device->writeMACsecConfig(cfg)) { if(!device->writeMACsecConfig(cfg, icsneo::Network::NetID::AE_01)) {
std::cout << "Failed to write MACsec config" << std::endl; std::cout << "Failed to write MACsec config" << std::endl;
std::cout << icsneo::GetLastError() << std::endl; std::cout << icsneo::GetLastError() << std::endl;
return -1; return -1;
@@ -0,0 +1,264 @@
"""
Two-device ISO-TP loopback on CAN1.
Firmware segments the payload. This script sends it once and prints CAN1
frames with the ISO-TP PCI nibble decoded (SF/FF/CF/FC).
Wire CAN1 of two devices together (CANH/CANL, terminated).
python iso15765_loopback.py --raw
python iso15765_loopback.py --sf
python iso15765_loopback.py --both
"""
import argparse
import threading
import time
from datetime import timedelta
import icsneopy
CAN1 = icsneopy.Network.NetID.DWCAN_01
def pci_describe(data):
if not data:
return ""
pci_type = data[0] >> 4
pci_low = data[0] & 0x0F
if pci_type == 0x0:
if pci_low > 7 or len(data) < 1 + pci_low:
return ""
return f"SF len={pci_low}"
if pci_type == 0x1:
if len(data) < 8:
return ""
length = (pci_low << 8) | data[1]
if length < 8:
return ""
return f"FF len={length}"
if pci_type == 0x2:
if len(data) < 2:
return ""
return f"CF SN={pci_low}"
if pci_type == 0x3:
if len(data) < 3 or pci_low > 2:
return ""
fs_name = ("CTS", "WAIT", "OVFLW")[pci_low]
return f"FC FS={fs_name} BS={data[1]} STmin=0x{data[2]:02X}"
return ""
def print_api_result(what, ok):
line = f" {what}: {'OK' if ok else 'FAIL'}"
if not ok:
err = icsneopy.get_last_error()
if err.get_type() != icsneopy.APIEvent.Type.NoErrorFound:
line += f" [{err.describe()}]"
print(line)
def is_extended(arb_id):
return arb_id > 0x7FF
def make_args(tx_id, fc_id, payload, rx):
msg = icsneopy.Iso15765MessageArgs()
msg.tx_index = 0
msg.arb_id = icsneopy.Iso15765MessageArgs.ArbId(tx_id, is_extended(tx_id))
msg.flow_control_arb_id = icsneopy.Iso15765MessageArgs.ArbId(fc_id, is_extended(fc_id))
msg.flow_control_arb_id_mask = 0x1FFFFFFF if is_extended(tx_id) else 0x7FF
msg.is_can_fd = False
msg.is_brs_enabled = False
msg.tx_dl = 8
msg.padding_value = 0x00
msg.fs_timeout = 75
msg.fs_wait_timeout = 150
msg.cf_timeout = 150
msg.is_flow_control_enabled = rx
if payload:
msg.data = payload
return msg
def transmit_can(device, arb_id, data):
frame = icsneopy.CANMessage()
frame.network = icsneopy.Network(CAN1)
frame.arbid = arb_id
# RawMessage.data is vector<uint8_t>: a list of ints, not bytes.
frame.data = list(data)
frame.isExtended = is_extended(arb_id)
frame.isCANFD = False
ok = device.transmit(frame)
if not ok:
print_api_result("transmit CAN", ok)
return ok
class Sniffer:
def __init__(self, tag):
self.tag = tag
self.t0 = None
self.lock = threading.Lock()
def on_message(self, message):
if not isinstance(message, icsneopy.CANMessage):
return
if message.network.get_type() != icsneopy.Network.Type.CAN:
return
with self.lock:
if self.t0 is None:
self.t0 = message.timestamp
rel_ms = 0.0
if message.timestamp >= self.t0:
rel_ms = (message.timestamp - self.t0) / 1e6
direction = "TX" if message.transmitted else "RX"
width = 8 if is_extended(message.arbid) else 3
data = " ".join(f"{b:02X}" for b in message.data)
line = (
f" [{self.tag} {direction}] {rel_ms:8.3f} ms "
f"{message.network} 0x{message.arbid:0{width}X} "
f"[{len(message.data)}] {data}"
)
pci = pci_describe(message.data)
if pci:
line += f" {pci}"
print(line)
def open_and_online(device, baud, keep_baud):
print(f"Opening {device.describe()} ...")
if not device.open():
print_api_result("open", False)
return False
if not keep_baud and device.settings is not None:
net = icsneopy.Network(CAN1)
if not device.settings.set_baudrate(net, baud):
print_api_result("set_baudrate", False)
elif not device.settings.apply(True):
print_api_result("settings.apply(temporary)", False)
if not device.go_online():
print_api_result("go_online", False)
device.close()
return False
return True
def close_device(device):
if device is None:
return
device.iso15765_disable_all()
if device.is_online():
device.go_offline()
if device.is_open():
device.close()
def find_by_serial(devices, serial):
for device in devices:
if device.get_serial().lower() == serial.lower():
return device
return None
def parse_args():
parser = argparse.ArgumentParser(
description="Two Intrepid devices with CAN1 wired together (CANH/CANL, terminated)."
)
mode = parser.add_mutually_exclusive_group(required=True)
mode.add_argument("--raw", action="store_true", help="Raw CAN ping-pong (cable check)")
mode.add_argument("--sf", action="store_true", help="Firmware ISO-TP single-frame TX from tester")
mode.add_argument("--both", action="store_true", help="Firmware ISO-TP TX on tester, firmware flow-control on ECU")
parser.add_argument("--tester", default="", help="Tester (sender) serial. Optional if exactly two devices are found.")
parser.add_argument("--ecu", default="", help="ECU / peer serial. Optional if exactly two devices are found.")
parser.add_argument("--baud", type=int, default=500000, help="CAN1 baud, applied temporarily (default 500000)")
parser.add_argument("--keep-baud", action="store_true", help="Do not change device baud")
parser.add_argument("--tx-id", type=lambda s: int(s, 0), default=0x7E0, help="Tester ISO-TP CAN ID (default 0x7E0)")
parser.add_argument("--fc-id", type=lambda s: int(s, 0), default=0x7E8, help="Flow-control CAN ID (default 0x7E8)")
parser.add_argument("--bytes", type=int, default=None, help="ISO-TP payload size (sf default 5, both default 20)")
parser.add_argument("--listen-ms", type=int, default=2000, help="Time to listen after the action (default 2000)")
return parser.parse_args()
def main():
args = parse_args()
print(f"libicsneo {icsneopy.get_version()}")
devices = icsneopy.find_all_devices()
print(f"Found {len(devices)} device(s)")
for device in devices:
print(f" {device.describe()} serial={device.get_serial()}")
if len(devices) < 2:
raise SystemExit("Need two devices connected.")
if not args.tester and not args.ecu:
if len(devices) != 2:
raise SystemExit("More than two devices found; pass --tester and --ecu serials.")
tester, ecu = devices[0], devices[1]
print("No serials given; using first as tester, second as ECU.")
else:
if not args.tester or not args.ecu:
raise SystemExit("Pass both --tester and --ecu, or neither.")
tester = find_by_serial(devices, args.tester)
ecu = find_by_serial(devices, args.ecu)
if tester is None or ecu is None:
raise SystemExit("Could not match tester/ECU serials.")
payload_size = args.bytes if args.bytes is not None else (5 if args.sf else 20)
payload = [i & 0xFF for i in range(payload_size)]
print(f"Tester: {tester.describe()}")
print(f"ECU: {ecu.describe()}")
if not args.raw:
print(f"CAN1 TX 0x{args.tx_id:X} FC 0x{args.fc_id:X} payload {payload_size} bytes")
print()
network = icsneopy.Network(CAN1)
try:
if not open_and_online(tester, args.baud, args.keep_baud):
return 1
if not open_and_online(ecu, args.baud, args.keep_baud):
return 1
for device, sniffer in ((tester, Sniffer("TESTER")), (ecu, Sniffer("ECU "))):
callback = icsneopy.MessageCallback(sniffer.on_message, icsneopy.MessageFilter(CAN1))
device.add_message_callback(callback)
if args.raw:
print("Mode --raw: tester 0x123, then ECU 0x456")
transmit_can(tester, 0x123, [0x11, 0x22, 0x33, 0x44])
time.sleep(0.2)
transmit_can(ecu, 0x456, [0x55, 0x66, 0x77, 0x88])
elif args.sf:
print("Mode --sf: firmware ISO-TP single frame from tester")
if len(payload) > 7:
print(" warning: payload > 7 bytes will be a First Frame (no flow control in this mode)")
ok = tester.iso15765_enable(network)
print_api_result("tester iso15765_enable", ok)
msg = make_args(args.tx_id, args.fc_id, payload, rx=False)
ok = tester.iso15765_transmit_message(network, msg, timedelta(0))
print_api_result("tester iso15765_transmit_message", ok)
else:
print("Mode --both: firmware TX on tester, firmware flow-control on ECU")
ok = tester.iso15765_enable(network)
print_api_result("tester iso15765_enable", ok)
ok = ecu.iso15765_enable(network)
print_api_result("ECU iso15765_enable", ok)
msg = make_args(args.tx_id, args.fc_id, [], rx=True)
ok = ecu.iso15765_setup_rx_flow_control(network, msg)
print_api_result("ECU iso15765_setup_rx_flow_control", ok)
time.sleep(0.1)
msg = make_args(args.tx_id, args.fc_id, payload, rx=False)
ok = tester.iso15765_transmit_message(network, msg, timedelta(0))
print_api_result("tester iso15765_transmit_message", ok)
time.sleep(args.listen_ms / 1000.0)
finally:
close_device(tester)
close_device(ecu)
return 0
if __name__ == "__main__":
raise SystemExit(main())
+45
View File
@@ -0,0 +1,45 @@
import icsneopy
import time
#
# Main51 messages are device-originated notifications from the firmware's Main51 processor.
# This example filters for RX buffer overflow and TX FIFO overflow events.
#
def main51_filter():
devices = icsneopy.find_all_devices()
if len(devices) == 0:
print("no devices found")
return False
device = devices[0]
print(f"selected {device}")
def on_main51(message):
if not isinstance(message, icsneopy.Main51Message):
return
if message.command == icsneopy.Command.Main51RxBufferOverflow:
print("RX buffer overflow")
elif message.command == icsneopy.Command.Main51TxFifoOverflow:
print("TX FIFO overflow")
else:
print(f"Main51 command: {message.command}")
filter = icsneopy.Main51MessageFilter()
callback = icsneopy.MessageCallback(on_main51, filter)
device.add_message_callback(callback)
if not device.open():
print("unable to open device")
return False
if not device.go_online():
print("unable to go online")
return False
time.sleep(5)
return True
if __name__ == "__main__":
main51_filter()
+125 -25
View File
@@ -1,33 +1,133 @@
#ifndef _J2534_H #ifndef _J2534_H
#define _J2534_H #define _J2534_H
#include <cstdint>
namespace icsneo {
//J2534 Commands //J2534 Commands
#define J1534_NUM_PERIOD_TX_MSGS 128 #define J1534_NUM_PERIOD_TX_MSGS 128
#define J1534_NUM_PERIOD_RX_MSGS 128 #define J1534_NUM_PERIOD_RX_MSGS 128
#define J2534NVCMD_SetISJ2534 0
#define J2534NVCMD_SetISO5Baud 1 enum class J2534Command : uint8_t {
#define J2534NVCMD_SetISOFastInit 2 SetISJ2534 = 0,
#define J2534NVCMD_SetISOCheckSum 3 SetISO5Baud = 1,
#define J2534NVCMD_SetISO9141Parms 4 SetISOFastInit = 2,
#define J2534NVCMD_GetISO9141Parms 5 SetISOCheckSum = 3,
#define J2534NVCMD_ISO9141APIChkSum 6 SetISO9141Parms = 4,
#define J2534NVCMD_SetNetworkBaudRate 7 GetISO9141Parms = 5,
#define J2534NVCMD_GetNetworkBaudRate 8 ISO9141APIChkSum = 6,
#define J2534NVCMD_EnableTransmitEvent 9 SetNetworkBaudRate = 7,
#define J2534NVCMD_SetTransmitEvent 10 GetNetworkBaudRate = 8,
#define J2534NVCMD_BlueEnableStopFilters 11 EnableTransmitEvent = 9,
#define J2534NVCMD_Blue15765HWSupport 12 SetTransmitEvent = 10,
#define J2534NVCMD_GetTXBufferInfo 13 BlueEnableStopFilters = 11,
#define J2534NVCMD_GetEncryptionKey 14 Blue15765HWSupport = 12,
#define J2534NVCMD_SetMiscIOForVBATT 15 GetTXBufferInfo = 13,
#define J2534NVCMD_EnableISO_KW_Network 16 GetEncryptionKey = 14,
#define J2534NVCMD_SetJ1708CheckSum 17 SetMiscIOForVBATT = 15,
#define J2534NVCMD_GetTimestamp 18 EnableISO_KW_Network = 16,
#define J2534NVCMD_GetCANFDRate 19 SetJ1708CheckSum = 17,
#define J2534NVCMD_SetCANFDRate 20 GetTimestamp = 18,
#define J2534NVCMD_GetCANFDTermination 21 GetCANFDRate = 19,
#define J2534NVCMD_SetCANFDTermination 22 SetCANFDRate = 20,
#define J2534NVCMD_GetCANFDFormat 23 GetCANFDTermination = 21,
#define J2534NVCMD_SetCANFDFormat 24 SetCANFDTermination = 22,
GetCANFDFormat = 23,
SetCANFDFormat = 24
};
#pragma pack(push)
#pragma pack(1)
/**
* SubFrame Commands
*/
enum class J2534SubCommand : uint8_t {
Enable = 0,
SetupIso15765RxFilter = 1,
SetupIso15765TxMessageProperties = 2,
SetupIso15765TxMessageDataBytes = 3,
SetupCanRxFilter = 4,
SetupClearCanRxFilters = 5,
EnableFiltering = 6
};
typedef struct
{
uint16_t uiFilterMask0;
uint16_t uiFilterID0;
uint16_t uiFilterMask1;
uint16_t uiFilterID1;
uint16_t uiFilterMask2;
uint16_t uiFilterID2;
union {
/** Mask and value words if rx filter is datalink filter*/
struct
{
uint16_t uiFilterMask3;
uint16_t uiFilterID3;
uint16_t uiFilterMask4;
uint16_t uiFilterID4;
uint16_t uiFilterMask5;
uint16_t uiFilterID5;
uint16_t uiFilterMask6;
uint16_t uiFilterID6;
} datalink;
/** Mask and value bytes if rx filter is datalink filter*/
struct
{
uint8_t uiFilterMask_DB0;
uint8_t uiFilterMask_DB1;
uint8_t uiFilterID_DB0;
uint8_t uiFilterID_DB1;
uint8_t uiFilterMask_DB2;
uint8_t uiFilterMask_DB3;
uint8_t uiFilterID_DB2;
uint8_t uiFilterID_DB3;
uint8_t uiFilterMask_DB4;
uint8_t uiFilterMask_DB5;
uint8_t uiFilterID_DB4;
uint8_t uiFilterID_DB5;
uint8_t uiFilterMask_DB6;
uint8_t uiFilterMask_DB7;
uint8_t uiFilterID_DB6;
uint8_t uiFilterID_DB7;
} datalinkBytes;
/** Mask and value bytes if rx filter is Iso15765-2*/
struct
{
uint8_t uiFilterMask_DB0;
uint8_t uiFilterID_DB0;
uint8_t uiFilterMask_DB1;
uint8_t uiFilterID_DB1;
uint8_t uiFilterMask_DB2;
uint8_t uiFilterID_DB2;
uint8_t uiFilterMask_DB3;
uint8_t uiFilterID_DB3;
uint8_t uiFilterMask_DB4;
uint8_t uiFilterID_DB4;
uint8_t uiFilterMask_DB5;
uint8_t uiFilterID_DB5;
uint8_t uiFilterMask_DB6;
uint8_t uiFilterID_DB6;
uint8_t uiFilterMask_DB7;
uint8_t uiFilterID_DB7;
} iso15Bytes;
} args;
} MessageFilterBytes;
typedef struct
{
uint16_t idx;
uint16_t enabled;
uint16_t filterCount;
MessageFilterBytes fb;
uint16_t networkId;
} J2534_RxCanFilter;
#pragma pack(pop)
} // namespace icsneo
#endif #endif
+1
View File
@@ -126,6 +126,7 @@ public:
SettingNotAvaiableDevice = 0x2057, SettingNotAvaiableDevice = 0x2057,
DiskFormatNotSupported = 0x2058, DiskFormatNotSupported = 0x2058,
DiskFormatInvalidCount = 0x2059, DiskFormatInvalidCount = 0x2059,
TC10RequestFailed = 0x205A,
// Transport Events // Transport Events
FailedToRead = 0x3000, FailedToRead = 0x3000,
+4
View File
@@ -43,6 +43,7 @@ enum class Command : uint8_t {
GetLogicalDiskInfo = 0xBB, // Previously known as RED_CMD_GET_SDCARD_INFO GetLogicalDiskInfo = 0xBB, // Previously known as RED_CMD_GET_SDCARD_INFO
RequestStatusUpdate = 0xBC, RequestStatusUpdate = 0xBC,
ReadSettings = 0xC7, // Previously known as 3G_READ_SETTINGS_EX ReadSettings = 0xC7, // Previously known as 3G_READ_SETTINGS_EX
J2534Command = 0xD7, // Previously known as RED_CMD_J2534_EXTENSION
SetVBattMonitor = 0xDB, // Previously known as RED_CMD_CM_VBATT_MONITOR SetVBattMonitor = 0xDB, // Previously known as RED_CMD_CM_VBATT_MONITOR
RequestBitSmash = 0xDC, // Previously known as RED_CMD_CM_BITSMASH RequestBitSmash = 0xDC, // Previously known as RED_CMD_CM_BITSMASH
WiVICommand = 0xDD, // Previously known as RED_CMD_WIVI_COMM WiVICommand = 0xDD, // Previously known as RED_CMD_WIVI_COMM
@@ -73,8 +74,11 @@ enum class ExtendedCommand : uint16_t {
GetComponentVersions = 0x001A, GetComponentVersions = 0x001A,
SoftwareUpdate = 0x001B, SoftwareUpdate = 0x001B,
Reboot = 0x001C, Reboot = 0x001C,
ReadGenericAPIStatus = 0x001D,
SetRootFSEntryFlags = 0x0027, SetRootFSEntryFlags = 0x0027,
TransmitCoreminiMessage = 0x0028, TransmitCoreminiMessage = 0x0028,
ReadGenericAPIData = 0x002E,
WriteGenericAPICommand = 0x002F,
GenericBinaryInfo = 0x0030, GenericBinaryInfo = 0x0030,
LiveData = 0x0035, LiveData = 0x0035,
ExecuteSPIPortKeyOperation = 0x003C, ExecuteSPIPortKeyOperation = 0x003C,
+6
View File
@@ -9,6 +9,7 @@
#include <common/v1/proto_header.pb.h> #include <common/v1/proto_header.pb.h>
#include <commands/generic/v1/client_id.pb.h> #include <commands/generic/v1/client_id.pb.h>
#include <commands/network/v1/mutex.pb.h> #include <commands/network/v1/mutex.pb.h>
#include <settings/manufacturing/v1/mfg_config.pb.h>
#ifdef _WIN32 #ifdef _WIN32
#pragma warning(pop) #pragma warning(pop)
#endif #endif
@@ -36,6 +37,11 @@ struct IDLookup {
constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_UNSPECIFIED; constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_UNSPECIFIED;
}; };
template <>
struct IDLookup<settings::manufacturing::v1::MfgConfig> {
constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_MFG_CONFIG;
};
template <> template <>
struct IDLookup<commands::network::v1::NetworkMutex> { struct IDLookup<commands::network::v1::NetworkMutex> {
constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_NETWORK_MUTEX; constexpr static common::v1::ProtoId value = common::v1::ProtoId::PROTO_ID_NETWORK_MUTEX;
@@ -8,6 +8,7 @@
#include "icsneo/communication/packet.h" #include "icsneo/communication/packet.h"
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <optional>
namespace icsneo { namespace icsneo {
@@ -17,13 +18,16 @@ namespace icsneo {
#endif #endif
struct PhyMessage { struct PhyMessage {
bool Enabled; bool Enabled = false;
bool WriteEnable; bool WriteEnable = false;
bool Clause45Enable; bool Clause45Enable = false;
uint8_t BusIndex; uint8_t BusIndex = 0;
uint8_t Version; uint8_t Version = PhyPacketVersion;
// Unset on locally constructed messages; every decoded response sets the raw wire status.
// Ignored when sending. A value does not establish firmware error coverage.
std::optional<uint8_t> Status;
union { union {
Clause22Message Clause22; Clause22Message Clause22{};
Clause45Message Clause45; Clause45Message Clause45;
}; };
}; };
@@ -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 HasUpdatedResponderOnce = false;
bool BusRecovered = false; bool BusRecovered = false;
bool BreakOnly = false; bool BreakOnly = false;
bool WakeupRequest = false;
}; };
class LINMessage : public Frame { class LINMessage : public Frame {
@@ -45,7 +46,8 @@ public:
LIN_BREAK_ONLY = icsneoc2_lin_msg_type_break_only, LIN_BREAK_ONLY = icsneoc2_lin_msg_type_break_only,
LIN_SYNC_ONLY = icsneoc2_lin_msg_type_sync_only, LIN_SYNC_ONLY = icsneoc2_lin_msg_type_sync_only,
LIN_UPDATE_RESPONDER = icsneoc2_lin_msg_type_update_responder, 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); static void calcChecksum(LINMessage& message);
@@ -49,6 +49,9 @@ public:
ClientId = 0x8017, ClientId = 0x8017,
AllMACAddresses = 0x8018, AllMACAddresses = 0x8018,
SPIPortKeyOperation = 0x8019, SPIPortKeyOperation = 0x8019,
GenericAPIData = 0x8020,
GenericAPIStatus = 0x8021,
MfgConfig = 0x8022,
}; };
Message(Type t) : type(t) {} Message(Type t) : type(t) {}
@@ -0,0 +1,56 @@
#ifndef __MFGCONFIGMESSAGE_H_
#define __MFGCONFIGMESSAGE_H_
#ifdef __cplusplus
#include "icsneo/communication/message/message.h"
#include "icsneo/communication/message/allmacaddressesmessage.h"
#include "icsneo/device/chipid.h"
#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <vector>
namespace icsneo {
class MfgConfigMessage : public Message {
public:
struct MfgDate {
uint32_t day = 0;
uint32_t month = 0;
uint32_t year = 0;
};
struct VersionNumber {
uint32_t major = 0;
uint32_t minor = 0;
std::optional<uint32_t> release;
std::optional<uint32_t> build;
};
MfgConfigMessage() : Message(Message::Type::MfgConfig) {}
static std::shared_ptr<MfgConfigMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
static std::vector<uint8_t> EncodeArgumentsForGet();
std::optional<uint64_t> serialNumber;
std::optional<MfgDate> manufactureDate;
std::optional<VersionNumber> hardwareRev;
std::optional<uint8_t> productId;
std::optional<VersionNumber> bootloaderRev;
std::optional<std::string> usbDescriptor;
std::vector<MACAddress> macAddresses;
std::optional<std::string> pcbSerial;
std::optional<ChipID> chipId;
std::optional<uint64_t> imei;
std::optional<uint8_t> parentProductId;
std::optional<VersionNumber> softwareVersionLock;
};
} // namespace icsneo
#endif // __cplusplus
#endif // __MFGCONFIGMESSAGE_H_
@@ -65,7 +65,7 @@ struct PhyRegisterPacket_t {
#pragma pack(pop) #pragma pack(pop)
static constexpr size_t MaxPhyEntries = 128u; static constexpr size_t MaxPhyEntries = 128u;
static constexpr size_t MaxBytesPhyEntries = MaxPhyEntries * sizeof(PhyRegisterHeader_t); static constexpr size_t MaxBytesPhyEntries = MaxPhyEntries * sizeof(PhyRegisterPacket_t);
static constexpr uint8_t PhyPacketVersion = 1u; static constexpr uint8_t PhyPacketVersion = 1u;
static constexpr uint8_t FiveBits = 0x1Fu; static constexpr uint8_t FiveBits = 0x1Fu;
@@ -47,7 +47,8 @@ struct HardwareLINPacket {
uint16_t ResponderByteFerr : 1; //Framing error in one of our responder bytes. uint16_t ResponderByteFerr : 1; //Framing error in one of our responder bytes.
uint16_t TxAborted : 1;//!< This transmit was aborted. uint16_t TxAborted : 1;//!< This transmit was aborted.
uint16_t BreakOnly : 1; uint16_t BreakOnly : 1;
uint16_t : 2; uint16_t WakeupRequest : 1; //!< LIN wakeup pulse.
uint16_t : 1;
} CoreMiniBitsLIN; } CoreMiniBitsLIN;
uint8_t data[8]; uint8_t data[8];
-2
View File
@@ -150,7 +150,6 @@ private:
uint8_t maxSecY; uint8_t maxSecY;
uint8_t maxSa; uint8_t maxSa;
uint8_t maxRule; uint8_t maxRule;
uint16_t binIndex;
DeviceType type; DeviceType type;
std::vector<MACsecRxRule> rxRule; std::vector<MACsecRxRule> rxRule;
@@ -205,7 +204,6 @@ public:
void clear(); void clear();
std::vector<uint8_t> serialize() const; std::vector<uint8_t> serialize() const;
operator bool() const; operator bool() const;
uint16_t getBinIndex() const;
DeviceType getType() const; DeviceType getType() const;
uint8_t getMaxNumRule() const; uint8_t getMaxNumRule() const;
uint8_t getMaxNumSecY() const; uint8_t getMaxNumSecY() const;
+3 -2
View File
@@ -91,9 +91,10 @@ struct FlashPhase : public BootloaderPhase {
bool authenticate = true; bool authenticate = true;
bool encrypt = true; bool encrypt = true;
bool checkOutOfDate = true; bool checkOutOfDate = true;
uint8_t slot = UINT8_MAX;
FlashPhase(ChipID chip, BootloaderCommunication comm, bool authenticate = true, bool encrypt = true, bool checkOutOfDate = true) FlashPhase(ChipID chip, BootloaderCommunication comm, bool authenticate = true, bool encrypt = true, bool checkOutOfDate = true, uint8_t slot = UINT8_MAX)
: chip(chip), comm(comm), authenticate(authenticate), encrypt(encrypt), checkOutOfDate(checkOutOfDate) {} : chip(chip), comm(comm), authenticate(authenticate), encrypt(encrypt), checkOutOfDate(checkOutOfDate), slot(slot) {}
}; };
enum class BootloaderSetting { enum class BootloaderSetting {
+1 -1
View File
@@ -138,7 +138,7 @@ enum class ChipID : icsneoc2_chip_id_t {
RADMOONT1S_ZCHIP = icsneoc2_chip_id_radmoont1s_zchip, RADMOONT1S_ZCHIP = icsneoc2_chip_id_radmoont1s_zchip,
RADGigastar2_ZYNQ = icsneoc2_chip_id_radgigastar2_zynq, RADGigastar2_ZYNQ = icsneoc2_chip_id_radgigastar2_zynq,
SFPModule_ent11100_MCHIP = icsneoc2_chip_id_sfpmodule_ent11100_mchip, SFPModule_ent11100_MCHIP = icsneoc2_chip_id_sfpmodule_ent11100_mchip,
RADGemini_MCHIP = icsneoc2_chip_id_radgemini_mchip, RADArgos_MCHIP = icsneoc2_chip_id_radargos_mchip,
Invalid = icsneoc2_chip_id_invalid Invalid = icsneoc2_chip_id_invalid
}; };
+39 -2
View File
@@ -12,6 +12,7 @@
#include <type_traits> #include <type_traits>
#include <optional> #include <optional>
#include <unordered_map> #include <unordered_map>
#include <map>
#include <set> #include <set>
#include <unordered_set> #include <unordered_set>
#include <chrono> #include <chrono>
@@ -47,6 +48,8 @@
#include "icsneo/communication/message/livedatamessage.h" #include "icsneo/communication/message/livedatamessage.h"
#include "icsneo/communication/message/tc10statusmessage.h" #include "icsneo/communication/message/tc10statusmessage.h"
#include "icsneo/communication/message/spiportkeymessage.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/core/macseccfg.h"
#include "icsneo/communication/packet/genericbinarystatuspacket.h" #include "icsneo/communication/packet/genericbinarystatuspacket.h"
#include "icsneo/communication/packet/livedatapacket.h" #include "icsneo/communication/packet/livedatapacket.h"
@@ -61,6 +64,9 @@
#include "icsneo/communication/message/gptpstatusmessage.h" #include "icsneo/communication/message/gptpstatusmessage.h"
#include "icsneo/communication/message/networkmutexmessage.h" #include "icsneo/communication/message/networkmutexmessage.h"
#include "icsneo/communication/message/allmacaddressesmessage.h" #include "icsneo/communication/message/allmacaddressesmessage.h"
#include "icsneo/communication/message/mfgconfigmessage.h"
#include "icsneo/communication/message/iso15765message.h"
#include "icsneo/J2534.h"
#define ICSNEO_FINDABLE_DEVICE_BASE(className, type) \ #define ICSNEO_FINDABLE_DEVICE_BASE(className, type) \
static constexpr DeviceType::Enum DEVICE_TYPE = type; \ static constexpr DeviceType::Enum DEVICE_TYPE = type; \
@@ -145,7 +151,7 @@ public:
RADMoonT1S = 56, RADMoonT1S = 56,
RADGigastar2 = 57, RADGigastar2 = 57,
SFPModule_ent11100 = 58, SFPModule_ent11100 = 58,
RADGemini = 60, RADArgos = 60,
}; };
virtual ProductID getProductID() const = 0; virtual ProductID getProductID() const = 0;
@@ -343,6 +349,7 @@ public:
virtual Network getNetworkByNumber(Network::Type, size_t) const; virtual Network getNetworkByNumber(Network::Type, size_t) const;
std::shared_ptr<HardwareInfo> getHardwareInfo(std::chrono::milliseconds timeout = std::chrono::milliseconds(100)); std::shared_ptr<HardwareInfo> getHardwareInfo(std::chrono::milliseconds timeout = std::chrono::milliseconds(100));
std::shared_ptr<MfgConfigMessage> getMfgConfig();
/** /**
@@ -891,7 +898,8 @@ public:
std::optional<GPTPStatus> getGPTPStatus(std::chrono::milliseconds timeout = std::chrono::milliseconds(100)); std::optional<GPTPStatus> getGPTPStatus(std::chrono::milliseconds timeout = std::chrono::milliseconds(100));
/* MACsec support */ /* MACsec support */
virtual bool writeMACsecConfig(const MACsecConfig& cfg); std::vector<Network> getMACsecNetworks() const;
bool writeMACsecConfig(const MACsecConfig& cfg, Network::NetID network);
std::shared_ptr<DeviceExtension> getExtension(const std::string& name) const; std::shared_ptr<DeviceExtension> getExtension(const std::string& name) const;
@@ -905,7 +913,19 @@ public:
void stopHeartbeat(); void stopHeartbeat();
void restartHeartbeat(); void restartHeartbeat();
bool iso15765Enable(const Network& network);
bool iso15765DisableAll(void);
bool iso15765TransmitMessage(const Network& network, const Iso15765MessageArgs& msg, const std::chrono::milliseconds& timeout);
bool iso15765SetupRxFlowControl(const Network& network, const Iso15765MessageArgs& msg);
protected: protected:
using MACsecNetworkMap = std::map<Network::NetID, uint16_t>;
virtual const MACsecNetworkMap& getMACsecNetworkMap() const {
static const MACsecNetworkMap networks;
return networks;
}
bool online = false; bool online = false;
int messagePollingCallbackID = 0; int messagePollingCallbackID = 0;
int internalHandlerCallbackID = 0; int internalHandlerCallbackID = 0;
@@ -1173,6 +1193,23 @@ private:
bool enableNetworkCommunication(bool enable, uint32_t timeout = 0); bool enableNetworkCommunication(bool enable, uint32_t timeout = 0);
bool J2534_Transaction(const Network& network, J2534CommandMessage&& msg, const std::chrono::milliseconds& timeout);
bool J2534_ClearRxFilters(const Network& network);
bool J2534_SetupCanRxFilter(const Network& network, const J2534_RxCanFilter& rxCanFilter);
bool J2534_EnableFiltering(const Network& network, const bool enable);
bool J2534_EnableIso15765(const Network& network, const bool enable);
bool J2534_ClearRxFilter(const Network& network, unsigned int iIndex);
bool J2534_EnableFirmwareUsbPassFilters(const Network& network, const bool enable);
struct NetworkHash {
size_t operator()(const Network& x) const {
return (size_t)x.getNetID();
}
};
std::unordered_map<Network, bool, NetworkHash> iso15765FirmwareEnabled;
// Keeponline (keepalive for online) // Keeponline (keepalive for online)
std::unique_ptr<Periodic> keeponline; std::unique_ptr<Periodic> keeponline;
std::unique_ptr<Heartbeat> heartbeat; std::unique_ptr<Heartbeat> heartbeat;
+4 -4
View File
@@ -62,7 +62,7 @@ public:
RADGigastar2 = icsneoc2_devicetype_rad_gigastar2, RADGigastar2 = icsneoc2_devicetype_rad_gigastar2,
FIRE3_T1S_LIN = icsneoc2_devicetype_fire3_t1s_lin, FIRE3_T1S_LIN = icsneoc2_devicetype_fire3_t1s_lin,
FIRE3_T1S_SENT = icsneoc2_devicetype_fire3_t1s_sent, FIRE3_T1S_SENT = icsneoc2_devicetype_fire3_t1s_sent,
RADGemini = icsneoc2_devicetype_rad_gemini, RADArgos = icsneoc2_devicetype_rad_argos,
RED = icsneoc2_devicetype_red, RED = icsneoc2_devicetype_red,
ECU = icsneoc2_devicetype_ecu, ECU = icsneoc2_devicetype_ecu,
IEVB = icsneoc2_devicetype_ievb, IEVB = icsneoc2_devicetype_ievb,
@@ -153,8 +153,8 @@ public:
return "RAD-EpsilonXL"; return "RAD-EpsilonXL";
case RADMoon3: case RADMoon3:
return "RAD-Moon 3"; return "RAD-Moon 3";
case RADGemini: case RADArgos:
return "RAD-Gemini"; return "RAD-Argos";
case RADComet2: case RADComet2:
return "RAD-Comet 2"; return "RAD-Comet 2";
case RED: case RED:
@@ -281,7 +281,7 @@ private:
#define ICSNEO_DEVICETYPE_RADGIGASTAR2 ((devicetype_t)icsneoc2_devicetype_rad_gigastar2) #define ICSNEO_DEVICETYPE_RADGIGASTAR2 ((devicetype_t)icsneoc2_devicetype_rad_gigastar2)
#define ICSNEO_DEVICETYPE_FIRE3_T1S_LIN ((devicetype_t)icsneoc2_devicetype_fire3_t1s_lin) #define ICSNEO_DEVICETYPE_FIRE3_T1S_LIN ((devicetype_t)icsneoc2_devicetype_fire3_t1s_lin)
#define ICSNEO_DEVICETYPE_FIRE3_T1S_SENT ((devicetype_t)icsneoc2_devicetype_fire3_t1s_sent) #define ICSNEO_DEVICETYPE_FIRE3_T1S_SENT ((devicetype_t)icsneoc2_devicetype_fire3_t1s_sent)
#define ICSNEO_DEVICETYPE_RADGEMINI ((devicetype_t)icsneoc2_devicetype_rad_gemini) #define ICSNEO_DEVICETYPE_RADARGOS ((devicetype_t)icsneoc2_devicetype_rad_argos)
#define ICSNEO_DEVICETYPE_RED ((devicetype_t)icsneoc2_devicetype_red) #define ICSNEO_DEVICETYPE_RED ((devicetype_t)icsneoc2_devicetype_red)
#define ICSNEO_DEVICETYPE_ECU ((devicetype_t)icsneoc2_devicetype_ecu) #define ICSNEO_DEVICETYPE_ECU ((devicetype_t)icsneoc2_devicetype_ecu)
#define ICSNEO_DEVICETYPE_IEVB ((devicetype_t)icsneoc2_devicetype_ievb) #define ICSNEO_DEVICETYPE_IEVB ((devicetype_t)icsneoc2_devicetype_ievb)
+48 -137
View File
@@ -1205,143 +1205,32 @@ public:
return std::nullopt; return std::nullopt;
} }
virtual std::optional<bool> isT1SPLCAEnabledFor(Network net) const { // 10BASE-T1S. Devices expose a network by overriding getT1SSettingsFor / getT1SSettingsExtFor.
(void)net; // Every field in the mapped struct is readable; a null accessor means the network has no T1S block.
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); std::optional<bool> isT1SPLCAEnabledFor(Network net) const;
return std::nullopt; bool setT1SPLCAFor(Network net, bool enable);
} std::optional<uint8_t> getT1SLocalIDFor(Network net) const;
bool setT1SLocalIDFor(Network net, uint8_t id);
virtual bool setT1SPLCAFor(Network net, bool enable) { std::optional<uint8_t> getT1SMaxNodesFor(Network net) const;
(void)net; (void)enable; bool setT1SMaxNodesFor(Network net, uint8_t nodes);
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); std::optional<uint8_t> getT1STxOppTimerFor(Network net) const;
return false; bool setT1STxOppTimerFor(Network net, uint8_t timer);
} std::optional<uint8_t> getT1SMaxBurstFor(Network net) const;
bool setT1SMaxBurstFor(Network net, uint8_t burst);
virtual std::optional<uint8_t> getT1SLocalIDFor(Network net) const { std::optional<uint8_t> getT1SBurstTimerFor(Network net) const;
(void)net; bool setT1SBurstTimerFor(Network net, uint8_t timer);
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); std::optional<uint8_t> getT1SLocalIDAlternateFor(Network net) const;
return std::nullopt; bool setT1SLocalIDAlternateFor(Network net, uint8_t id);
} std::optional<bool> isT1STerminationEnabledFor(Network net) const;
bool setT1STerminationFor(Network net, bool enable);
virtual bool setT1SLocalIDFor(Network net, uint8_t id) { std::optional<bool> isT1SBusDecodingBeaconsEnabledFor(Network net) const;
(void)net; (void)id; bool setT1SBusDecodingBeaconsFor(Network net, bool enable);
return false; std::optional<bool> isT1SBusDecodingAllEnabledFor(Network net) const;
} bool setT1SBusDecodingAllFor(Network net, bool enable);
std::optional<uint8_t> getT1SMultiIDEnableMaskFor(Network net) const;
virtual std::optional<uint8_t> getT1SMaxNodesFor(Network net) const { bool setT1SMultiIDEnableMaskFor(Network net, uint8_t mask);
(void)net; std::optional<uint8_t> getT1SMultiIDFor(Network net, uint8_t index) const;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); bool setT1SMultiIDFor(Network net, uint8_t index, uint8_t id);
return std::nullopt;
}
virtual bool setT1SMaxNodesFor(Network net, uint8_t nodes) {
(void)net; (void)nodes;
return false;
}
virtual std::optional<uint8_t> getT1STxOppTimerFor(Network net) const {
(void)net;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return std::nullopt;
}
virtual bool setT1STxOppTimerFor(Network net, uint8_t timer) {
(void)net; (void)timer;
return false;
}
virtual std::optional<uint8_t> getT1SMaxBurstFor(Network net) const {
(void)net;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return std::nullopt;
}
virtual bool setT1SMaxBurstFor(Network net, uint8_t burst) {
(void)net; (void)burst;
return false;
}
virtual std::optional<uint8_t> getT1SBurstTimerFor(Network net) const {
(void)net;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return std::nullopt;
}
virtual bool setT1SBurstTimerFor(Network net, uint8_t timer) {
(void)net; (void)timer;
return false;
}
virtual std::optional<uint8_t> getT1SLocalIDAlternateFor(Network net) const {
(void)net;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return std::nullopt;
}
virtual bool setT1SLocalIDAlternateFor(Network net, uint8_t id) {
(void)net; (void)id;
return false;
}
virtual std::optional<bool> isT1STerminationEnabledFor(Network net) const {
(void)net;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return std::nullopt;
}
virtual bool setT1STerminationFor(Network net, bool enable) {
(void)net; (void)enable;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return false;
}
virtual std::optional<bool> isT1SBusDecodingBeaconsEnabledFor(Network net) const {
(void)net;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return std::nullopt;
}
virtual bool setT1SBusDecodingBeaconsFor(Network net, bool enable) {
(void)net; (void)enable;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return false;
}
virtual std::optional<bool> isT1SBusDecodingAllEnabledFor(Network net) const {
(void)net;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return std::nullopt;
}
virtual bool setT1SBusDecodingAllFor(Network net, bool enable) {
(void)net; (void)enable;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return false;
}
virtual std::optional<uint8_t> getT1SMultiIDEnableMaskFor(Network net) const {
(void)net;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return std::nullopt;
}
virtual bool setT1SMultiIDEnableMaskFor(Network net, uint8_t mask) {
(void)net; (void)mask;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return false;
}
virtual std::optional<uint8_t> getT1SMultiIDFor(Network net, uint8_t index) const {
(void)net; (void)index;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return std::nullopt;
}
virtual bool setT1SMultiIDFor(Network net, uint8_t index, uint8_t id) {
(void)net; (void)index; (void)id;
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
return false;
}
virtual std::optional<bool> isPerfTestEnabled() const { virtual std::optional<bool> isPerfTestEnabled() const {
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning); report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::EventWarning);
@@ -1427,6 +1316,28 @@ protected:
return reinterpret_cast<ICSNEO_UNALIGNED(uint64_t*)>((void*)(settings.data() + (offset - settingsInDeviceRAM.data()))); return reinterpret_cast<ICSNEO_UNALIGNED(uint64_t*)>((void*)(settings.data() + (offset - settingsInDeviceRAM.data())));
} }
// Pointer into the device RAM image. Override per device. Unknown networks return nullptr
// and do not report; the public T1S methods report SettingNotAvaiableDevice.
virtual const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const { (void)net; return nullptr; }
ETHERNET10T1S_SETTINGS* getMutableT1SSettingsFor(Network net) {
if(disabled || readonly)
return nullptr;
const uint8_t* offset = reinterpret_cast<const uint8_t*>(getT1SSettingsFor(net));
if(offset == nullptr)
return nullptr;
return reinterpret_cast<ETHERNET10T1S_SETTINGS*>(settings.data() + (offset - settingsInDeviceRAM.data()));
}
virtual const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const { (void)net; return nullptr; }
ETHERNET10T1S_SETTINGS_EXT* getMutableT1SSettingsExtFor(Network net) {
if(disabled || readonly)
return nullptr;
const uint8_t* offset = reinterpret_cast<const uint8_t*>(getT1SSettingsExtFor(net));
if(offset == nullptr)
return nullptr;
return reinterpret_cast<ETHERNET10T1S_SETTINGS_EXT*>(settings.data() + (offset - settingsInDeviceRAM.data()));
}
static bool SetNetworkEnabled(uint64_t* bitfields, size_t count, uint64_t networkID) { static bool SetNetworkEnabled(uint64_t* bitfields, size_t count, uint64_t networkID) {
const size_t index = networkID / 64; const size_t index = networkID / 64;
const size_t offset = networkID & 0x3F; const size_t offset = networkID & 0x3F;
@@ -132,9 +132,8 @@ protected:
virtual void setupExtensions() override { virtual void setupExtensions() override {
std::vector<Network> flexRayControllers; std::vector<Network> flexRayControllers;
flexRayControllers.push_back(Network::NetID::FLEXRAY_01); flexRayControllers.push_back(Network::NetID::FLEXRAY_01);
flexRayControllers.push_back(Network::NetID::FLEXRAY_01); flexRayControllers.push_back(Network::NetID::FLEXRAY_02);
addExtension(std::make_shared<FlexRay::Extension>(*this, flexRayControllers)); addExtension(std::make_shared<FlexRay::Extension>(*this, flexRayControllers));
} }
virtual std::vector<std::shared_ptr<FlexRay::Controller>> getFlexRayControllers() const override { virtual std::vector<std::shared_ptr<FlexRay::Controller>> getFlexRayControllers() const override {
@@ -269,215 +269,6 @@ public:
} }
} }
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA) != 0);
}
bool setT1SPLCAFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
return true;
}
std::optional<uint8_t> getT1SLocalIDFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->local_id);
}
bool setT1SLocalIDFor(Network net, uint8_t id) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->local_id = id;
return true;
}
std::optional<uint8_t> getT1SMaxNodesFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->max_num_nodes);
}
bool setT1SMaxNodesFor(Network net, uint8_t nodes) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->max_num_nodes = nodes;
return true;
}
std::optional<uint8_t> getT1STxOppTimerFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->to_timer);
}
bool setT1STxOppTimerFor(Network net, uint8_t timer) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->to_timer = timer;
return true;
}
std::optional<uint8_t> getT1SMaxBurstFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->max_burst_count);
}
bool setT1SMaxBurstFor(Network net, uint8_t burst) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->max_burst_count = burst;
return true;
}
std::optional<uint8_t> getT1SBurstTimerFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->burst_timer);
}
bool setT1SBurstTimerFor(Network net, uint8_t timer) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->burst_timer = timer;
return true;
}
std::optional<uint8_t> getT1SLocalIDAlternateFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->local_id_alternate);
}
bool setT1SLocalIDAlternateFor(Network net, uint8_t id) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->local_id_alternate = id;
return true;
}
std::optional<bool> isT1SBusDecodingBeaconsEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS) != 0);
}
bool setT1SBusDecodingBeaconsFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS;
return true;
}
std::optional<bool> isT1SBusDecodingAllEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL) != 0);
}
bool setT1SBusDecodingAllFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL;
return true;
}
std::optional<uint8_t> getT1SMultiIDEnableMaskFor(Network net) const override {
const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return std::nullopt;
return std::make_optional(t1sExt->enable_multi_id);
}
bool setT1SMultiIDEnableMaskFor(Network net, uint8_t mask) override {
ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return false;
t1sExt->enable_multi_id = mask;
return true;
}
std::optional<uint8_t> getT1SMultiIDFor(Network net, uint8_t index) const override {
const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return std::nullopt;
if(index >= 7) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return std::nullopt;
}
return std::make_optional(t1sExt->multi_id[index]);
}
bool setT1SMultiIDFor(Network net, uint8_t index, uint8_t id) override {
ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return false;
if(index >= 7) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
t1sExt->multi_id[index] = id;
return true;
}
std::optional<bool> isPerfTestEnabled() const override { std::optional<bool> isPerfTestEnabled() const override {
auto cfg = getStructurePointer<neovifire3t1slin_settings_t>(); auto cfg = getStructurePointer<neovifire3t1slin_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -496,11 +287,10 @@ public:
} }
private: private:
const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const { const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const override {
auto cfg = getStructurePointer<neovifire3t1slin_settings_t>(); auto cfg = getStructurePointer<neovifire3t1slin_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
return nullptr; return nullptr;
switch(net.getNetID()) { switch(net.getNetID()) {
case Network::NetID::AE_01: return &(cfg->t1s1); case Network::NetID::AE_01: return &(cfg->t1s1);
case Network::NetID::AE_02: return &(cfg->t1s2); case Network::NetID::AE_02: return &(cfg->t1s2);
@@ -510,69 +300,24 @@ private:
case Network::NetID::AE_06: return &(cfg->t1s6); case Network::NetID::AE_06: return &(cfg->t1s6);
case Network::NetID::AE_07: return &(cfg->t1s7); case Network::NetID::AE_07: return &(cfg->t1s7);
case Network::NetID::AE_08: return &(cfg->t1s8); case Network::NetID::AE_08: return &(cfg->t1s8);
default: default: return nullptr;
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
} }
} }
ETHERNET10T1S_SETTINGS* getMutableT1SSettingsFor(Network net) { const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const override {
auto cfg = getMutableStructurePointer<neovifire3t1slin_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::AE_01: return &(cfg->t1s1);
case Network::NetID::AE_02: return &(cfg->t1s2);
case Network::NetID::AE_03: return &(cfg->t1s3);
case Network::NetID::AE_04: return &(cfg->t1s4);
case Network::NetID::AE_05: return &(cfg->t1s5);
case Network::NetID::AE_06: return &(cfg->t1s6);
case Network::NetID::AE_07: return &(cfg->t1s7);
case Network::NetID::AE_08: return &(cfg->t1s8);
default:
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
}
}
const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const {
auto cfg = getStructurePointer<neovifire3t1slin_settings_t>(); auto cfg = getStructurePointer<neovifire3t1slin_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
return nullptr; return nullptr;
switch(net.getNetID()) { switch(net.getNetID()) {
case Network::NetID::AE_03: return &(cfg->t1s1Ext); case Network::NetID::AE_01: return &(cfg->t1s1Ext);
case Network::NetID::AE_04: return &(cfg->t1s2Ext); case Network::NetID::AE_02: return &(cfg->t1s2Ext);
case Network::NetID::AE_05: return &(cfg->t1s3Ext); case Network::NetID::AE_03: return &(cfg->t1s3Ext);
case Network::NetID::AE_06: return &(cfg->t1s4Ext); case Network::NetID::AE_04: return &(cfg->t1s4Ext);
case Network::NetID::AE_07: return &(cfg->t1s5Ext); case Network::NetID::AE_05: return &(cfg->t1s5Ext);
case Network::NetID::AE_08: return &(cfg->t1s6Ext); case Network::NetID::AE_06: return &(cfg->t1s6Ext);
case Network::NetID::AE_09: return &(cfg->t1s7Ext); case Network::NetID::AE_07: return &(cfg->t1s7Ext);
case Network::NetID::AE_10: return &(cfg->t1s8Ext); case Network::NetID::AE_08: return &(cfg->t1s8Ext);
default: default: return nullptr;
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
}
}
ETHERNET10T1S_SETTINGS_EXT* getMutableT1SSettingsExtFor(Network net) {
auto cfg = getMutableStructurePointer<neovifire3t1slin_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::AE_03: return &(cfg->t1s1Ext);
case Network::NetID::AE_04: return &(cfg->t1s2Ext);
case Network::NetID::AE_05: return &(cfg->t1s3Ext);
case Network::NetID::AE_06: return &(cfg->t1s4Ext);
case Network::NetID::AE_07: return &(cfg->t1s5Ext);
case Network::NetID::AE_08: return &(cfg->t1s6Ext);
case Network::NetID::AE_09: return &(cfg->t1s7Ext);
case Network::NetID::AE_10: return &(cfg->t1s8Ext);
default:
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
} }
} }
@@ -1,19 +1,19 @@
#ifndef __RADGEMINI_H_ #ifndef __RADARGOS_H_
#define __RADGEMINI_H_ #define __RADARGOS_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/radgemini/radgeminisettings.h" #include "icsneo/device/tree/radargos/radargossettings.h"
namespace icsneo { namespace icsneo {
class RADGemini : public Device { class RADArgos : public Device {
public: public:
// Serial numbers start with GE // Serial numbers start with GE
// USB PID is 0x110E, standard driver is CDCACM // USB PID is 0x110E, standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(RADGemini, DeviceType::RADGemini, "GE"); ICSNEO_FINDABLE_DEVICE(RADArgos, DeviceType::RADArgos, "GE");
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
@@ -28,11 +28,11 @@ public:
bool supportsTC10() const override { return true; } bool supportsTC10() const override { return true; }
ProductID getProductID() const override { return ProductID::RADGemini; } ProductID getProductID() const override { return ProductID::RADArgos; }
const std::vector<ChipInfo>& getChipInfo() const override { const std::vector<ChipInfo>& getChipInfo() const override {
static std::vector<ChipInfo> chips = { static std::vector<ChipInfo> chips = {
{ChipID::RADGemini_MCHIP, true, "MCHIP", "radgemini_mchip_ief", 0, FirmwareType::IEF}, {ChipID::RADArgos_MCHIP, true, "MCHIP", "radargos_mchip_ief", 0, FirmwareType::IEF},
}; };
return chips; return chips;
} }
@@ -40,15 +40,15 @@ public:
BootloaderPipeline getBootloader() override { BootloaderPipeline getBootloader() override {
return BootloaderPipeline() return BootloaderPipeline()
.add<EnterBootloaderPhase>() .add<EnterBootloaderPhase>()
.add<FlashPhase>(ChipID::RADGemini_MCHIP, BootloaderCommunication::RED) .add<FlashPhase>(ChipID::RADArgos_MCHIP, BootloaderCommunication::RED)
.add<EnterApplicationPhase>(ChipID::RADGemini_MCHIP) .add<EnterApplicationPhase>(ChipID::RADArgos_MCHIP)
.add<ReconnectPhase>() .add<ReconnectPhase>()
.add<WaitPhase>(std::chrono::milliseconds(3000)); .add<WaitPhase>(std::chrono::milliseconds(3000));
} }
protected: protected:
RADGemini(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { RADArgos(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADGeminiSettings>(makeDriver); initialize<RADArgosSettings>(makeDriver);
} }
void setupPacketizer(Packetizer& packetizer) override { void setupPacketizer(Packetizer& packetizer) override {
@@ -74,4 +74,4 @@ protected:
#endif // __cplusplus #endif // __cplusplus
#endif // __RADGEMINI_H_ #endif // __RADARGOS_H_
@@ -1,5 +1,5 @@
#ifndef LIBICSNEO_RADGEMINISETTINGS_H #ifndef LIBICSNEO_RADARGOSSETTINGS_H
#define LIBICSNEO_RADGEMINISETTINGS_H #define LIBICSNEO_RADARGOSSETTINGS_H
#include <stdint.h> #include <stdint.h>
#include "icsneo/device/idevicesettings.h" #include "icsneo/device/idevicesettings.h"
@@ -31,18 +31,18 @@ typedef struct {
uint16_t enableLatencyTest : 1; uint16_t enableLatencyTest : 1;
uint16_t reserved : 15; uint16_t reserved : 15;
} flags; // 2 } flags; // 2
} radgemini_settings_t; } radargos_settings_t;
#pragma pack(pop) #pragma pack(pop)
#ifdef __cplusplus #ifdef __cplusplus
static_assert(sizeof(radgemini_settings_t) == 86, "RADGemini settings size mismatch"); static_assert(sizeof(radargos_settings_t) == 86, "RADArgos settings size mismatch");
#include <iostream> #include <iostream>
class RADGeminiSettings : public IDeviceSettings { class RADArgosSettings : public IDeviceSettings {
public: public:
RADGeminiSettings(Device* device) : IDeviceSettings(device, sizeof(radgemini_settings_t)) {} RADArgosSettings(Device* device) : IDeviceSettings(device, sizeof(radargos_settings_t)) {}
}; };
} }
@@ -50,4 +50,4 @@ public:
#endif // __cplusplus #endif // __cplusplus
#endif // LIBICSNEO_RADGEMINISETTINGS_H #endif // LIBICSNEO_RADARGOSSETTINGS_H
@@ -70,6 +70,13 @@ public:
} }
protected: protected:
const MACsecNetworkMap& getMACsecNetworkMap() const override {
static const MACsecNetworkMap networks = {
{Network::NetID::AE_01, 0},
};
return networks;
}
RADComet2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { RADComet2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADComet2Settings, Disk::NeoMemoryDiskDriver, Disk::NeoMemoryDiskDriver>(makeDriver); initialize<RADComet2Settings, Disk::NeoMemoryDiskDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
} }
@@ -118,131 +118,16 @@ public:
} }
} }
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override { const LIN_SETTINGS* getLINSettingsFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); auto cfg = getStructurePointer<radcomet2_settings_t>();
if(t1s == nullptr) if(cfg == nullptr)
return std::nullopt; return nullptr;
switch(net.getNetID()) {
return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA) != 0); case Network::NetID::LIN_01:
} return &(cfg->lin1);
default:
bool setT1SPLCAFor(Network net, bool enable) override { return nullptr;
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net); }
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
return true;
}
std::optional<uint8_t> getT1SLocalIDFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->local_id);
}
bool setT1SLocalIDFor(Network net, uint8_t id) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->local_id = id;
return true;
}
std::optional<uint8_t> getT1SMaxNodesFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->max_num_nodes);
}
bool setT1SMaxNodesFor(Network net, uint8_t nodes) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->max_num_nodes = nodes;
return true;
}
std::optional<uint8_t> getT1STxOppTimerFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->to_timer);
}
bool setT1STxOppTimerFor(Network net, uint8_t timer) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->to_timer = timer;
return true;
}
std::optional<uint8_t> getT1SMaxBurstFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->max_burst_count);
}
bool setT1SMaxBurstFor(Network net, uint8_t burst) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->max_burst_count = burst;
return true;
}
std::optional<uint8_t> getT1SBurstTimerFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->burst_timer);
}
bool setT1SBurstTimerFor(Network net, uint8_t timer) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->burst_timer = timer;
return true;
}
std::optional<bool> isT1STerminationEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_TERMINATION) != 0);
}
bool setT1STerminationFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_TERMINATION;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_TERMINATION;
return true;
} }
std::optional<bool> isPerfTestEnabled() const override { std::optional<bool> isPerfTestEnabled() const override {
@@ -262,32 +147,41 @@ public:
return true; return true;
} }
private: std::vector<TerminationGroup> getTerminationGroups() const override {
const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const { return {
{ Network(Network::NetID::DWCAN_01) },
{ Network(Network::NetID::DWCAN_02) }
};
}
protected:
ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override {
auto cfg = getStructurePointer<radcomet2_settings_t>(); auto cfg = getStructurePointer<radcomet2_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
return nullptr; return nullptr;
return &cfg->termination_enables;
}
private:
const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radcomet2_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) { switch(net.getNetID()) {
case Network::NetID::AE_02: return &(cfg->t1s1); case Network::NetID::AE_02: return &(cfg->t1s1);
case Network::NetID::AE_03: return &(cfg->t1s2); case Network::NetID::AE_03: return &(cfg->t1s2);
default: default: return nullptr;
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
} }
} }
ETHERNET10T1S_SETTINGS* getMutableT1SSettingsFor(Network net) { const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const override {
auto cfg = getMutableStructurePointer<radcomet2_settings_t>(); auto cfg = getStructurePointer<radcomet2_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
return nullptr; return nullptr;
switch(net.getNetID()) { switch(net.getNetID()) {
case Network::NetID::AE_02: return &(cfg->t1s1); case Network::NetID::AE_02: return &(cfg->t1s1Ext);
case Network::NetID::AE_03: return &(cfg->t1s2); case Network::NetID::AE_03: return &(cfg->t1s2Ext);
default: default: return nullptr;
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
} }
} }
@@ -77,6 +77,13 @@ public:
} }
protected: protected:
const MACsecNetworkMap& getMACsecNetworkMap() const override {
static const MACsecNetworkMap networks = {
{Network::NetID::AE_01, 0},
};
return networks;
}
RADComet3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { RADComet3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADComet3Settings, Disk::NeoMemoryDiskDriver, Disk::NeoMemoryDiskDriver>(makeDriver); initialize<RADComet3Settings, Disk::NeoMemoryDiskDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
} }
@@ -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 { const ETHERNET_SETTINGS2* getEthernetSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radcomet3_settings_t>(); auto cfg = getStructurePointer<radcomet3_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -153,215 +165,6 @@ public:
} }
} }
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA) != 0);
}
bool setT1SPLCAFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
return true;
}
std::optional<uint8_t> getT1SLocalIDFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->local_id);
}
bool setT1SLocalIDFor(Network net, uint8_t id) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->local_id = id;
return true;
}
std::optional<uint8_t> getT1SMaxNodesFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->max_num_nodes);
}
bool setT1SMaxNodesFor(Network net, uint8_t nodes) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->max_num_nodes = nodes;
return true;
}
std::optional<uint8_t> getT1STxOppTimerFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->to_timer);
}
bool setT1STxOppTimerFor(Network net, uint8_t timer) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->to_timer = timer;
return true;
}
std::optional<uint8_t> getT1SMaxBurstFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->max_burst_count);
}
bool setT1SMaxBurstFor(Network net, uint8_t burst) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->max_burst_count = burst;
return true;
}
std::optional<uint8_t> getT1SBurstTimerFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->burst_timer);
}
bool setT1SBurstTimerFor(Network net, uint8_t timer) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->burst_timer = timer;
return true;
}
std::optional<uint8_t> getT1SLocalIDAlternateFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->local_id_alternate);
}
bool setT1SLocalIDAlternateFor(Network net, uint8_t id) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->local_id_alternate = id;
return true;
}
std::optional<bool> isT1SBusDecodingBeaconsEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS) != 0);
}
bool setT1SBusDecodingBeaconsFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS;
return true;
}
std::optional<bool> isT1SBusDecodingAllEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL) != 0);
}
bool setT1SBusDecodingAllFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL;
return true;
}
std::optional<uint8_t> getT1SMultiIDEnableMaskFor(Network net) const override {
const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return std::nullopt;
return std::make_optional(t1sExt->enable_multi_id);
}
bool setT1SMultiIDEnableMaskFor(Network net, uint8_t mask) override {
ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return false;
t1sExt->enable_multi_id = mask;
return true;
}
std::optional<uint8_t> getT1SMultiIDFor(Network net, uint8_t index) const override {
const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return std::nullopt;
if(index >= 7) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return std::nullopt;
}
return std::make_optional(t1sExt->multi_id[index]);
}
bool setT1SMultiIDFor(Network net, uint8_t index, uint8_t id) override {
ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return false;
if(index >= 7) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
t1sExt->multi_id[index] = id;
return true;
}
bool setPhyRoleFor(Network net, AELinkMode mode) override { bool setPhyRoleFor(Network net, AELinkMode mode) override {
if (mode != AE_LINK_AUTO && mode != AE_LINK_MASTER && mode != AE_LINK_SLAVE) { if (mode != AE_LINK_AUTO && mode != AE_LINK_MASTER && mode != AE_LINK_SLAVE) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error); report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
@@ -656,12 +459,26 @@ public:
return true; return true;
} }
std::vector<TerminationGroup> getTerminationGroups() const override {
return {
{ Network(Network::NetID::DWCAN_01) },
{ Network(Network::NetID::DWCAN_02) }
};
}
protected:
ICSNEO_UNALIGNED(const uint64_t*) getTerminationEnables() const override {
auto cfg = getStructurePointer<radcomet3_settings_t>();
if(cfg == nullptr)
return nullptr;
return &cfg->termination_enables;
}
private: private:
const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const { const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radcomet3_settings_t>(); auto cfg = getStructurePointer<radcomet3_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
return nullptr; return nullptr;
switch(net.getNetID()) { switch(net.getNetID()) {
case Network::NetID::AE_02: return &(cfg->t1s1); case Network::NetID::AE_02: return &(cfg->t1s1);
case Network::NetID::AE_03: return &(cfg->t1s2); case Network::NetID::AE_03: return &(cfg->t1s2);
@@ -669,35 +486,14 @@ private:
case Network::NetID::AE_05: return &(cfg->t1s4); case Network::NetID::AE_05: return &(cfg->t1s4);
case Network::NetID::AE_06: return &(cfg->t1s5); case Network::NetID::AE_06: return &(cfg->t1s5);
case Network::NetID::AE_07: return &(cfg->t1s6); case Network::NetID::AE_07: return &(cfg->t1s6);
default: default: return nullptr;
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
} }
} }
ETHERNET10T1S_SETTINGS* getMutableT1SSettingsFor(Network net) { const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const override {
auto cfg = getMutableStructurePointer<radcomet3_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::AE_02: return &(cfg->t1s1);
case Network::NetID::AE_03: return &(cfg->t1s2);
case Network::NetID::AE_04: return &(cfg->t1s3);
case Network::NetID::AE_05: return &(cfg->t1s4);
case Network::NetID::AE_06: return &(cfg->t1s5);
case Network::NetID::AE_07: return &(cfg->t1s6);
default:
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
}
}
const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const {
auto cfg = getStructurePointer<radcomet3_settings_t>(); auto cfg = getStructurePointer<radcomet3_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
return nullptr; return nullptr;
switch(net.getNetID()) { switch(net.getNetID()) {
case Network::NetID::AE_02: return &(cfg->t1s1Ext); case Network::NetID::AE_02: return &(cfg->t1s1Ext);
case Network::NetID::AE_03: return &(cfg->t1s2Ext); case Network::NetID::AE_03: return &(cfg->t1s2Ext);
@@ -705,27 +501,7 @@ private:
case Network::NetID::AE_05: return &(cfg->t1s4Ext); case Network::NetID::AE_05: return &(cfg->t1s4Ext);
case Network::NetID::AE_06: return &(cfg->t1s5Ext); case Network::NetID::AE_06: return &(cfg->t1s5Ext);
case Network::NetID::AE_07: return &(cfg->t1s6Ext); case Network::NetID::AE_07: return &(cfg->t1s6Ext);
default: default: return nullptr;
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
}
}
ETHERNET10T1S_SETTINGS_EXT* getMutableT1SSettingsExtFor(Network net) {
auto cfg = getMutableStructurePointer<radcomet3_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::AE_02: return &(cfg->t1s1Ext);
case Network::NetID::AE_03: return &(cfg->t1s2Ext);
case Network::NetID::AE_04: return &(cfg->t1s3Ext);
case Network::NetID::AE_05: return &(cfg->t1s4Ext);
case Network::NetID::AE_06: return &(cfg->t1s5Ext);
case Network::NetID::AE_07: return &(cfg->t1s6Ext);
default:
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
} }
} }
@@ -87,9 +87,32 @@ public:
} }
BootloaderPipeline pipeline; BootloaderPipeline pipeline;
auto compVersions = getComponentVersions();
for(size_t i = 0; i < chipVersions.size(); i++) { for(size_t i = 0; i < chipVersions.size(); i++) {
const auto& version = chipVersions[i]; const auto& version = chipVersions[i];
pipeline.add<FlashPhase>(version.id, BootloaderCommunication::RADMultiChip, i == 0); auto it = compVersions.begin();
std::vector<ComponentVersion> sameIdComponents;
while(it != compVersions.end()) {
it = std::find_if(it, compVersions.end(), [&version](const auto& component) {
return (ChipID)component.identifier == version.id;
});
if (it != compVersions.end()) {
sameIdComponents.push_back(*it);
it++;
}
}
if (sameIdComponents.size() > 1) {
std::vector<ComponentVersion> tempCompVersions;
for (const auto& component : compVersions) {
if ((ChipID)component.identifier != version.id || component.expansionSlot != sameIdComponents[0].expansionSlot) {
tempCompVersions.push_back(component);
}
}
compVersions = std::move(tempCompVersions);
}
if (!sameIdComponents.empty()) {
pipeline.add<FlashPhase>(version.id, BootloaderCommunication::RADMultiChip, i == 0, true, true, sameIdComponents[0].expansionSlot);
}
} }
pipeline.add<EnterApplicationPhase>(mainChipID); pipeline.add<EnterApplicationPhase>(mainChipID);
pipeline.add<WaitPhase>(std::chrono::milliseconds(3000)); pipeline.add<WaitPhase>(std::chrono::milliseconds(3000));
@@ -183,6 +206,7 @@ protected:
Network::NetID::LIN_01, Network::NetID::LIN_01,
Network::NetID::FLEXRAY_01,
Network::NetID::FLEXRAY_01A, Network::NetID::FLEXRAY_01A,
Network::NetID::FLEXRAY_01B, Network::NetID::FLEXRAY_01B,
@@ -171,9 +171,32 @@ public:
} }
BootloaderPipeline pipeline; BootloaderPipeline pipeline;
auto compVersions = getComponentVersions();
for(size_t i = 0; i < chipVersions.size(); i++) { for(size_t i = 0; i < chipVersions.size(); i++) {
const auto& version = chipVersions[i]; const auto& version = chipVersions[i];
pipeline.add<FlashPhase>(version.id, BootloaderCommunication::RADMultiChip, i == 0); auto it = compVersions.begin();
std::vector<ComponentVersion> sameIdComponents;
while(it != compVersions.end()) {
it = std::find_if(it, compVersions.end(), [&version](const auto& component) {
return (ChipID)component.identifier == version.id;
});
if (it != compVersions.end()) {
sameIdComponents.push_back(*it);
it++;
}
}
if (sameIdComponents.size() > 1) {
std::vector<ComponentVersion> tempCompVersions;
for (const auto& component : compVersions) {
if ((ChipID)component.identifier != version.id || component.expansionSlot != sameIdComponents[0].expansionSlot) {
tempCompVersions.push_back(component);
}
}
compVersions = std::move(tempCompVersions);
}
if (!sameIdComponents.empty()) {
pipeline.add<FlashPhase>(version.id, BootloaderCommunication::RADMultiChip, i == 0, true, true, sameIdComponents[0].expansionSlot);
}
} }
pipeline.add<EnterApplicationPhase>(mainChipID); pipeline.add<EnterApplicationPhase>(mainChipID);
pipeline.add<WaitPhase>(std::chrono::milliseconds(3000)); pipeline.add<WaitPhase>(std::chrono::milliseconds(3000));
@@ -217,6 +240,14 @@ public:
return chipVersions; return chipVersions;
} }
protected: protected:
const MACsecNetworkMap& getMACsecNetworkMap() const override {
static const MACsecNetworkMap networks = {
{Network::NetID::AE_01, 0},
{Network::NetID::AE_02, 1},
};
return networks;
}
RADGigastar2(neodevice_t neodevice, const driver_factory_t &makeDriver) : Device(neodevice) RADGigastar2(neodevice_t neodevice, const driver_factory_t &makeDriver) : Device(neodevice)
{ {
initialize<RADGigastar2Settings, Disk::ExtExtractorDiskReadDriver, Disk::NeoMemoryDiskDriver>(makeDriver); initialize<RADGigastar2Settings, Disk::ExtExtractorDiskReadDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
@@ -250,222 +250,6 @@ namespace icsneo
} }
} }
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA) != 0);
}
bool setT1SPLCAFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
return true;
}
std::optional<uint8_t> getT1SLocalIDFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->local_id);
}
bool setT1SLocalIDFor(Network net, uint8_t id) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->local_id = id;
return true;
}
std::optional<uint8_t> getT1SMaxNodesFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->max_num_nodes);
}
bool setT1SMaxNodesFor(Network net, uint8_t nodes) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->max_num_nodes = nodes;
return true;
}
std::optional<uint8_t> getT1STxOppTimerFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->to_timer);
}
bool setT1STxOppTimerFor(Network net, uint8_t timer) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->to_timer = timer;
return true;
}
std::optional<uint8_t> getT1SMaxBurstFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->max_burst_count);
}
bool setT1SMaxBurstFor(Network net, uint8_t burst) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->max_burst_count = burst;
return true;
}
std::optional<uint8_t> getT1SBurstTimerFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->burst_timer);
}
bool setT1SBurstTimerFor(Network net, uint8_t timer) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->burst_timer = timer;
return true;
}
std::optional<uint8_t> getT1SLocalIDAlternateFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->local_id_alternate);
}
bool setT1SLocalIDAlternateFor(Network net, uint8_t id) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->local_id_alternate = id;
return true;
}
std::optional<bool> isT1STerminationEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_TERMINATION) != 0);
}
bool setT1STerminationFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_TERMINATION;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_TERMINATION;
return true;
}
std::optional<bool> isT1SBusDecodingBeaconsEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS) != 0);
}
bool setT1SBusDecodingBeaconsFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS;
return true;
}
std::optional<bool> isT1SBusDecodingAllEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional<bool>((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL) != 0);
}
bool setT1SBusDecodingAllFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL;
return true;
}
std::optional<uint8_t> getT1SMultiIDEnableMaskFor(Network net) const override {
const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return std::nullopt;
return std::make_optional(t1sExt->enable_multi_id);
}
bool setT1SMultiIDEnableMaskFor(Network net, uint8_t mask) override {
ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return false;
t1sExt->enable_multi_id = mask;
return true;
}
std::optional<uint8_t> getT1SMultiIDFor(Network net, uint8_t index) const override {
const ETHERNET10T1S_SETTINGS_EXT* t1sExt = getT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return std::nullopt;
if(index >= 7) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return std::nullopt;
}
return std::make_optional(t1sExt->multi_id[index]);
}
bool setPhyEnableFor(Network net, bool enable) override { bool setPhyEnableFor(Network net, bool enable) override {
auto cfg = getMutableStructurePointer<radgigastar2_settings_t>(); auto cfg = getMutableStructurePointer<radgigastar2_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -524,20 +308,6 @@ namespace icsneo
return GetNetworkEnabled(bitfields, 2, networkID); return GetNetworkEnabled(bitfields, 2, networkID);
} }
bool setT1SMultiIDFor(Network net, uint8_t index, uint8_t id) override {
ETHERNET10T1S_SETTINGS_EXT* t1sExt = getMutableT1SSettingsExtFor(net);
if(t1sExt == nullptr)
return false;
if(index >= 7) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
t1sExt->multi_id[index] = id;
return true;
}
std::optional<bool> isPerfTestEnabled() const override { std::optional<bool> isPerfTestEnabled() const override {
auto cfg = getStructurePointer<radgigastar2_settings_t>(); auto cfg = getStructurePointer<radgigastar2_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -556,11 +326,10 @@ namespace icsneo
} }
private: private:
const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const { const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radgigastar2_settings_t>(); auto cfg = getStructurePointer<radgigastar2_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
return nullptr; return nullptr;
switch(net.getNetID()) { switch(net.getNetID()) {
case Network::NetID::AE_03: return &(cfg->t1s1); case Network::NetID::AE_03: return &(cfg->t1s1);
case Network::NetID::AE_04: return &(cfg->t1s2); case Network::NetID::AE_04: return &(cfg->t1s2);
@@ -570,37 +339,14 @@ namespace icsneo
case Network::NetID::AE_08: return &(cfg->t1s6); case Network::NetID::AE_08: return &(cfg->t1s6);
case Network::NetID::AE_09: return &(cfg->t1s7); case Network::NetID::AE_09: return &(cfg->t1s7);
case Network::NetID::AE_10: return &(cfg->t1s8); case Network::NetID::AE_10: return &(cfg->t1s8);
default: default: return nullptr;
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
} }
} }
ETHERNET10T1S_SETTINGS* getMutableT1SSettingsFor(Network net) { const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const override {
auto cfg = getMutableStructurePointer<radgigastar2_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::AE_03: return &(cfg->t1s1);
case Network::NetID::AE_04: return &(cfg->t1s2);
case Network::NetID::AE_05: return &(cfg->t1s3);
case Network::NetID::AE_06: return &(cfg->t1s4);
case Network::NetID::AE_07: return &(cfg->t1s5);
case Network::NetID::AE_08: return &(cfg->t1s6);
case Network::NetID::AE_09: return &(cfg->t1s7);
case Network::NetID::AE_10: return &(cfg->t1s8);
default:
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
}
}
const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const {
auto cfg = getStructurePointer<radgigastar2_settings_t>(); auto cfg = getStructurePointer<radgigastar2_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
return nullptr; return nullptr;
switch(net.getNetID()) { switch(net.getNetID()) {
case Network::NetID::AE_03: return &(cfg->t1s1Ext); case Network::NetID::AE_03: return &(cfg->t1s1Ext);
case Network::NetID::AE_04: return &(cfg->t1s2Ext); case Network::NetID::AE_04: return &(cfg->t1s2Ext);
@@ -610,29 +356,7 @@ namespace icsneo
case Network::NetID::AE_08: return &(cfg->t1s6Ext); case Network::NetID::AE_08: return &(cfg->t1s6Ext);
case Network::NetID::AE_09: return &(cfg->t1s7Ext); case Network::NetID::AE_09: return &(cfg->t1s7Ext);
case Network::NetID::AE_10: return &(cfg->t1s8Ext); case Network::NetID::AE_10: return &(cfg->t1s8Ext);
default: default: return nullptr;
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
}
}
ETHERNET10T1S_SETTINGS_EXT* getMutableT1SSettingsExtFor(Network net) {
auto cfg = getMutableStructurePointer<radgigastar2_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::AE_03: return &(cfg->t1s1Ext);
case Network::NetID::AE_04: return &(cfg->t1s2Ext);
case Network::NetID::AE_05: return &(cfg->t1s3Ext);
case Network::NetID::AE_06: return &(cfg->t1s4Ext);
case Network::NetID::AE_07: return &(cfg->t1s5Ext);
case Network::NetID::AE_08: return &(cfg->t1s6Ext);
case Network::NetID::AE_09: return &(cfg->t1s7Ext);
case Network::NetID::AE_10: return &(cfg->t1s8Ext);
default:
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
} }
} }
@@ -38,6 +38,13 @@ public:
.add<ReconnectPhase>(); .add<ReconnectPhase>();
} }
protected: protected:
const MACsecNetworkMap& getMACsecNetworkMap() const override {
static const MACsecNetworkMap networks = {
{Network::NetID::AE_01, 0},
};
return networks;
}
RADMoon2ZL(neodevice_t neodevice, const driver_factory_t& makeDriver) : RADMoon2Base(neodevice) { RADMoon2ZL(neodevice_t neodevice, const driver_factory_t& makeDriver) : RADMoon2Base(neodevice) {
initialize<RADMoon2Settings>(makeDriver); initialize<RADMoon2Settings>(makeDriver);
} }
@@ -52,6 +52,14 @@ public:
.add<ReconnectPhase>(); .add<ReconnectPhase>();
} }
protected: protected:
const MACsecNetworkMap& getMACsecNetworkMap() const override {
static const MACsecNetworkMap networks = {
{Network::NetID::AE_01, 0},
{Network::NetID::ETHERNET_01, 1},
};
return networks;
}
RADMoon3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { RADMoon3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADMoon3Settings>(makeDriver); initialize<RADMoon3Settings>(makeDriver);
} }
@@ -48,112 +48,6 @@ class RADMoonT1SSettings : public IDeviceSettings {
public: public:
RADMoonT1SSettings(Device* device) : IDeviceSettings(device, 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);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional((t1s->flags & ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA) != 0);
}
bool setT1SPLCAFor(Network net, bool enable) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
if(enable)
t1s->flags |= ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
else
t1s->flags &= ~ETHERNET10T1S_SETTINGS_FLAG_ENABLE_PLCA;
return true;
}
std::optional<uint8_t> getT1SLocalIDFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->local_id);
}
bool setT1SLocalIDFor(Network net, uint8_t id) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->local_id = id;
return true;
}
std::optional<uint8_t> getT1SMaxNodesFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->max_num_nodes);
}
bool setT1SMaxNodesFor(Network net, uint8_t nodes) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->max_num_nodes = nodes;
return true;
}
std::optional<uint8_t> getT1STxOppTimerFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->to_timer);
}
bool setT1STxOppTimerFor(Network net, uint8_t timer) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->to_timer = timer;
return true;
}
std::optional<uint8_t> getT1SMaxBurstFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->max_burst_count);
}
bool setT1SMaxBurstFor(Network net, uint8_t burst) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->max_burst_count = burst;
return true;
}
std::optional<uint8_t> getT1SBurstTimerFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
if(t1s == nullptr)
return std::nullopt;
return std::make_optional(t1s->burst_timer);
}
bool setT1SBurstTimerFor(Network net, uint8_t timer) override {
ETHERNET10T1S_SETTINGS* t1s = getMutableT1SSettingsFor(net);
if(t1s == nullptr)
return false;
t1s->burst_timer = timer;
return true;
}
std::optional<bool> isPerfTestEnabled() const override { std::optional<bool> isPerfTestEnabled() const override {
auto cfg = getStructurePointer<radmoont1s_settings_t>(); auto cfg = getStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -172,215 +66,26 @@ public:
} }
private: private:
const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const { const ETHERNET10T1S_SETTINGS* getT1SSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radmoont1s_settings_t>(); auto cfg = getStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
return nullptr; return nullptr;
switch(net.getNetID()) { switch(net.getNetID()) {
case Network::NetID::AE_01: case Network::NetID::AE_01: return &(cfg->t1s);
return &(cfg->t1s); default: return nullptr;
default:
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
} }
} }
ETHERNET10T1S_SETTINGS* getMutableT1SSettingsFor(Network net) { const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const override {
auto cfg = getMutableStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::AE_01:
return &(cfg->t1s);
default:
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
}
}
const ETHERNET10T1S_SETTINGS_EXT* getT1SSettingsExtFor(Network net) const {
auto cfg = getStructurePointer<radmoont1s_settings_t>(); auto cfg = getStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
return nullptr; return nullptr;
switch(net.getNetID()) { switch(net.getNetID()) {
case Network::NetID::AE_01: case Network::NetID::AE_01: return &(cfg->t1sExt);
return &(cfg->t1sExt); default: return nullptr;
default:
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
} }
} }
ETHERNET10T1S_SETTINGS_EXT* getMutableT1SSettingsExtFor(Network net) {
auto cfg = getMutableStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return nullptr;
switch(net.getNetID()) {
case Network::NetID::AE_01:
return &(cfg->t1sExt);
default:
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return nullptr;
}
}
std::optional<uint8_t> getT1SLocalIDAlternateFor(Network net) const override {
auto cfg = getStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return std::nullopt;
if(net.getNetID() != Network::NetID::AE_01) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return std::nullopt;
}
return std::make_optional(cfg->t1s.local_id_alternate);
}
bool setT1SLocalIDAlternateFor(Network net, uint8_t id) override {
auto cfg = getMutableStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return false;
if(net.getNetID() != Network::NetID::AE_01) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
cfg->t1s.local_id_alternate = id;
return true;
}
std::optional<bool> isT1SBusDecodingBeaconsEnabledFor(Network net) const override {
auto cfg = getStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return std::nullopt;
if(net.getNetID() != Network::NetID::AE_01) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return std::nullopt;
}
return std::make_optional<bool>((cfg->t1s.flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS) != 0);
}
bool setT1SBusDecodingBeaconsFor(Network net, bool enable) override {
auto cfg = getMutableStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return false;
if(net.getNetID() != Network::NetID::AE_01) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
if(enable)
cfg->t1s.flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS;
else
cfg->t1s.flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_BEACONS;
return true;
}
std::optional<bool> isT1SBusDecodingAllEnabledFor(Network net) const override {
auto cfg = getStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return std::nullopt;
if(net.getNetID() != Network::NetID::AE_01) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return std::nullopt;
}
return std::make_optional<bool>((cfg->t1s.flags & ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL) != 0);
}
bool setT1SBusDecodingAllFor(Network net, bool enable) override {
auto cfg = getMutableStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return false;
if(net.getNetID() != Network::NetID::AE_01) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
if(enable)
cfg->t1s.flags |= ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL;
else
cfg->t1s.flags &= ~ETHERNET10T1S_SETTINGS_FLAG_BUS_DECODING_ALL;
return true;
}
std::optional<uint8_t> getT1SMultiIDEnableMaskFor(Network net) const override {
auto cfg = getStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return std::nullopt;
if(net.getNetID() != Network::NetID::AE_01) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return std::nullopt;
}
return std::make_optional(cfg->t1sExt.enable_multi_id);
}
bool setT1SMultiIDEnableMaskFor(Network net, uint8_t mask) override {
auto cfg = getMutableStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return false;
if(net.getNetID() != Network::NetID::AE_01) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
cfg->t1sExt.enable_multi_id = mask;
return true;
}
std::optional<uint8_t> getT1SMultiIDFor(Network net, uint8_t index) const override {
auto cfg = getStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return std::nullopt;
if(net.getNetID() != Network::NetID::AE_01) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return std::nullopt;
}
if(index >= 7) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return std::nullopt;
}
return std::make_optional(cfg->t1sExt.multi_id[index]);
}
bool setT1SMultiIDFor(Network net, uint8_t index, uint8_t id) override {
auto cfg = getMutableStructurePointer<radmoont1s_settings_t>();
if(cfg == nullptr)
return false;
if(net.getNetID() != Network::NetID::AE_01) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
if(index >= 7) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
cfg->t1sExt.multi_id[index] = id;
return true;
}
const RAD_GPTP_SETTINGS* getGPTPSettings() const override { const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
auto cfg = getStructurePointer<radmoont1s_settings_t>(); auto cfg = getStructurePointer<radmoont1s_settings_t>();
return cfg ? &cfg->gPTP : nullptr; return cfg ? &cfg->gPTP : nullptr;
+9 -9
View File
@@ -280,7 +280,7 @@ typedef unsigned __int64 uint64_t;
#define NEODEVICE_GIGASTAR2 (0x00000029) #define NEODEVICE_GIGASTAR2 (0x00000029)
#define NEODEVICE_FIRE3_T1S_LIN (0x0000002A) #define NEODEVICE_FIRE3_T1S_LIN (0x0000002A)
#define NEODEVICE_FIRE3_T1S_SENT (0x0000002B) #define NEODEVICE_FIRE3_T1S_SENT (0x0000002B)
#define NEODEVICE_RADGEMINI (0x0000002C) #define NEODEVICE_RADARGOS (0x0000002C)
#define NEODEVICE_RED_DEPRECATED (0x00000040) #define NEODEVICE_RED_DEPRECATED (0x00000040)
#define NEODEVICE_ECU_DEPRECATED (0x00000080) #define NEODEVICE_ECU_DEPRECATED (0x00000080)
@@ -975,7 +975,7 @@ typedef union _stChipVersions
{ {
uint8_t mchip_major; uint8_t mchip_major;
uint8_t mchip_minor; uint8_t mchip_minor;
} radgemini_versions; } radargos_versions;
struct struct
{ {
@@ -2794,7 +2794,7 @@ typedef struct _SRADMoon3Settings
#define SRADMoon3Settings_SIZE 68 #define SRADMoon3Settings_SIZE 68
typedef struct _SRADGeminiSettings typedef struct _SRADArgosSettings
{ {
uint16_t perf_en; // 2 uint16_t perf_en; // 2
@@ -2815,9 +2815,9 @@ typedef struct _SRADGeminiSettings
uint16_t enableLatencyTest : 1; uint16_t enableLatencyTest : 1;
uint16_t reserved : 15; uint16_t reserved : 15;
} flags; // 2 } flags; // 2
} SRADGeminiSettings; } SRADArgosSettings;
#define SRADGeminiSettings_SIZE 86 #define SRADArgosSettings_SIZE 86
typedef struct _SRADGigastarSettings typedef struct _SRADGigastarSettings
{ {
@@ -4450,7 +4450,7 @@ typedef struct _GLOBAL_SETTINGS
SRADEpsilonSettings epsilon; SRADEpsilonSettings epsilon;
SRADBMSSettings rad_bms; SRADBMSSettings rad_bms;
SRADMoon3Settings radmoon3; SRADMoon3Settings radmoon3;
SRADGeminiSettings radgemini; SRADArgosSettings radargos;
SRADCometSettings radcomet; SRADCometSettings radcomet;
SRADComet3Settings radcomet3; SRADComet3Settings radcomet3;
SRADGigastar2Settings radgigastar2; SRADGigastar2Settings radgigastar2;
@@ -4509,7 +4509,7 @@ typedef enum _EDeviceSettingsType
DeviceRADGalaxy2SettingsType, DeviceRADGalaxy2SettingsType,
DeviceRADGigastar2SettingsType, DeviceRADGigastar2SettingsType,
DeviceRADMoonT1SSettingsType, DeviceRADMoonT1SSettingsType,
DeviceRADGeminiSettingsType, DeviceRADArgosSettingsType,
DeviceFire3T1sLinSettingsType, DeviceFire3T1sLinSettingsType,
// add new settings type here // add new settings type here
// Also add to map inside cicsneoVI::Init() // Also add to map inside cicsneoVI::Init()
@@ -4545,7 +4545,7 @@ typedef struct _SDeviceSettings
SRADEpsilonSettings epsilon; SRADEpsilonSettings epsilon;
SRADBMSSettings rad_bms; SRADBMSSettings rad_bms;
SRADMoon3Settings radmoon3; SRADMoon3Settings radmoon3;
SRADGeminiSettings radgemini; SRADArgosSettings radargos;
SFire3FlexraySettings fire3Flexray; SFire3FlexraySettings fire3Flexray;
SFire3T1sLinSettings fire3t1slin; SFire3T1sLinSettings fire3t1slin;
SRADCometSettings radcomet; SRADCometSettings radcomet;
@@ -5430,7 +5430,7 @@ CHECK_STRUCT_SIZE(SRADEpsilonSettings);
CHECK_STRUCT_SIZE(RAD_GPTP_SETTINGS); CHECK_STRUCT_SIZE(RAD_GPTP_SETTINGS);
CHECK_STRUCT_SIZE(SRADBMSSettings); CHECK_STRUCT_SIZE(SRADBMSSettings);
CHECK_STRUCT_SIZE(SRADMoon3Settings); CHECK_STRUCT_SIZE(SRADMoon3Settings);
CHECK_STRUCT_SIZE(SRADGeminiSettings); CHECK_STRUCT_SIZE(SRADArgosSettings);
CHECK_STRUCT_SIZE(SFire3FlexraySettings); CHECK_STRUCT_SIZE(SFire3FlexraySettings);
CHECK_STRUCT_SIZE(SFire3T1sLinSettings); CHECK_STRUCT_SIZE(SFire3T1sLinSettings);
CHECK_STRUCT_SIZE(CANHubSettings); CHECK_STRUCT_SIZE(CANHubSettings);
+2
View File
@@ -381,6 +381,7 @@ typedef enum _icsneoc2_lin_msg_type_t {
icsneoc2_lin_msg_type_sync_only = 4, icsneoc2_lin_msg_type_sync_only = 4,
icsneoc2_lin_msg_type_update_responder = 5, icsneoc2_lin_msg_type_update_responder = 5,
icsneoc2_lin_msg_type_error = 6, icsneoc2_lin_msg_type_error = 6,
icsneoc2_lin_msg_type_wakeup_request = 7,
} _icsneoc2_lin_msg_type_t; } _icsneoc2_lin_msg_type_t;
typedef uint8_t 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_HAS_UPDATED_RESPONDER_ONCE 0x20
#define ICSNEOC2_LIN_STATUS_BUS_RECOVERED 0x40 #define ICSNEOC2_LIN_STATUS_BUS_RECOVERED 0x40
#define ICSNEOC2_LIN_STATUS_BREAK_ONLY 0x80 #define ICSNEOC2_LIN_STATUS_BREAK_ONLY 0x80
#define ICSNEOC2_LIN_STATUS_WAKEUP_REQUEST 0x100
typedef uint32_t icsneoc2_lin_status_flags_t; typedef uint32_t icsneoc2_lin_status_flags_t;
+6 -6
View File
@@ -533,26 +533,26 @@ icsneoc2_error_t icsneoc2_settings_t1s_burst_timer_get(icsneoc2_device_t* device
icsneoc2_error_t icsneoc2_settings_t1s_burst_timer_set(icsneoc2_device_t* device, icsneoc2_netid_t netid, uint8_t value); icsneoc2_error_t icsneoc2_settings_t1s_burst_timer_set(icsneoc2_device_t* device, icsneoc2_netid_t netid, uint8_t value);
/** /**
* Get the Max burst timer for a network that supports 10BASE-T1S. * Get the maximum PLCA burst count for a network that supports 10BASE-T1S.
* *
* @param[in] device The device to check. * @param[in] device The device to check.
* @param[in] netid The network ID to check. * @param[in] netid The network ID to check.
* @param[out] value Pointer to store the Max burst timer value. * @param[out] value Pointer to store the maximum burst count.
* *
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise. * @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise.
*/ */
icsneoc2_error_t icsneoc2_settings_t1s_max_burst_timer_for_get(icsneoc2_device_t* device, icsneoc2_netid_t netid, uint8_t* value); icsneoc2_error_t icsneoc2_settings_t1s_max_burst_get(icsneoc2_device_t* device, icsneoc2_netid_t netid, uint8_t* value);
/** /**
* Set the Max burst timer for a network that supports 10BASE-T1S. * Set the maximum PLCA burst count for a network that supports 10BASE-T1S.
* *
* @param[in] device The device to configure. * @param[in] device The device to configure.
* @param[in] netid The network ID to configure. * @param[in] netid The network ID to configure.
* @param[in] value The Max burst timer value to set. * @param[in] value The maximum burst count to set.
* *
* @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise. * @return icsneoc2_error_t icsneoc2_error_success if successful, icsneoc2_error_invalid_parameters otherwise.
*/ */
icsneoc2_error_t icsneoc2_settings_t1s_max_burst_timer_for_set(icsneoc2_device_t* device, icsneoc2_netid_t netid, uint8_t value); icsneoc2_error_t icsneoc2_settings_t1s_max_burst_set(icsneoc2_device_t* device, icsneoc2_netid_t netid, uint8_t value);
/** /**
* Get the alternate local ID for a network that supports 10BASE-T1S. * Get the alternate local ID for a network that supports 10BASE-T1S.
+2 -2
View File
@@ -52,7 +52,7 @@ typedef enum _icsneoc2_devicetype_t {
icsneoc2_devicetype_rad_gigastar2 = 0x00000029, icsneoc2_devicetype_rad_gigastar2 = 0x00000029,
icsneoc2_devicetype_fire3_t1s_lin = 0x0000002a, icsneoc2_devicetype_fire3_t1s_lin = 0x0000002a,
icsneoc2_devicetype_fire3_t1s_sent = 0x0000002b, icsneoc2_devicetype_fire3_t1s_sent = 0x0000002b,
icsneoc2_devicetype_rad_gemini = 0x0000002c, icsneoc2_devicetype_rad_argos = 0x0000002c,
icsneoc2_devicetype_red = 0x00000040, icsneoc2_devicetype_red = 0x00000040,
icsneoc2_devicetype_ecu = 0x00000080, icsneoc2_devicetype_ecu = 0x00000080,
icsneoc2_devicetype_ievb = 0x00000100, icsneoc2_devicetype_ievb = 0x00000100,
@@ -678,7 +678,7 @@ typedef enum _icsneoc2_chip_id_t {
icsneoc2_chip_id_radmoont1s_zchip = 130, icsneoc2_chip_id_radmoont1s_zchip = 130,
icsneoc2_chip_id_radgigastar2_zynq = 131, icsneoc2_chip_id_radgigastar2_zynq = 131,
icsneoc2_chip_id_sfpmodule_ent11100_mchip = 132, icsneoc2_chip_id_sfpmodule_ent11100_mchip = 132,
icsneoc2_chip_id_radgemini_mchip = 135, icsneoc2_chip_id_radargos_mchip = 135,
icsneoc2_chip_id_maxsize, // Must be last entry, Don't use as a chip ID. icsneoc2_chip_id_maxsize, // Must be last entry, Don't use as a chip ID.
// Used for unknown or invalid chip ID // Used for unknown or invalid chip ID
+1 -1
View File
@@ -28,7 +28,7 @@
#include "icsneo/device/tree/radmoon2/radmoon2.h" #include "icsneo/device/tree/radmoon2/radmoon2.h"
#include "icsneo/device/tree/radmoon2/radmoon2zl.h" #include "icsneo/device/tree/radmoon2/radmoon2zl.h"
#include "icsneo/device/tree/radmoon3/radmoon3.h" #include "icsneo/device/tree/radmoon3/radmoon3.h"
#include "icsneo/device/tree/radgemini/radgemini.h" #include "icsneo/device/tree/radargos/radargos.h"
#include "icsneo/device/tree/radmoonduo/radmoonduo.h" #include "icsneo/device/tree/radmoonduo/radmoonduo.h"
#include "icsneo/device/tree/radpluto/radpluto.h" #include "icsneo/device/tree/radpluto/radpluto.h"
#include "icsneo/device/tree/radstar2/radstar2.h" #include "icsneo/device/tree/radstar2/radstar2.h"
+1
View File
@@ -35,6 +35,7 @@ private:
Socket messageSocket; Socket messageSocket;
bool opened = false; bool opened = false;
bool comEnabled = false; bool comEnabled = false;
std::string token;
std::unique_ptr<Socket> dataSocket; std::unique_ptr<Socket> dataSocket;
}; };
+1 -1
View File
@@ -28,7 +28,7 @@
#include "icsneo/device/tree/radmoon2/radmoon2.h" #include "icsneo/device/tree/radmoon2/radmoon2.h"
#include "icsneo/device/tree/radmoon2/radmoon2zl.h" #include "icsneo/device/tree/radmoon2/radmoon2zl.h"
#include "icsneo/device/tree/radmoon3/radmoon3.h" #include "icsneo/device/tree/radmoon3/radmoon3.h"
#include "icsneo/device/tree/radgemini/radgemini.h" #include "icsneo/device/tree/radargos/radargos.h"
#include "icsneo/device/tree/radmoonduo/radmoonduo.h" #include "icsneo/device/tree/radmoonduo/radmoonduo.h"
#include "icsneo/device/tree/radpluto/radpluto.h" #include "icsneo/device/tree/radpluto/radpluto.h"
#include "icsneo/device/tree/radstar2/radstar2.h" #include "icsneo/device/tree/radstar2/radstar2.h"
+1 -1
View File
@@ -86,7 +86,7 @@ void CDCACM::Find(std::vector<FoundDevice>& found) {
if(ref == nullptr) if(ref == nullptr)
return; return;
io_iterator_t matchingServices = 0; io_iterator_t matchingServices = 0;
kern_return_t kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, ref, &matchingServices); kern_return_t kernResult = IOServiceGetMatchingServices(kIOMainPortDefault, ref, &matchingServices);
if(KERN_SUCCESS != kernResult || matchingServices == 0) if(KERN_SUCCESS != kernResult || matchingServices == 0)
return; return;
IOReleaser matchingServicesReleaser(matchingServices); IOReleaser matchingServicesReleaser(matchingServices);
+43 -16
View File
@@ -6,9 +6,21 @@
using namespace icsneo; using namespace icsneo;
#define SERVD_VERSION 2 #define SERVD_VERSION 3
static const Address SERVD_ADDRESS = [] {
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4996)
#endif
const auto envip = std::getenv("LIBICSNEO_SERVD_IP");
const auto envport = std::getenv("LIBICSNEO_SERVD_PORT");
#ifdef _MSC_VER
#pragma warning(pop)
#endif
return Address(envip ? envip : "127.0.0.1", envport ? static_cast<uint16_t>(std::stoi(envport)) : 26741);
}();
static const Address SERVD_ADDRESS = Address("127.0.0.1", 26741);
static const std::string SERVD_VERSION_STR = std::to_string(SERVD_VERSION); static const std::string SERVD_VERSION_STR = std::to_string(SERVD_VERSION);
bool Servd::Enabled() { bool Servd::Enabled() {
@@ -56,8 +68,13 @@ void Servd::Find(std::vector<FoundDevice>& found) {
return; return;
} }
if(std::stoll(response) < SERVD_VERSION) { try {
EventManager::GetInstance().add(APIEvent::Type::ServdOutdatedError, APIEvent::Severity::Error); if(std::stoll(response) < SERVD_VERSION) {
EventManager::GetInstance().add(APIEvent::Type::ServdOutdatedError, APIEvent::Severity::Error);
return;
}
} catch (const std::exception&) {
EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error);
return; return;
} }
@@ -70,22 +87,25 @@ void Servd::Find(std::vector<FoundDevice>& found) {
const auto lines = split(response, '\n'); const auto lines = split(response, '\n');
for(auto&& line : lines) { for(auto&& line : lines) {
const auto cols = split(line, ' '); const auto cols = split(line, ' ');
if(cols.size() < 3) { if(cols.size() < 2) {
if(!line.empty()) { if(!line.empty()) {
EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error);
} }
continue; continue;
} }
const auto& serial = cols[0]; const auto& serial = cols[0];
const auto& ip = cols[1]; if(serial.empty() || serial.size() >= sizeof(FoundDevice::serial)) {
EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error);
continue;
}
uint16_t port = 0; uint16_t port = 0;
try { try {
port = static_cast<uint16_t>(std::stoi(cols[2])); port = static_cast<uint16_t>(std::stoi(cols[1]));
} catch (const std::exception&) { } catch (const std::exception&) {
EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error);
continue; continue;
} }
Address address(ip.c_str(), port); Address address(SERVD_ADDRESS.ip().c_str(), port);
auto& newFound = found.emplace_back(); auto& newFound = found.emplace_back();
std::copy(serial.begin(), serial.end(), newFound.serial); std::copy(serial.begin(), serial.end(), newFound.serial);
newFound.makeDriver = [=](device_eventhandler_t err, neodevice_t& forDevice) { newFound.makeDriver = [=](device_eventhandler_t err, neodevice_t& forDevice) {
@@ -130,16 +150,19 @@ bool Servd::open() {
EventManager::GetInstance().add(APIEvent::Type::SyscallError, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::SyscallError, APIEvent::Severity::Error);
return false; return false;
} }
const auto& ip = tokens[0];
uint16_t port = 0; uint16_t port = 0;
try { try {
port = static_cast<uint16_t>(std::stoi(tokens[1])); port = static_cast<uint16_t>(std::stoi(tokens[0]));
} catch (const std::exception&) { } catch (const std::exception&) {
EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error);
return false; return false;
} }
Address address(ip.c_str(), port); token = tokens[1];
dataSocket->connect(address); Address address(SERVD_ADDRESS.ip().c_str(), port);
if(!dataSocket->connect(address)) {
EventManager::GetInstance().add(APIEvent::Type::SyscallError, APIEvent::Severity::Error);
return false;
}
readThread = std::thread(&Servd::read, this); readThread = std::thread(&Servd::read, this);
writeThread = std::thread(&Servd::write, this); writeThread = std::thread(&Servd::write, this);
opened = true; opened = true;
@@ -159,15 +182,14 @@ bool Servd::close() {
writeThread.join(); writeThread.join();
} }
if(isOpen()) { if(isOpen()) {
Address localAddress; const std::string request = SERVD_VERSION_STR + " close " + token;
dataSocket->address(localAddress);
const std::string request = SERVD_VERSION_STR + " close " + localAddress.ip() + " " + std::to_string(localAddress.port());
std::string response; std::string response;
response.resize(1); response.resize(1);
if(!messageSocket.transceive(request, response, std::chrono::milliseconds(5000))) { if(!messageSocket.transceive(request, response, std::chrono::milliseconds(5000))) {
EventManager::GetInstance().add(APIEvent::Type::ServdTransceiveError, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::ServdTransceiveError, APIEvent::Severity::Error);
return false; return false;
} }
token.clear();
dataSocket.reset(); dataSocket.reset();
} }
opened = false; opened = false;
@@ -207,7 +229,12 @@ bool Servd::enableCommunication(bool enable, bool& sendMsg) {
EventManager::GetInstance().add(APIEvent::Type::ServdTransceiveError, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::ServdTransceiveError, APIEvent::Severity::Error);
return false; return false;
} }
com = response.empty() ? 0 : std::stoll(response); try {
com = response.empty() ? 0 : std::stoll(response);
} catch (const std::exception&) {
EventManager::GetInstance().add(APIEvent::Type::ServdInvalidResponseError, APIEvent::Severity::Error);
return false;
}
} }
sendMsg = false; sendMsg = false;
if(enable) { if(enable) {
+111
View File
@@ -0,0 +1,111 @@
#include "icsneo/communication/message/ethphymessage.h"
#include "icsneo/communication/packet/ethphyregpacket.h"
#include "gtest/gtest.h"
#include "icsneo/device/tree/radjupiter/radjupiter.h"
using namespace icsneo;
namespace {
const device_eventhandler_t ignore = [](APIEvent::Type, APIEvent::Severity) {};
EthPhyMessage request(bool clause45 = false, bool write = false) {
EthPhyMessage msg;
msg.appendPhyMessage(write, clause45, 31, clause45 ? 31 : 255, clause45 ? 65535 : 31, 0x1234);
msg.messages[0]->BusIndex = 15;
return msg;
}
std::vector<uint8_t> encode(const EthPhyMessage& msg) {
std::vector<uint8_t> bytes;
EXPECT_TRUE(HardwareEthernetPhyRegisterPacket::EncodeFromMessage(msg, bytes, ignore));
return bytes;
}
}
TEST(EthPhyRegister, KnownWireBytesAndStatus) {
for(bool clause45 : {false, true}) {
auto msg = request(clause45, true);
EXPECT_FALSE(msg.messages[0]->Status.has_value());
auto bytes = encode(msg);
EXPECT_EQ(bytes, (std::vector<uint8_t>{1, 0, 1, 8, static_cast<uint8_t>(clause45 ? 7 : 3), 0x1f,
31, static_cast<uint8_t>(clause45 ? 31 : 255), static_cast<uint8_t>(clause45 ? 255 : 31),
static_cast<uint8_t>(clause45 ? 255 : 0), 0x34, 0x12}));
for(uint8_t status = 0; status < 8; ++status) {
bytes[4] = static_cast<uint8_t>((clause45 ? 7 : 3) | (status << 3));
auto decoded = HardwareEthernetPhyRegisterPacket::DecodeToMessage(bytes, ignore);
ASSERT_NE(decoded, nullptr);
EXPECT_EQ(decoded->messages[0]->Status, status);
EXPECT_EQ(encode(*decoded)[4], clause45 ? 7 : 3); // never retransmit response status
}
}
}
TEST(EthPhyRegister, InvalidRequestsLeaveOutputUntouched) {
for(int invalid = 0; invalid < 8; ++invalid) {
auto msg = request();
switch(invalid) {
case 0: msg.messages.clear(); break;
case 1: msg.messages.resize(129, msg.messages[0]); break;
case 2: msg.messages.push_back(nullptr); break;
case 3: msg.messages[0]->BusIndex = 16; break;
case 4: msg.messages[0]->Version = 0; break;
case 5: msg.messages[0]->Clause22.phyAddr = 32; break;
case 6: msg.messages[0]->Clause22.regAddr = 32; break;
case 7: msg.messages = request(true).messages; msg.messages[0]->Clause45.device = 32; break;
}
std::vector<uint8_t> bytes{0xaa};
EXPECT_FALSE(HardwareEthernetPhyRegisterPacket::EncodeFromMessage(msg, bytes, ignore));
EXPECT_EQ(bytes, (std::vector<uint8_t>{0xaa}));
}
auto msg = request(); msg.messages.resize(128, msg.messages[0]);
EXPECT_EQ(encode(msg).size(), 1028u);
}
TEST(EthPhyRegister, RejectMalformedResponses) {
const auto valid = encode(request());
for(size_t size = 0; size < valid.size(); ++size)
EXPECT_EQ(HardwareEthernetPhyRegisterPacket::DecodeToMessage({valid.begin(), valid.begin() + size}, ignore), nullptr);
for(size_t index : {0u, 2u, 3u, 5u}) {
auto bytes = valid; bytes[index] = 0;
EXPECT_EQ(HardwareEthernetPhyRegisterPacket::DecodeToMessage(bytes, ignore), nullptr);
}
auto extra = valid; extra.push_back(0);
EXPECT_EQ(HardwareEthernetPhyRegisterPacket::DecodeToMessage(extra, ignore), nullptr);
}
namespace {
class PhyTestDriver : public Driver {
public:
explicit PhyTestDriver(const device_eventhandler_t& report) : Driver(report) {}
bool open() override { return false; }
bool isOpen() override { return opened; }
bool opened = true;
bool close() override { opened = false; return true; }
driver_finder_t getFinder() override { return [](std::vector<FoundDevice>&) {}; }
int writes = 0;
protected:
bool writeInternal(const std::vector<uint8_t>&) override { ++writes; return false; }
};
class PhyTestJupiter : public RADJupiter {
public:
explicit PhyTestJupiter(const FoundDevice& found) : RADJupiter(found) {}
~PhyTestJupiter() override { com->driver->close(); }
bool isOpen() const override { return true; } // Exercise the native send path, without hardware.
};
}
TEST(EthPhyRegister, DeviceDoesNotSendInvalidRequests) {
PhyTestDriver* driver = nullptr;
FoundDevice found;
found.makeDriver = [&driver](device_eventhandler_t report, neodevice_t&) {
auto result = std::make_unique<PhyTestDriver>(report);
driver = result.get();
return result;
};
PhyTestJupiter device(found);
auto msg = request();
msg.messages.push_back(nullptr);
EXPECT_FALSE(device.sendEthPhyMsg(msg).has_value());
EXPECT_EQ(driver->writes, 0);
msg.messages = request().messages; msg.messages[0]->BusIndex = 16;
EXPECT_FALSE(device.sendEthPhyMsg(msg).has_value());
EXPECT_EQ(driver->writes, 0);
msg.messages = request().messages;
EXPECT_FALSE(device.sendEthPhyMsg(msg, std::chrono::milliseconds(0)).has_value());
EXPECT_EQ(driver->writes, 0);
// The valid request reaches the fake driver's explicit send failure.
EXPECT_FALSE(device.sendEthPhyMsg(msg).has_value());
EXPECT_EQ(driver->writes, 1);
}
+10 -7
View File
@@ -317,8 +317,8 @@ TEST(icsneoc2, test_icsneoc2_error_invalid_parameters_and_invalid_device)
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_max_nodes_set(NULL, 0, placeholderInteger8)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_max_nodes_set(NULL, 0, placeholderInteger8));
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_tx_opp_timer_get(NULL, 0, &placeholderInteger8)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_tx_opp_timer_get(NULL, 0, &placeholderInteger8));
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_tx_opp_timer_set(NULL, 0, placeholderInteger8)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_tx_opp_timer_set(NULL, 0, placeholderInteger8));
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_max_burst_timer_for_get(NULL, 0, &placeholderInteger8)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_max_burst_get(NULL, 0, &placeholderInteger8));
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_max_burst_timer_for_set(NULL, 0, placeholderInteger8)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_max_burst_set(NULL, 0, placeholderInteger8));
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_burst_timer_get(NULL, 0, &placeholderInteger8)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_burst_timer_get(NULL, 0, &placeholderInteger8));
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_burst_timer_set(NULL, 0, placeholderInteger8)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_burst_timer_set(NULL, 0, placeholderInteger8));
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_local_id_alternate_get(NULL, 0, &placeholderInteger8)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_settings_t1s_local_id_alternate_get(NULL, 0, &placeholderInteger8));
@@ -480,7 +480,7 @@ TEST(icsneoc2, test_icsneoc2_devicetype_t)
ASSERT_EQ(icsneoc2_devicetype_rad_gigastar2, 0x00000029); ASSERT_EQ(icsneoc2_devicetype_rad_gigastar2, 0x00000029);
ASSERT_EQ(icsneoc2_devicetype_fire3_t1s_lin, 0x0000002a); ASSERT_EQ(icsneoc2_devicetype_fire3_t1s_lin, 0x0000002a);
ASSERT_EQ(icsneoc2_devicetype_fire3_t1s_sent, 0x0000002b); ASSERT_EQ(icsneoc2_devicetype_fire3_t1s_sent, 0x0000002b);
ASSERT_EQ(icsneoc2_devicetype_rad_gemini, 0x0000002c); ASSERT_EQ(icsneoc2_devicetype_rad_argos, 0x0000002c);
ASSERT_EQ(icsneoc2_devicetype_red, 0x00000040); ASSERT_EQ(icsneoc2_devicetype_red, 0x00000040);
ASSERT_EQ(icsneoc2_devicetype_ecu, 0x00000080); ASSERT_EQ(icsneoc2_devicetype_ecu, 0x00000080);
ASSERT_EQ(icsneoc2_devicetype_ievb, 0x00000100); ASSERT_EQ(icsneoc2_devicetype_ievb, 0x00000100);
@@ -543,7 +543,7 @@ TEST(icsneoc2, test_devicetype_enum_alignment)
ASSERT_EQ(icsneo::DeviceType::RADGigastar2, icsneoc2_devicetype_rad_gigastar2); ASSERT_EQ(icsneo::DeviceType::RADGigastar2, icsneoc2_devicetype_rad_gigastar2);
ASSERT_EQ(icsneo::DeviceType::FIRE3_T1S_LIN, icsneoc2_devicetype_fire3_t1s_lin); ASSERT_EQ(icsneo::DeviceType::FIRE3_T1S_LIN, icsneoc2_devicetype_fire3_t1s_lin);
ASSERT_EQ(icsneo::DeviceType::FIRE3_T1S_SENT, icsneoc2_devicetype_fire3_t1s_sent); ASSERT_EQ(icsneo::DeviceType::FIRE3_T1S_SENT, icsneoc2_devicetype_fire3_t1s_sent);
ASSERT_EQ(icsneo::DeviceType::RADGemini, icsneoc2_devicetype_rad_gemini); ASSERT_EQ(icsneo::DeviceType::RADArgos, icsneoc2_devicetype_rad_argos);
ASSERT_EQ(icsneo::DeviceType::RED, icsneoc2_devicetype_red); ASSERT_EQ(icsneo::DeviceType::RED, icsneoc2_devicetype_red);
ASSERT_EQ(icsneo::DeviceType::ECU, icsneoc2_devicetype_ecu); ASSERT_EQ(icsneo::DeviceType::ECU, icsneoc2_devicetype_ecu);
ASSERT_EQ(icsneo::DeviceType::IEVB, icsneoc2_devicetype_ievb); ASSERT_EQ(icsneo::DeviceType::IEVB, icsneoc2_devicetype_ievb);
@@ -947,7 +947,7 @@ TEST(icsneoc2, test_icsneoc2_chip_id_t)
ASSERT_EQ(icsneoc2_chip_id_radmoont1s_zchip, 130); ASSERT_EQ(icsneoc2_chip_id_radmoont1s_zchip, 130);
ASSERT_EQ(icsneoc2_chip_id_radgigastar2_zynq, 131); ASSERT_EQ(icsneoc2_chip_id_radgigastar2_zynq, 131);
ASSERT_EQ(icsneoc2_chip_id_sfpmodule_ent11100_mchip, 132); ASSERT_EQ(icsneoc2_chip_id_sfpmodule_ent11100_mchip, 132);
ASSERT_EQ(icsneoc2_chip_id_radgemini_mchip, 135); ASSERT_EQ(icsneoc2_chip_id_radargos_mchip, 135);
ASSERT_EQ(icsneoc2_chip_id_maxsize, 136); ASSERT_EQ(icsneoc2_chip_id_maxsize, 136);
ASSERT_EQ(icsneoc2_chip_id_invalid, 255); ASSERT_EQ(icsneoc2_chip_id_invalid, 255);
@@ -1084,7 +1084,7 @@ TEST(icsneoc2, test_chip_id_enum_alignment)
ASSERT_EQ(static_cast<icsneoc2_chip_id_t>(icsneo::ChipID::RADMOONT1S_ZCHIP), icsneoc2_chip_id_radmoont1s_zchip); ASSERT_EQ(static_cast<icsneoc2_chip_id_t>(icsneo::ChipID::RADMOONT1S_ZCHIP), icsneoc2_chip_id_radmoont1s_zchip);
ASSERT_EQ(static_cast<icsneoc2_chip_id_t>(icsneo::ChipID::RADGigastar2_ZYNQ), icsneoc2_chip_id_radgigastar2_zynq); ASSERT_EQ(static_cast<icsneoc2_chip_id_t>(icsneo::ChipID::RADGigastar2_ZYNQ), icsneoc2_chip_id_radgigastar2_zynq);
ASSERT_EQ(static_cast<icsneoc2_chip_id_t>(icsneo::ChipID::SFPModule_ent11100_MCHIP), icsneoc2_chip_id_sfpmodule_ent11100_mchip); ASSERT_EQ(static_cast<icsneoc2_chip_id_t>(icsneo::ChipID::SFPModule_ent11100_MCHIP), icsneoc2_chip_id_sfpmodule_ent11100_mchip);
ASSERT_EQ(static_cast<icsneoc2_chip_id_t>(icsneo::ChipID::RADGemini_MCHIP), icsneoc2_chip_id_radgemini_mchip); ASSERT_EQ(static_cast<icsneoc2_chip_id_t>(icsneo::ChipID::RADArgos_MCHIP), icsneoc2_chip_id_radargos_mchip);
ASSERT_EQ(static_cast<icsneoc2_chip_id_t>(icsneo::ChipID::Invalid), icsneoc2_chip_id_invalid); ASSERT_EQ(static_cast<icsneoc2_chip_id_t>(icsneo::ChipID::Invalid), icsneoc2_chip_id_invalid);
} }
@@ -1113,7 +1113,7 @@ TEST(icsneoc2, test_icsneoc2_chip_versions_props_get)
{ {
// Build an in-memory list of two chip_versions nodes // Build an in-memory list of two chip_versions nodes
icsneoc2_chip_versions_t second{}; icsneoc2_chip_versions_t second{};
second.version_report.id = icsneo::ChipID::RADGemini_MCHIP; second.version_report.id = icsneo::ChipID::RADArgos_MCHIP;
second.version_report.name = "second"; second.version_report.name = "second";
second.version_report.major = 9; second.version_report.major = 9;
second.version_report.minor = 8; second.version_report.minor = 8;
@@ -1862,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_sync_only, 4);
ASSERT_EQ(icsneoc2_lin_msg_type_update_responder, 5); ASSERT_EQ(icsneoc2_lin_msg_type_update_responder, 5);
ASSERT_EQ(icsneoc2_lin_msg_type_error, 6); 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)); ASSERT_EQ(sizeof(icsneoc2_lin_msg_type_t), sizeof(uint8_t));
} }
@@ -1875,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_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_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_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) TEST(icsneoc2, test_lin_flag_bitmask_values)
@@ -1901,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_HAS_UPDATED_RESPONDER_ONCE, 0x20);
ASSERT_EQ(ICSNEOC2_LIN_STATUS_BUS_RECOVERED, 0x40); ASSERT_EQ(ICSNEOC2_LIN_STATUS_BUS_RECOVERED, 0x40);
ASSERT_EQ(ICSNEOC2_LIN_STATUS_BREAK_ONLY, 0x80); ASSERT_EQ(ICSNEOC2_LIN_STATUS_BREAK_ONLY, 0x80);
ASSERT_EQ(ICSNEOC2_LIN_STATUS_WAKEUP_REQUEST, 0x100);
} }
TEST(icsneoc2, test_icsneoc2_eth_create) TEST(icsneoc2, test_icsneoc2_eth_create)
+77
View File
@@ -2,12 +2,14 @@
#include "icsneo/communication/encoder.h" #include "icsneo/communication/encoder.h"
#include "icsneo/communication/packet/linpacket.h" #include "icsneo/communication/packet/linpacket.h"
#include "icsneo/communication/message/linmessage.h" #include "icsneo/communication/message/linmessage.h"
#include "icsneo/communication/message/transmitmessage.h"
#include "icsneo/communication/packetizer.h" #include "icsneo/communication/packetizer.h"
#include "icsneo/core/ringbuffer.h" #include "icsneo/core/ringbuffer.h"
#include "icsneo/api/eventmanager.h" #include "icsneo/api/eventmanager.h"
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include <vector> #include <vector>
#include <iostream> #include <iostream>
#include <cstring>
using namespace icsneo; using namespace icsneo;
@@ -55,6 +57,16 @@ protected:
0x00, 0x00, 0x00, 0x00,
0xE2, 0x41}; 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 = std::vector<uint8_t> recvBytes =
{0xaa, 0x0c, 0x22, 0x00, {0xaa, 0x0c, 0x22, 0x00,
0x10, 0x00, 0x88, 0x03, 0x10, 0x00, 0x88, 0x03,
@@ -139,6 +151,29 @@ TEST_F(LINEncoderDecoderTest, PacketEncoderControllerHeaderTest) {
EXPECT_EQ(bytestream, testControllerHeaderOnly); 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) { TEST_F(LINEncoderDecoderTest, PacketEncoderControllerWithDataTest) {
std::vector<uint8_t> bytestream; std::vector<uint8_t> bytestream;
auto message = std::make_shared<icsneo::LINMessage>(static_cast<uint8_t>(0x11u)); 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->data, testMessage2->data);
EXPECT_EQ(msg2->checksum, testMessage2->checksum); 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);
}
+84
View File
@@ -0,0 +1,84 @@
#include <gtest/gtest.h>
#include <cstring>
#include "icsneo/communication/driver.h"
#include "icsneo/core/macseccfg.h"
#include "icsneo/disk/neomemorydiskdriver.h"
#include "icsneo/device/tree/radcomet2/radcomet2.h"
#include "icsneo/device/tree/radcomet3/radcomet3.h"
#include "icsneo/device/tree/radgigastar2/radgigastar2.h"
#include "icsneo/device/tree/radmoon2/radmoon2.h"
#include "icsneo/device/tree/radmoon2/radmoon2zl.h"
#include "icsneo/device/tree/radmoon3/radmoon3.h"
using namespace icsneo;
namespace {
class MACsecTestDriver : public Driver {
public:
MACsecTestDriver(const device_eventhandler_t& handler) : Driver(handler) {}
bool open() override { return true; }
bool isOpen() override { return true; }
bool close() override { return true; }
driver_finder_t getFinder() override {
return [](std::vector<FoundDevice>&) {};
}
};
FoundDevice makeFoundDevice(const char* serial) {
FoundDevice found;
std::memcpy(found.serial, serial, sizeof(found.serial) - 1);
found.serial[sizeof(found.serial) - 1] = '\0';
found.makeDriver = [](device_eventhandler_t handler, neodevice_t&) {
return std::make_unique<MACsecTestDriver>(handler);
};
return found;
}
std::vector<Network::NetID> getMACsecNetIDs(const Device& device) {
std::vector<Network::NetID> netIDs;
for(const auto& network : device.getMACsecNetworks())
netIDs.push_back(network.getNetID());
return netIDs;
}
TEST(MACsec, RADMoon2ZLOnlyMapsAutomotiveEthernet) {
RADMoon2 moon2(makeFoundDevice("RM0001"));
RADMoon2ZL moon2zl(makeFoundDevice("RN0001"));
EXPECT_TRUE(getMACsecNetIDs(moon2).empty());
EXPECT_EQ(getMACsecNetIDs(moon2zl), std::vector<Network::NetID>({Network::NetID::AE_01}));
}
TEST(MACsec, RADMoon3MapsIndependentPHYs) {
RADMoon3 moon3(makeFoundDevice("R30001"));
EXPECT_EQ(
getMACsecNetIDs(moon3),
std::vector<Network::NetID>({Network::NetID::AE_01, Network::NetID::ETHERNET_01})
);
}
TEST(MACsec, RADGigastar2MapsBothMACsecPorts) {
RADGigastar2 gigastar2(makeFoundDevice("GT0001"));
EXPECT_EQ(
getMACsecNetIDs(gigastar2),
std::vector<Network::NetID>({Network::NetID::AE_01, Network::NetID::AE_02})
);
}
TEST(MACsec, RADCometsMapOneMACsecPort) {
RADComet2 comet2(makeFoundDevice("RC0300"));
RADComet3 comet3(makeFoundDevice("C30001"));
EXPECT_EQ(getMACsecNetIDs(comet2), std::vector<Network::NetID>({Network::NetID::AE_01}));
EXPECT_EQ(getMACsecNetIDs(comet3), std::vector<Network::NetID>({Network::NetID::AE_01}));
EXPECT_TRUE(MACsecConfig(comet2.getType()));
EXPECT_TRUE(MACsecConfig(comet3.getType()));
}
} // namespace
+221
View File
@@ -0,0 +1,221 @@
#include "gtest/gtest.h"
#include <cstring>
#include <memory>
#include "icsneo/icsneocpp.h"
#include "icsneo/communication/driver.h"
#include "icsneo/communication/message/extendedresponsemessage.h"
#include "icsneo/communication/message/filter/extendedresponsefilter.h"
#include "icsneo/communication/message/tc10statusmessage.h"
#include "icsneo/device/tree/radmoon2/radmoon2.h"
#include "icsneo/device/tree/radmoon2/radmoon2zl.h"
using namespace icsneo;
namespace {
class TC10TestDriver : public Driver {
public:
explicit TC10TestDriver(const device_eventhandler_t& handler) : Driver(handler) {}
bool open() override { opened = true; return true; }
bool isOpen() override { return opened; }
bool close() override { opened = false; return true; }
driver_finder_t getFinder() override { return [](std::vector<FoundDevice>&) {}; }
int writes = 0;
// Replies pushed, in order, when the host writes a command.
std::vector<std::vector<uint8_t>> replies;
protected:
bool writeInternal(const std::vector<uint8_t>&) override {
++writes;
for(const auto& reply : replies)
pushRx(reply.data(), reply.size());
replies.clear();
return true;
}
private:
bool opened = false;
};
std::vector<uint8_t> longPacket(Network::NetID netid, const void* payload, size_t payloadSize) {
const uint16_t packetLength = static_cast<uint16_t>(6 + payloadSize);
std::vector<uint8_t> bytes(packetLength);
bytes[0] = 0xAA;
bytes[1] = 0x00;
bytes[2] = static_cast<uint8_t>(packetLength & 0xff);
bytes[3] = static_cast<uint8_t>((packetLength >> 8) & 0xff);
const auto id = static_cast<uint16_t>(netid);
bytes[4] = static_cast<uint8_t>(id & 0xff);
bytes[5] = static_cast<uint8_t>((id >> 8) & 0xff);
std::memcpy(bytes.data() + 6, payload, payloadSize);
return bytes;
}
std::vector<uint8_t> genericReturn(ExtendedCommand command, ExtendedResponse code) {
ExtendedResponseMessage::PackedGenericResponse packed{};
packed.header.command = ExtendedCommand::GenericReturn;
packed.header.length = static_cast<uint16_t>(sizeof(packed) - sizeof(packed.header));
packed.command = command;
packed.returnCode = code;
return longPacket(Network::NetID::ExtendedCommand, &packed, sizeof(packed));
}
// Extended body of a GetTC10Status reply. `tail` is extra payload past the two status bytes.
std::vector<uint8_t> statusBody(uint8_t wake, uint8_t sleep, std::initializer_list<uint8_t> tail = {}) {
const auto payloadLength = static_cast<uint16_t>(2 + tail.size());
std::vector<uint8_t> body = {
0x3f, 0x00,
static_cast<uint8_t>(payloadLength & 0xff),
static_cast<uint8_t>((payloadLength >> 8) & 0xff),
wake,
sleep,
};
body.insert(body.end(), tail);
return body;
}
class OpenTC10Device {
public:
TC10TestDriver* driver = nullptr;
std::shared_ptr<RADMoon2ZL> device;
OpenTC10Device() {
FoundDevice found;
std::memcpy(found.serial, "RN0001", 6);
found.makeDriver = [this](device_eventhandler_t handler, neodevice_t&) {
auto result = std::make_unique<TC10TestDriver>(handler);
driver = result.get();
return result;
};
device = std::make_shared<RADMoon2ZL>(found);
device->com->readTaskWakeTimeout = std::chrono::milliseconds(20);
EXPECT_TRUE(device->com->open());
}
};
FoundDevice moon2Found() {
FoundDevice found;
std::memcpy(found.serial, "RM0001", 6);
found.makeDriver = [](device_eventhandler_t handler, neodevice_t&) {
return std::make_unique<TC10TestDriver>(handler);
};
return found;
}
}
TEST(TC10, WakeFilterMatchesOnlyThatCommand) {
ExtendedResponseFilter filter(ExtendedCommand::RequestTC10Wake);
EXPECT_TRUE(filter.match(std::make_shared<ExtendedResponseMessage>(
ExtendedCommand::RequestTC10Wake, ExtendedResponse::OperationFailed)));
EXPECT_FALSE(filter.match(std::make_shared<ExtendedResponseMessage>(
ExtendedCommand::RequestTC10Sleep, ExtendedResponse::OK)));
EXPECT_FALSE(filter.match(std::make_shared<ExtendedResponseMessage>(
ExtendedCommand::GetDiskDetails, ExtendedResponse::OK)));
}
TEST(TC10, SleepFilterMatchesOnlyThatCommand) {
ExtendedResponseFilter filter(ExtendedCommand::RequestTC10Sleep);
EXPECT_TRUE(filter.match(std::make_shared<ExtendedResponseMessage>(
ExtendedCommand::RequestTC10Sleep, ExtendedResponse::OK)));
EXPECT_FALSE(filter.match(std::make_shared<ExtendedResponseMessage>(
ExtendedCommand::RequestTC10Wake, ExtendedResponse::OK)));
}
TEST(TC10, UnsupportedDeviceReportsNotSupported) {
auto device = std::make_shared<RADMoon2>(moon2Found());
EXPECT_FALSE(device->requestTC10Wake(Network::NetID::AE_01));
EXPECT_EQ(GetLastError().getType(), APIEvent::Type::NotSupported);
EXPECT_FALSE(device->requestTC10Sleep(Network::NetID::AE_01));
EXPECT_EQ(GetLastError().getType(), APIEvent::Type::NotSupported);
EXPECT_FALSE(device->getTC10Status(Network::NetID::AE_01).has_value());
EXPECT_EQ(GetLastError().getType(), APIEvent::Type::NotSupported);
}
TEST(TC10, WakeAcceptsItsOwnOk) {
OpenTC10Device tc10;
(void)GetLastError();
tc10.driver->replies = {
genericReturn(ExtendedCommand::RequestTC10Sleep, ExtendedResponse::OperationFailed),
genericReturn(ExtendedCommand::RequestTC10Wake, ExtendedResponse::OK),
};
EXPECT_TRUE(tc10.device->requestTC10Wake(Network::NetID::AE_02));
EXPECT_EQ(GetLastError().getType(), APIEvent::Type::NoErrorFound);
EXPECT_EQ(tc10.driver->writes, 1);
}
TEST(TC10, SleepAcceptsItsOwnOk) {
OpenTC10Device tc10;
(void)GetLastError();
tc10.driver->replies = {
genericReturn(ExtendedCommand::RequestTC10Wake, ExtendedResponse::OperationFailed),
genericReturn(ExtendedCommand::RequestTC10Sleep, ExtendedResponse::OK),
};
EXPECT_TRUE(tc10.device->requestTC10Sleep(Network::NetID::AE_01));
EXPECT_EQ(GetLastError().getType(), APIEvent::Type::NoErrorFound);
EXPECT_EQ(tc10.driver->writes, 1);
}
TEST(TC10, WakeReportsDeviceRejection) {
OpenTC10Device tc10;
tc10.driver->replies = {
genericReturn(ExtendedCommand::RequestTC10Sleep, ExtendedResponse::OK),
genericReturn(ExtendedCommand::RequestTC10Wake, ExtendedResponse::OperationFailed),
};
EXPECT_FALSE(tc10.device->requestTC10Wake(Network::NetID::AE_02));
EXPECT_EQ(GetLastError().getType(), APIEvent::Type::TC10RequestFailed);
EXPECT_EQ(tc10.driver->writes, 1);
}
TEST(TC10, SleepReportsDeviceRejection) {
OpenTC10Device tc10;
tc10.driver->replies = {
genericReturn(ExtendedCommand::RequestTC10Wake, ExtendedResponse::OK),
genericReturn(ExtendedCommand::RequestTC10Sleep, ExtendedResponse::InvalidParameter),
};
EXPECT_FALSE(tc10.device->requestTC10Sleep(Network::NetID::AE_01));
EXPECT_EQ(GetLastError().getType(), APIEvent::Type::TC10RequestFailed);
EXPECT_EQ(tc10.driver->writes, 1);
}
TEST(TC10Status, DecodesTheStatusPair) {
auto msg = TC10StatusMessage::DecodeToMessage(statusBody(1, 1));
ASSERT_NE(msg, nullptr);
EXPECT_EQ(msg->wakeStatus, TC10WakeStatus::WakeReceived);
EXPECT_EQ(msg->sleepStatus, TC10SleepStatus::SleepReceived);
}
TEST(TC10Status, RejectsTruncatedOrForeignPayloads) {
EXPECT_EQ(TC10StatusMessage::DecodeToMessage({}), nullptr);
auto bytes = statusBody(0, 0);
EXPECT_EQ(TC10StatusMessage::DecodeToMessage({bytes.begin(), bytes.begin() + 5}), nullptr);
std::vector<uint8_t> shortLength = {0x3f, 0x00, 0x01, 0x00, 0x00, 0x00};
EXPECT_EQ(TC10StatusMessage::DecodeToMessage(shortLength), nullptr);
std::vector<uint8_t> foreign = {0x3d, 0x00, 0x02, 0x00, 0x00, 0x00};
EXPECT_EQ(TC10StatusMessage::DecodeToMessage(foreign), nullptr);
}
TEST(TC10Status, DropsBytesAfterTheStatusPair) {
// Tail is little-endian AE_02 (37). The decoded message has no network, so this still succeeds.
auto msg = TC10StatusMessage::DecodeToMessage(statusBody(0, 1, {37, 0}));
ASSERT_NE(msg, nullptr);
EXPECT_EQ(msg->wakeStatus, TC10WakeStatus::NoWakeReceived);
EXPECT_EQ(msg->sleepStatus, TC10SleepStatus::SleepReceived);
}
TEST(TC10, StatusReturnsTheDecodedPair) {
OpenTC10Device tc10;
(void)GetLastError();
const auto body = statusBody(1, 0);
tc10.driver->replies = {longPacket(Network::NetID::ExtendedCommand, body.data(), body.size())};
const auto status = tc10.device->getTC10Status(Network::NetID::AE_01);
ASSERT_TRUE(status.has_value());
EXPECT_EQ(status->wakeStatus, TC10WakeStatus::WakeReceived);
EXPECT_EQ(status->sleepStatus, TC10SleepStatus::NoSleepReceived);
EXPECT_EQ(GetLastError().getType(), APIEvent::Type::NoErrorFound);
EXPECT_EQ(tc10.driver->writes, 1);
}