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

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

Verified on macOS 26 (Tahoe, arm64) with a ValueCAN 4-2 (V2D805).
2026-05-22 09:12:58 -04:00
77 changed files with 255 additions and 763 deletions
+24
View File
@@ -35,6 +35,30 @@ unit_test windows/x64:
- libicsneo-win-x64 - libicsneo-win-x64
timeout: 5m timeout: 5m
build windows/x86:
stage: build
script:
- cmd /C ci\build-windows32.bat
artifacts:
when: always
paths:
- build
expire_in: 3 days
tags:
- libicsneo-win-x64
unit_test windows/x86:
stage: unit_test
script:
- build\libicsneo-unit-tests.exe
dependencies:
- build windows/x86
needs:
- build windows/x86
tags:
- libicsneo-win-x64
timeout: 5m
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
# Ubuntu # Ubuntu
#------------------------------------------------------------------------------- #-------------------------------------------------------------------------------
+1 -3
View File
@@ -82,7 +82,7 @@ if(MSVC)
add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING) add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
add_definitions(-D_ITERATOR_DEBUG_LEVEL=0) add_definitions(-D_ITERATOR_DEBUG_LEVEL=0)
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
set(LIBICSNEO_COMPILER_WARNINGS -Wall -Wno-unknown-pragmas) set(LIBICSNEO_COMPILER_WARNINGS -Wall -Wno-switch -Wno-unknown-pragmas)
endif() endif()
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
@@ -235,7 +235,6 @@ set(SRC_FILES
communication/message/networkmutexmessage.cpp communication/message/networkmutexmessage.cpp
communication/message/clientidmessage.cpp communication/message/clientidmessage.cpp
communication/message/transmitmessage.cpp communication/message/transmitmessage.cpp
communication/message/spiportkeymessage.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
@@ -346,7 +345,6 @@ add_library(icsneocpp
api/icsneocpp/icsneocpp.cpp api/icsneocpp/icsneocpp.cpp
api/icsneocpp/event.cpp api/icsneocpp/event.cpp
api/icsneocpp/eventmanager.cpp api/icsneocpp/eventmanager.cpp
api/icsneocpp/heartbeat.cpp
api/icsneocpp/version.cpp api/icsneocpp/version.cpp
${SRC_FILES} ${SRC_FILES}
) )
-1
View File
@@ -45,7 +45,6 @@ Instructions for installing each API can be found in its respective documentatio
- RAD-Pluto - RAD-Pluto
- RAD-Star 2 - RAD-Star 2
- RAD-SuperMoon - RAD-SuperMoon
- RAD-wBMS
- ValueCAN 3 - ValueCAN 3
- ValueCAN 4 - ValueCAN 4
+11 -20
View File
@@ -5,7 +5,6 @@
#include "icsneo/device/devicefinder.h" #include "icsneo/device/devicefinder.h"
#include "icsneo/icsneocpp.h" #include "icsneo/icsneocpp.h"
#include "icsneo/communication/io.h" #include "icsneo/communication/io.h"
#include "icsneo/communication/network.h"
#include <string> #include <string>
#include <vector> #include <vector>
@@ -466,13 +465,11 @@ icsneoc2_error_t icsneoc2_device_pcb_serial_get(const icsneoc2_device_t* device,
return icsneoc2_error_invalid_type; return icsneoc2_error_invalid_type;
} }
const auto& data = *pcbSerial; const auto& data = *pcbSerial;
if(!value) { if(value) {
*value_length = data.size(); size_t copyLen = std::min(*value_length, data.size());
return icsneoc2_error_success; std::copy(data.begin(), data.begin() + copyLen, value);
} }
size_t copyLen = std::min(*value_length, data.size()); *value_length = data.size();
std::copy(data.begin(), data.begin() + copyLen, value);
*value_length = copyLen;
return icsneoc2_error_success; return icsneoc2_error_success;
} }
@@ -506,32 +503,26 @@ icsneoc2_error_t icsneoc2_device_mac_addresses_enumerate(const icsneoc2_device_t
} }
tail = node; tail = node;
} }
*mac_entries = head;
return icsneoc2_error_success; return icsneoc2_error_success;
} }
icsneoc2_error_t icsneoc2_mac_network_id_get(const icsneoc2_mac_addr_entry_t* mac_address, icsneoc2_netid_t* network_id) { icsneoc2_error_t icsneoc2_mac_network_id_get(const icsneoc2_mac_addr_entry_t* mac_address, _icsneoc2_netid_t* network_id) {
if(!mac_address || !network_id) { if(!mac_address || !network_id) {
return icsneoc2_error_invalid_parameters; return icsneoc2_error_invalid_parameters;
} }
const auto netid = static_cast<Network::NetID>(mac_address->network_id); *network_id = static_cast<_icsneoc2_netid_t>(mac_address->network_id);
*network_id = Network::GetCoreMiniNetworkFromNetID(netid).has_value()
? mac_address->network_id
: static_cast<icsneoc2_netid_t>(icsneoc2_netid_invalid);
return icsneoc2_error_success; return icsneoc2_error_success;
} }
icsneoc2_error_t icsneoc2_mac_address_get(const icsneoc2_mac_addr_entry_t* mac_address, uint8_t* value, size_t* value_length) { icsneoc2_error_t icsneoc2_mac_address_get(const icsneoc2_mac_addr_entry_t* mac_address, uint8_t* value, size_t* value_length) {
if(!mac_address || !value_length) { if(!mac_address || !value || !value_length) {
return icsneoc2_error_invalid_parameters; return icsneoc2_error_invalid_parameters;
} }
if(!value) { if(value) {
*value_length = static_cast<size_t>(ICSNEO_MAC_ADDRESS_LEN); size_t copyLen = std::min(*value_length, static_cast<size_t>(ICSNEO_MAC_ADDRESS_LEN));
return icsneoc2_error_success; std::copy(mac_address->address, mac_address->address + copyLen, value);
} }
size_t copyLen = std::min(*value_length, static_cast<size_t>(ICSNEO_MAC_ADDRESS_LEN)); *value_length = static_cast<size_t>(ICSNEO_MAC_ADDRESS_LEN);
std::copy(mac_address->address, mac_address->address + copyLen, value);
*value_length = copyLen;
return icsneoc2_error_success; return icsneoc2_error_success;
} }
-2
View File
@@ -462,8 +462,6 @@ const char* APIEvent::DescriptionForType(Type type) {
return TOO_MANY_EVENTS; return TOO_MANY_EVENTS;
case Type::Unknown: case Type::Unknown:
return UNKNOWN; return UNKNOWN;
case Type::Any:
break;
} }
return INVALID; return INVALID;
} }
-53
View File
@@ -1,53 +0,0 @@
#include "icsneo/api/heartbeat.h"
#include "icsneo/api/lifetime.h"
#include "icsneo/device/device.h"
using namespace icsneo;
Heartbeat::Heartbeat(Device& device) :
device(device), mode(device.isOnline() ? Mode::Passive : Mode::Active), thread(&Heartbeat::run, this) {
}
Heartbeat::~Heartbeat() {
{
std::lock_guard lk(mutex);
stop = true;
}
cv.notify_one();
thread.join();
}
void Heartbeat::run() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
auto filter = std::make_shared<MessageFilter>(Message::Type::ResetStatus);
bool status = false;
auto cbHandle = device.com->addMessageCallback(std::make_shared<MessageCallback>(filter, [&](std::shared_ptr<Message>) {
{
std::lock_guard lk(mutex);
status = true;
}
cv.notify_one();
}));
Lifetime cbLifetime([&] {
device.com->removeMessageCallback(cbHandle);
});
while(true) {
std::unique_lock lk(mutex);
if(mode == Mode::Active) {
if(cv.wait_for(lk, std::chrono::milliseconds(100), [&] { return stop; })) {
break;
}
device.com->sendCommand(Command::RequestStatusUpdate);
}
if(!cv.wait_for(lk, std::chrono::seconds(2), [&] { return status || stop; })) {
// we disconnect instead of close because it indicates to the user that a cleanup is still required (our thread join)
device.report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
device.com->driver->setIsDisconnected(true);
break;
}
if(stop)
break;
status = false;
}
}
-2
View File
@@ -1088,8 +1088,6 @@ int LegacyDLLExport icsneoGetDeviceSettingsType(void* hObject, EPlasmaIonVnetCha
case NEODEVICE_FIRE3_FLEXRAY: case NEODEVICE_FIRE3_FLEXRAY:
*pDeviceSettingsType = DeviceFire3FlexraySettingsType; *pDeviceSettingsType = DeviceFire3FlexraySettingsType;
break; break;
case NEODEVICE_RAD_BMS:
*pDeviceSettingsType = DeviceRADBMSSettingsType;
default: default:
return 0; return 0;
} }
@@ -36,7 +36,6 @@ void init_devicetype(pybind11::module_& m) {
.value("RADEpsilon", DeviceType::Enum::RADEpsilon) .value("RADEpsilon", DeviceType::Enum::RADEpsilon)
.value("RADEpsilonXL", DeviceType::Enum::RADEpsilonXL) .value("RADEpsilonXL", DeviceType::Enum::RADEpsilonXL)
.value("RADGalaxy2", DeviceType::Enum::RADGalaxy2) .value("RADGalaxy2", DeviceType::Enum::RADGalaxy2)
.value("RADwBMS", DeviceType::Enum::RADwBMS)
.value("RADMoon3", DeviceType::Enum::RADMoon3) .value("RADMoon3", DeviceType::Enum::RADMoon3)
.value("RADGemini", DeviceType::Enum::RADGemini) .value("RADGemini", DeviceType::Enum::RADGemini)
.value("RADComet2", DeviceType::Enum::RADComet2) .value("RADComet2", DeviceType::Enum::RADComet2)
+2 -1
View File
@@ -1,6 +1,7 @@
#!/bin/sh #!/bin/sh
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_EXAMPLES=ON -DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_ENABLE_TCP=OFF || exit 1 cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_EXAMPLES=ON \
-DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_ENABLE_TCP=OFF || exit 1
cmake --build build || exit 1 cmake --build build || exit 1
+2 -1
View File
@@ -3,6 +3,7 @@
mkdir build >nul 2>&1 mkdir build >nul 2>&1
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DLIBICSNEO_BUILD_UNIT_TESTS=ON-DLIBICSNEO_ENABLE_TCP=ON || exit /b 1 cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_UNIT_TESTS=ON ^
-DLIBICSNEO_ENABLE_TCP=ON || exit /b 1
cmake --build build || exit /b 1 cmake --build build || exit /b 1
-7
View File
@@ -26,7 +26,6 @@
#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/spiportkeymessage.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"
@@ -342,9 +341,6 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
case ExtendedCommand::LiveData: case ExtendedCommand::LiveData:
result = HardwareLiveDataPacket::DecodeToMessage(packet->data, report); result = HardwareLiveDataPacket::DecodeToMessage(packet->data, report);
return true; return true;
case ExtendedCommand::ExecuteSPIPortKeyOperation:
result = SPIPortKeyMessage::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;
@@ -567,9 +563,6 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
} }
break; break;
} }
default:
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
return false;
} }
// For the moment other types of messages will automatically be decoded as raw messages // For the moment other types of messages will automatically be decoded as raw messages
+1 -3
View File
@@ -234,9 +234,7 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
result = packetizer.packetWrap(result, false); result = packetizer.packetWrap(result, false);
return true; return true;
} }
default: break;
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
return false; // The message was not a properly formed Message
} }
// Early returns may mean we don't reach this far, check the type you're concerned with // Early returns may mean we don't reach this far, check the type you're concerned with
-2
View File
@@ -163,8 +163,6 @@ void A2BMessage::setChannelSample(Direction dir, uint8_t channel, size_t frame,
case PCMType::L24: case PCMType::L24:
sampleToSet = sampleToSet << 8; sampleToSet = sampleToSet << 8;
break; break;
case PCMType::L32:
break;
} }
if(channelSize16) { if(channelSize16) {
+1 -1
View File
@@ -35,7 +35,7 @@ bool EthPhyMessage::appendPhyMessage(bool writeEnable, bool clause45, uint8_t ph
bool EthPhyMessage::appendPhyMessage(std::shared_ptr<PhyMessage> message) bool EthPhyMessage::appendPhyMessage(std::shared_ptr<PhyMessage> message)
{ {
if(message) if(message != nullptr)
{ {
messages.push_back(message); messages.push_back(message);
return true; return true;
@@ -1,27 +0,0 @@
#include "icsneo/communication/message/spiportkeymessage.h"
#include "icsneo/communication/message/extendedresponsemessage.h"
#include "icsneo/communication/command.h"
#include "icsneo/communication/network.h"
using namespace icsneo;
std::shared_ptr<SPIPortKeyMessage> SPIPortKeyMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
if(bytestream.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
return nullptr;
const auto* hdr = reinterpret_cast<const ExtendedResponseMessage::ResponseHeader*>(bytestream.data());
if(hdr->command != ExtendedCommand::ExecuteSPIPortKeyOperation)
return nullptr;
const size_t required = sizeof(ExtendedResponseMessage::ResponseHeader) + sizeof(SPIPortKeyPacket);
if(bytestream.size() < required)
return nullptr;
auto msg = std::make_shared<SPIPortKeyMessage>();
const auto* packet = reinterpret_cast<const SPIPortKeyPacket*>(bytestream.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
msg->isKeyLoaded = packet->isKeyLoaded;
return msg;
}
@@ -142,8 +142,6 @@ void MultiChannelCommunication::hidReadTask() {
dispatchMessage(msg); dispatchMessage(msg);
break; break;
} }
default:
break;
} }
if(currentQueue == nullptr) { if(currentQueue == nullptr) {
+114 -54
View File
@@ -92,6 +92,10 @@ Device::~Device() {
disableMessagePolling(); disableMessagePolling();
if(isOpen()) if(isOpen())
close(); close();
if(heartbeatThread.joinable()) {
stopHeartbeatThread = true;
heartbeatThread.join();
}
} }
uint16_t Device::getTimestampResolution() const { uint16_t Device::getTimestampResolution() const {
@@ -284,8 +288,6 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
return false; return false;
} }
startHeartbeat();
APIEvent::Type attemptErr = attemptToBeginCommunication(); APIEvent::Type attemptErr = attemptToBeginCommunication();
if(attemptErr != APIEvent::Type::NoErrorFound) { if(attemptErr != APIEvent::Type::NoErrorFound) {
// We could not communicate with the device, let's see if an extension can // We could not communicate with the device, let's see if an extension can
@@ -332,6 +334,79 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
EventManager::GetInstance().cancelErrorDowngradingOnCurrentThread(); EventManager::GetInstance().cancelErrorDowngradingOnCurrentThread();
} }
MessageFilter filter;
filter.includeInternalInAny = true;
internalHandlerCallbackID = com->addMessageCallback(std::make_shared<MessageCallback>(filter, [this](std::shared_ptr<Message> message) {
handleInternalMessage(message);
}));
// Clear the previous heartbeat thread, in case open() was called on this instance more than once
if(heartbeatThread.joinable())
heartbeatThread.join();
stopHeartbeatThread = false;
heartbeatThread = std::thread([this]() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
MessageFilter filter;
filter.includeInternalInAny = true;
std::condition_variable heartbeatCV;
std::mutex receivedMessageMutex;
bool receivedMessage = false;
auto messageReceivedCallbackID = com->addMessageCallback(std::make_shared<MessageCallback>(filter, [&](std::shared_ptr<Message>) {
{
std::scoped_lock<std::mutex> lk(receivedMessageMutex);
receivedMessage = true;
}
heartbeatCV.notify_all();
}));
// Give the device time to get situated
auto i = 150;
while(!stopHeartbeatThread && i != 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(50));
i--;
}
while(!stopHeartbeatThread) {
std::unique_lock<std::mutex> recvLk(receivedMessageMutex);
// Wait for 110ms for a possible heartbeat
if(heartbeatCV.wait_for(recvLk, std::chrono::milliseconds(110), [&]() { return receivedMessage; })) {
receivedMessage = false;
} else if(!stopHeartbeatThread) { // Add this condition here in case the thread was stopped while waiting for the last message
// Some communication, such as the bootloader and extractor interfaces, must
// redirect the input stream from the device as it will no longer be in the
// packet format we expect here. As a result, status updates will not reach
// us here and suppressDisconnects() must be used. We don't want to request
// a status and then redirect the stream, as we'll then be polluting an
// otherwise quiet stream. This lock makes sure suppressDisconnects() will
// block until we've either gotten our status update or disconnected from
// the device.
std::unique_lock<std::mutex> lk(heartbeatMutex);
if(heartbeatSuppressed()) continue;
// No heartbeat received, request a status
com->sendCommand(Command::RequestStatusUpdate);
// Check if we got a message, and if not, if settings are being applied
if(heartbeatCV.wait_for(recvLk, std::chrono::milliseconds(3500), [&](){ return receivedMessage; })) {
receivedMessage = false;
} else {
if(!stopHeartbeatThread) {
close();
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
}
break;
}
}
}
com->removeMessageCallback(messageReceivedCallbackID);
});
if(supportsLiveData()) if(supportsLiveData())
clearAllLiveData(); clearAllLiveData();
@@ -428,7 +503,7 @@ bool Device::close() {
return false; return false;
} }
stopHeartbeat(); stopHeartbeatThread = true;
if (isMessagePollingEnabled()) { if (isMessagePollingEnabled()) {
disableMessagePolling(); disableMessagePolling();
@@ -459,15 +534,31 @@ bool Device::goOnline() {
if(!enableNetworkCommunication(true, onlineTimeoutMs)) if(!enableNetworkCommunication(true, onlineTimeoutMs))
return false; return false;
auto startTime = std::chrono::system_clock::now();
ledState = LEDState::Online; ledState = LEDState::Online;
updateLEDState(); updateLEDState();
// (re)start the keeponline std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(Network::NetID::Reset_Status);
keeponline = std::make_unique<Periodic>([this] { filter->includeInternalInAny = true;
static std::vector<uint8_t> timeoutBytes = std::vector<uint8_t>((uint8_t*)&onlineTimeoutMs, (uint8_t*)&onlineTimeoutMs + sizeof(onlineTimeoutMs));
return com->sendCommand(Command::KeepAlive, timeoutBytes); // Wait until communication is enabled or 5 seconds, whichever comes first
}, std::chrono::milliseconds(onlineTimeoutMs / 4)); while((std::chrono::system_clock::now() - startTime) < std::chrono::seconds(5)) {
if(latestResetStatus && latestResetStatus->comEnabled)
break;
bool failOut = false;
com->waitForMessageSync([this, &failOut]() {
if(!com->sendCommand(Command::RequestStatusUpdate)) {
failOut = true;
return false;
}
return true;
}, filter, std::chrono::milliseconds(100));
if(failOut)
return false;
}
if(supportsNetworkMutex) { if(supportsNetworkMutex) {
assignedClientId = com->getClientIDSync(); assignedClientId = com->getClientIDSync();
@@ -484,26 +575,25 @@ bool Device::goOnline() {
case NetworkMutexEvent::Acquired: case NetworkMutexEvent::Acquired:
lockedNetworks.emplace(*netMutexMsg->networks.begin()); lockedNetworks.emplace(*netMutexMsg->networks.begin());
break; break;
case NetworkMutexEvent::Expired:
case NetworkMutexEvent::Preempted:
case NetworkMutexEvent::Released: { case NetworkMutexEvent::Released: {
auto it = lockedNetworks.find(*netMutexMsg->networks.begin()); auto it = lockedNetworks.find(*netMutexMsg->networks.begin());
if (it != lockedNetworks.end()) if (it != lockedNetworks.end())
lockedNetworks.erase(it); lockedNetworks.erase(it);
break; break;
} }
case NetworkMutexEvent::Queued:
break;
} }
} }
}); });
} }
} }
online = true; // (re)start the keeponline
keeponline = std::make_unique<Periodic>([this] {
static std::vector<uint8_t> timeoutBytes = std::vector<uint8_t>((uint8_t*)&onlineTimeoutMs, (uint8_t*)&onlineTimeoutMs + sizeof(onlineTimeoutMs));
return com->sendCommand(Command::KeepAlive, timeoutBytes);
}, std::chrono::milliseconds(onlineTimeoutMs / 4));
// restart the heartbeat in online mode online = true;
restartHeartbeat();
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOnline(); return true; }); forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOnline(); return true; });
@@ -511,19 +601,15 @@ bool Device::goOnline() {
} }
bool Device::goOffline() { bool Device::goOffline() {
online = false;
keeponline.reset(); keeponline.reset();
// restart the heartbeat in offline mode
restartHeartbeat();
if(networkMutexCallbackHandle) if(networkMutexCallbackHandle)
removeMessageCallback(*networkMutexCallbackHandle); removeMessageCallback(*networkMutexCallbackHandle);
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOffline(); return true; }); forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOffline(); return true; });
if(isDisconnected()) { if(isDisconnected()) {
online = false;
return true; return true;
} }
@@ -539,6 +625,8 @@ bool Device::goOffline() {
updateLEDState(); updateLEDState();
online = false;
return true; return true;
} }
@@ -1900,9 +1988,11 @@ void Device::stopScriptStatusThreadIfNecessary(std::unique_lock<std::mutex> lk)
} }
Lifetime Device::suppressDisconnects() { Lifetime Device::suppressDisconnects() {
stopHeartbeat(); std::lock_guard<std::mutex> lk(heartbeatMutex);
heartbeatSuppressedByUser++;
return Lifetime([this] { return Lifetime([this] {
startHeartbeat(); std::lock_guard<std::mutex> lk2(heartbeatMutex);
heartbeatSuppressedByUser--;
}); });
} }
@@ -2038,18 +2128,6 @@ std::optional<EthPhyMessage> Device::sendEthPhyMsg(const EthPhyMessage& message,
return std::make_optional<EthPhyMessage>(*retMsg); return std::make_optional<EthPhyMessage>(*retMsg);
} }
bool Device::sendSPIPortKeyOperation(uint8_t portIndex, SPIPortKeyMessage::Operation op, std::array<uint8_t, 16> key) {
std::vector<uint8_t> args(sizeof(SPIPortKeyMessage::SPIPortKeyPacket));
auto& params = *reinterpret_cast<SPIPortKeyMessage::SPIPortKeyPacket*>(args.data());
params.op = op;
params.portIndex = portIndex;
std::copy(key.begin(), key.end(), params.key);
if(!com->sendCommand(ExtendedCommand::ExecuteSPIPortKeyOperation, args)) {
return false;
}
return true;
}
std::optional<bool> Device::SetRootDirectoryEntryFlags(uint8_t mask, uint8_t values, uint32_t collectionEntryByteAddress) std::optional<bool> Device::SetRootDirectoryEntryFlags(uint8_t mask, uint8_t values, uint32_t collectionEntryByteAddress)
{ {
if(!supportsWiVI()) if(!supportsWiVI())
@@ -3219,12 +3297,11 @@ bool Device::findVSAOffsetFromTimepoint(ICSClock::time_point point, uint64_t& vs
std::shared_ptr<VSA> midRecord; std::shared_ptr<VSA> midRecord;
auto midRecordStatus = parser.getRecordFromBytes(buffer.data(), Disk::SectorSize, midRecord); auto midRecordStatus = parser.getRecordFromBytes(buffer.data(), Disk::SectorSize, midRecord);
switch(midRecordStatus) { switch(midRecordStatus) {
case VSAParser::RecordParseStatus::NotARecordStart: { case VSAParser::RecordParseStatus::NotARecordStart:
// This part of the buffer does not contain records // This part of the buffer does not contain records
rightIndex = midIndex - 1; rightIndex = midIndex - 1;
continue; continue;
} case VSAParser::RecordParseStatus::ConsecutiveExtended:
case VSAParser::RecordParseStatus::ConsecutiveExtended: {
// We dropped in the middle of an extended message record // We dropped in the middle of an extended message record
auto extendedRecord = std::dynamic_pointer_cast<VSAExtendedMessage>(midRecord); auto extendedRecord = std::dynamic_pointer_cast<VSAExtendedMessage>(midRecord);
uint64_t pos = readPos; uint64_t pos = readPos;
@@ -3239,9 +3316,6 @@ bool Device::findVSAOffsetFromTimepoint(ICSClock::time_point point, uint64_t& vs
midIndex = (pos - firstOffset) / Disk::SectorSize; midIndex = (pos - firstOffset) / Disk::SectorSize;
midRecord = extendedRecord; midRecord = extendedRecord;
break; break;
}
default:
break;
} }
if(midIndex <= leftIndex) { if(midIndex <= leftIndex) {
// Extended records cause problems with binary search // Extended records cause problems with binary search
@@ -4082,17 +4156,3 @@ bool Device::unlockAllNetworks()
return true; return true;
} }
void Device::startHeartbeat() {
if(!heartbeat)
heartbeat = std::make_unique<Heartbeat>(*this);
}
void Device::stopHeartbeat() {
heartbeat.reset();
}
void Device::restartHeartbeat() {
stopHeartbeat();
startHeartbeat();
}
-8
View File
@@ -241,10 +241,6 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
makeIfSerialMatches<RADSupermoon>(dev, newFoundDevices); makeIfSerialMatches<RADSupermoon>(dev, newFoundDevices);
#endif #endif
#ifdef __RADWBMS_H_
makeIfSerialMatches<RADwBMS>(dev, newFoundDevices);
#endif
#ifdef __VALUECAN3_H_ #ifdef __VALUECAN3_H_
makeIfSerialRangeMatches<ValueCAN3>(dev, newFoundDevices); makeIfSerialRangeMatches<ValueCAN3>(dev, newFoundDevices);
#endif #endif
@@ -408,10 +404,6 @@ const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
RADSupermoon::DEVICE_TYPE, RADSupermoon::DEVICE_TYPE,
#endif #endif
#ifdef __RADWBMS_H_
RADwBMS::DEVICE_TYPE,
#endif
#ifdef __VALUECAN3_H_ #ifdef __VALUECAN3_H_
ValueCAN3::DEVICE_TYPE, ValueCAN3::DEVICE_TYPE,
#endif #endif
+17 -24
View File
@@ -1,16 +1,9 @@
#include "icsneo/device/device.h"
#include "icsneo/device/idevicesettings.h" #include "icsneo/device/idevicesettings.h"
#include "icsneo/communication/message/filter/main51messagefilter.h" #include "icsneo/communication/message/filter/main51messagefilter.h"
#include <cstring> #include <cstring>
using namespace icsneo; using namespace icsneo;
IDeviceSettings::IDeviceSettings(Device* device, size_t size)
: device(device), report(device->report), structSize(size) {}
IDeviceSettings::IDeviceSettings(warn_t createInoperableSettings, Device* device)
: disabled(true), readonly(true), report(device->report), structSize(0) { (void)createInoperableSettings; }
std::optional<uint16_t> IDeviceSettings::CalculateGSChecksum(const std::vector<uint8_t>& settings) { std::optional<uint16_t> IDeviceSettings::CalculateGSChecksum(const std::vector<uint8_t>& settings) {
const uint16_t* p = reinterpret_cast<const uint16_t*>(settings.data()); const uint16_t* p = reinterpret_cast<const uint16_t*>(settings.data());
size_t words = settings.size(); size_t words = settings.size();
@@ -173,7 +166,7 @@ bool IDeviceSettings::refresh() {
} }
std::vector<uint8_t> rxSettings; std::vector<uint8_t> rxSettings;
bool ret = device->com->getSettingsSync(rxSettings); bool ret = com->getSettingsSync(rxSettings);
if(!ret) { if(!ret) {
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error); report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
return false; return false;
@@ -238,10 +231,10 @@ bool IDeviceSettings::apply(bool temporary) {
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size()); memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
// Pause I/O with the device while the settings are applied // Pause I/O with the device while the settings are applied
device->stopHeartbeat(); applyingSettings = true;
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() { std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
return device->com->sendCommand(Command::SetSettings, bytestream); return com->sendCommand(Command::SetSettings, bytestream);
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000))); }, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000)));
if(!msg || msg->data[0] != 1) { // We did not receive a response if(!msg || msg->data[0] != 1) { // We did not receive a response
@@ -266,8 +259,8 @@ bool IDeviceSettings::apply(bool temporary) {
bytestream[6] = (uint8_t)(*gsChecksum >> 8); bytestream[6] = (uint8_t)(*gsChecksum >> 8);
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size()); memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() { msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
return device->com->sendCommand(Command::SetSettings, bytestream); return com->sendCommand(Command::SetSettings, bytestream);
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000))); }, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000)));
if(!msg || msg->data[0] != 1) { if(!msg || msg->data[0] != 1) {
// Attempt to get the settings from the device so we're up to date if possible // Attempt to get the settings from the device so we're up to date if possible
@@ -279,12 +272,12 @@ bool IDeviceSettings::apply(bool temporary) {
} }
if(!temporary) { if(!temporary) {
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() { msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
return device->com->sendCommand(Command::SaveSettings); return com->sendCommand(Command::SaveSettings);
}, std::make_shared<Main51MessageFilter>(Command::SaveSettings), std::chrono::milliseconds(5000))); }, std::make_shared<Main51MessageFilter>(Command::SaveSettings), std::chrono::milliseconds(5000)));
} }
device->startHeartbeat(); applyingSettings = false;
refresh(); // Refresh our buffer with what the device has, whether we were successful or not refresh(); // Refresh our buffer with what the device has, whether we were successful or not
@@ -306,10 +299,10 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
return false; return false;
} }
device->stopHeartbeat(); applyingSettings = true;
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() { std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
return device->com->sendCommand(Command::SetDefaultSettings); return com->sendCommand(Command::SetDefaultSettings);
}, std::make_shared<Main51MessageFilter>(Command::SetDefaultSettings), std::chrono::milliseconds(5000))); }, std::make_shared<Main51MessageFilter>(Command::SetDefaultSettings), std::chrono::milliseconds(5000)));
if(!msg || msg->data[0] != 1) { if(!msg || msg->data[0] != 1) {
// Attempt to get the settings from the device so we're up to date if possible // Attempt to get the settings from the device so we're up to date if possible
@@ -343,8 +336,8 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
bytestream[6] = (uint8_t)(*gsChecksum >> 8); bytestream[6] = (uint8_t)(*gsChecksum >> 8);
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size()); memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() { msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
return device->com->sendCommand(Command::SetSettings, bytestream); return com->sendCommand(Command::SetSettings, bytestream);
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000))); }, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000)));
if(!msg || msg->data[0] != 1) { if(!msg || msg->data[0] != 1) {
// Attempt to get the settings from the device so we're up to date if possible // Attempt to get the settings from the device so we're up to date if possible
@@ -356,12 +349,12 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
} }
if(!temporary) { if(!temporary) {
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() { msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
return device->com->sendCommand(Command::SaveSettings); return com->sendCommand(Command::SaveSettings);
}, std::make_shared<Main51MessageFilter>(Command::SaveSettings), std::chrono::milliseconds(5000))); }, std::make_shared<Main51MessageFilter>(Command::SaveSettings), std::chrono::milliseconds(5000)));
} }
device->startHeartbeat(); applyingSettings = false;
refresh(); // Refresh our buffer with what the device has, whether we were successful or not refresh(); // Refresh our buffer with what the device has, whether we were successful or not
+1 -1
View File
@@ -112,7 +112,7 @@ int main() {
} }
printf("MACs: %u entr%s\n", mac_count, mac_count == 1 ? "y" : "ies"); printf("MACs: %u entr%s\n", mac_count, mac_count == 1 ? "y" : "ies");
for(icsneoc2_mac_addr_entry_t* cur = macs; cur; cur = icsneoc2_mac_addresses_next(cur)) { for(icsneoc2_mac_addr_entry_t* cur = macs; cur; cur = icsneoc2_mac_addresses_next(cur)) {
icsneoc2_netid_t network_id; _icsneoc2_netid_t network_id;
icsneoc2_mac_network_id_get(cur, &network_id); icsneoc2_mac_network_id_get(cur, &network_id);
printf(" Network %-5u ", (unsigned)network_id); printf(" Network %-5u ", (unsigned)network_id);
uint8_t address[6]; uint8_t address[6];
-38
View File
@@ -1,38 +0,0 @@
#ifndef __HEARTBEAT_H__
#define __HEARTBEAT_H__
#ifdef __cplusplus
#include <thread>
#include <condition_variable>
#include <mutex>
namespace icsneo {
class Device;
class Heartbeat {
public:
Heartbeat(Device& device);
~Heartbeat();
private:
enum class Mode {
Passive, // ResetStatus messages arrive without requesting
Active, // RequestStatusUpdate needs to be sent
};
Device& device;
const Mode mode;
bool stop = false;
std::mutex mutex;
std::condition_variable cv;
std::thread thread;
void run();
};
} // icsneo
#endif // __cplusplus
#endif // __HEARTBEAT_H__
-1
View File
@@ -77,7 +77,6 @@ enum class ExtendedCommand : uint16_t {
TransmitCoreminiMessage = 0x0028, TransmitCoreminiMessage = 0x0028,
GenericBinaryInfo = 0x0030, GenericBinaryInfo = 0x0030,
LiveData = 0x0035, LiveData = 0x0035,
ExecuteSPIPortKeyOperation = 0x003C,
RequestTC10Wake = 0x003D, RequestTC10Wake = 0x003D,
RequestTC10Sleep = 0x003E, RequestTC10Sleep = 0x003E,
GetTC10Status = 0x003F, GetTC10Status = 0x003F,
@@ -14,7 +14,6 @@
#include "icsneo/communication/message/extendedresponsemessage.h" #include "icsneo/communication/message/extendedresponsemessage.h"
#include "icsneo/device/deviceversion.h" #include "icsneo/device/deviceversion.h"
#include "icsneo/api/eventmanager.h" #include "icsneo/api/eventmanager.h"
#include "icsneo/api/heartbeat.h"
#include "icsneo/communication/packetizer.h" #include "icsneo/communication/packetizer.h"
#include "icsneo/communication/encoder.h" #include "icsneo/communication/encoder.h"
#include "icsneo/communication/decoder.h" #include "icsneo/communication/decoder.h"
+1 -1
View File
@@ -31,7 +31,6 @@ public:
virtual driver_finder_t getFinder() = 0; virtual driver_finder_t getFinder() = 0;
inline bool isDisconnected() const { return disconnected; }; inline bool isDisconnected() const { return disconnected; };
inline void setIsDisconnected(bool isDisconnected) { disconnected = isDisconnected; }
inline bool isClosing() const { return closing; } inline bool isClosing() const { return closing; }
bool waitForRx(size_t limit, std::chrono::milliseconds timeout); bool waitForRx(size_t limit, std::chrono::milliseconds timeout);
@@ -63,6 +62,7 @@ protected:
}; };
inline void setIsClosing(bool isClosing) { closing = isClosing; } inline void setIsClosing(bool isClosing) { closing = isClosing; }
inline void setIsDisconnected(bool isDisconnected) { disconnected = isDisconnected; }
// Overridable in case the driver doesn't want to use writeTask and writeQueue // Overridable in case the driver doesn't want to use writeTask and writeQueue
virtual bool writeQueueFull() { return writeQueue.size_approx() > writeQueueSize; } virtual bool writeQueueFull() { return writeQueue.size_approx() > writeQueueSize; }
@@ -6,6 +6,7 @@
#include "icsneo/communication/packet/ethphyregpacket.h" #include "icsneo/communication/packet/ethphyregpacket.h"
#include "icsneo/communication/message/message.h" #include "icsneo/communication/message/message.h"
#include "icsneo/communication/packet.h" #include "icsneo/communication/packet.h"
#include "icsneo/api/eventmanager.h"
#include <vector> #include <vector>
#include <memory> #include <memory>
@@ -48,7 +48,6 @@ public:
NetworkMutex = 0x8016, NetworkMutex = 0x8016,
ClientId = 0x8017, ClientId = 0x8017,
AllMACAddresses = 0x8018, AllMACAddresses = 0x8018,
SPIPortKeyOperation = 0x8019,
}; };
Message(Type t) : type(t) {} Message(Type t) : type(t) {}
@@ -1,43 +0,0 @@
#ifndef __SPIPORTKEYMESSAGE_H_
#define __SPIPORTKEYMESSAGE_H_
#ifdef __cplusplus
#include "icsneo/communication/message/message.h"
#include <array>
#include <memory>
namespace icsneo {
class SPIPortKeyMessage : public Message {
public:
enum class Operation : uint8_t {
WriteKey = 0,
IsKeySet = 1,
ClearKey = 2
};
#pragma pack(push, 2)
struct SPIPortKeyPacket
{
Operation op;
uint8_t portIndex;
bool isKeyLoaded;
uint8_t rsvd;
uint8_t key[16];
};
#pragma pack(pop)
static std::shared_ptr<SPIPortKeyMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
SPIPortKeyMessage() : Message(Type::SPIPortKeyOperation) {}
bool isKeyLoaded;
};
} // namespace icsneo
#endif // __cplusplus
#endif // __SPIPORTKEYMESSAGE_H_
-1
View File
@@ -126,7 +126,6 @@ enum class ChipID : icsneoc2_chip_id_t {
RADA2B_REVB_ZCHIP = icsneoc2_chip_id_rada2b_revb_zchip, RADA2B_REVB_ZCHIP = icsneoc2_chip_id_rada2b_revb_zchip,
RADGigastar_FFG_ZYNQ = icsneoc2_chip_id_radgigastar_ffg_zynq, RADGigastar_FFG_ZYNQ = icsneoc2_chip_id_radgigastar_ffg_zynq,
VEM_02_FR_FCHIP = icsneoc2_chip_id_vem_02_fr_fchip, VEM_02_FR_FCHIP = icsneoc2_chip_id_vem_02_fr_fchip,
RADBMS_WIL = icsneoc2_chip_id_radbms_wil,
Connect_ZCHIP = icsneoc2_chip_id_connect_zchip, Connect_ZCHIP = icsneoc2_chip_id_connect_zchip,
SFPModule_88q2221_MCHIP = icsneoc2_chip_id_sfpmodule_88q2221_mchip, SFPModule_88q2221_MCHIP = icsneoc2_chip_id_sfpmodule_88q2221_mchip,
RADGALAXY2_SYSMON_CHIP = icsneoc2_chip_id_radgalaxy2_sysmon_chip, RADGALAXY2_SYSMON_CHIP = icsneoc2_chip_id_radgalaxy2_sysmon_chip,
+12 -13
View File
@@ -46,7 +46,6 @@
#include "icsneo/communication/message/extendeddatamessage.h" #include "icsneo/communication/message/extendeddatamessage.h"
#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/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"
@@ -134,7 +133,6 @@ public:
RADA2B = 40, RADA2B = 40,
SFPModule_88q2112 = 41, SFPModule_88q2112 = 41,
RADGalaxy2 = 47, RADGalaxy2 = 47,
RADwBMS = 48,
RADMoon3 = 49, RADMoon3 = 49,
RADComet2 = 50, RADComet2 = 50,
Connect = 51, Connect = 51,
@@ -727,8 +725,6 @@ public:
std::optional<EthPhyMessage> sendEthPhyMsg(const EthPhyMessage& message, std::chrono::milliseconds timeout = std::chrono::milliseconds(50)); std::optional<EthPhyMessage> sendEthPhyMsg(const EthPhyMessage& message, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
bool sendSPIPortKeyOperation(uint8_t portIndex, SPIPortKeyMessage::Operation op, std::array<uint8_t, 16> key = {});
/** /**
* Set the flags of the root directory entry specified at given address * Set the flags of the root directory entry specified at given address
@@ -743,7 +739,6 @@ public:
*/ */
std::optional<bool> SetRootDirectoryEntryFlags(uint8_t mask, uint8_t values, uint32_t collectionEntryByteAddress); std::optional<bool> SetRootDirectoryEntryFlags(uint8_t mask, uint8_t values, uint32_t collectionEntryByteAddress);
device_eventhandler_t report;
std::shared_ptr<Communication> com; std::shared_ptr<Communication> com;
std::shared_ptr<IDeviceSettings> settings; std::shared_ptr<IDeviceSettings> settings;
@@ -901,14 +896,11 @@ public:
bool unlockAllNetworks(); bool unlockAllNetworks();
std::shared_ptr<NetworkMutexMessage> getNetworkMutexStatus(Network::NetID network); std::shared_ptr<NetworkMutexMessage> getNetworkMutexStatus(Network::NetID network);
void startHeartbeat();
void stopHeartbeat();
void restartHeartbeat();
protected: protected:
bool online = false; bool online = false;
int messagePollingCallbackID = 0; int messagePollingCallbackID = 0;
int internalHandlerCallbackID = 0; int internalHandlerCallbackID = 0;
device_eventhandler_t report;
std::mutex ioMutex; std::mutex ioMutex;
std::optional<bool> ethActivationStatus; std::optional<bool> ethActivationStatus;
@@ -941,7 +933,7 @@ protected:
std::move(decoder) std::move(decoder)
); );
setupCommunication(*com); setupCommunication(*com);
settings = makeSettings<Settings>(this); settings = makeSettings<Settings>(com);
setupSettings(*settings); setupSettings(*settings);
diskReadDriver = std::unique_ptr<DiskRead>(new DiskRead()); diskReadDriver = std::unique_ptr<DiskRead>(new DiskRead());
diskWriteDriver = std::unique_ptr<DiskWrite>(new DiskWrite()); diskWriteDriver = std::unique_ptr<DiskWrite>(new DiskWrite());
@@ -977,8 +969,8 @@ protected:
} }
template<typename Settings> template<typename Settings>
std::shared_ptr<IDeviceSettings> makeSettings(Device* device) { std::shared_ptr<IDeviceSettings> makeSettings(std::shared_ptr<Communication> comm) {
return std::make_shared<Settings>(device); return std::make_shared<Settings>(comm);
} }
virtual void setupSettings(IDeviceSettings&) {} virtual void setupSettings(IDeviceSettings&) {}
@@ -1043,6 +1035,10 @@ private:
APIEvent::Type attemptToBeginCommunication(); APIEvent::Type attemptToBeginCommunication();
// Use heartbeatSuppressed instead when reading
std::atomic<int> heartbeatSuppressedByUser{0};
bool heartbeatSuppressed() const { return heartbeatSuppressedByUser > 0 || (settings && settings->applyingSettings); }
void handleNeoVIMessage(std::shared_ptr<CANMessage> message); void handleNeoVIMessage(std::shared_ptr<CANMessage> message);
bool firmwareUpdateSupported(); bool firmwareUpdateSupported();
@@ -1053,6 +1049,10 @@ private:
moodycamel::BlockingConcurrentQueue<std::shared_ptr<Message>> pollingContainer; moodycamel::BlockingConcurrentQueue<std::shared_ptr<Message>> pollingContainer;
void enforcePollingMessageLimit(); void enforcePollingMessageLimit();
std::atomic<bool> stopHeartbeatThread{false};
std::mutex heartbeatMutex;
std::thread heartbeatThread;
std::mutex diskMutex; std::mutex diskMutex;
// Wireless neoVI Stack // Wireless neoVI Stack
@@ -1175,7 +1175,6 @@ private:
// Keeponline (keepalive for online) // Keeponline (keepalive for online)
std::unique_ptr<Periodic> keeponline; std::unique_ptr<Periodic> keeponline;
std::unique_ptr<Heartbeat> heartbeat;
std::optional<uint32_t> assignedClientId; std::optional<uint32_t> assignedClientId;
std::unordered_set<icsneo::Network::NetID> lockedNetworks; std::unordered_set<icsneo::Network::NetID> lockedNetworks;
-4
View File
@@ -52,7 +52,6 @@ public:
RADEpsilon = icsneoc2_devicetype_rad_epsilon, RADEpsilon = icsneoc2_devicetype_rad_epsilon,
RADEpsilonXL = icsneoc2_devicetype_rad_epsilon_xl, RADEpsilonXL = icsneoc2_devicetype_rad_epsilon_xl,
RADGalaxy2 = icsneoc2_devicetype_rad_galaxy2, RADGalaxy2 = icsneoc2_devicetype_rad_galaxy2,
RADwBMS = icsneoc2_devicetype_rad_wbms,
RADMoon3 = icsneoc2_devicetype_rad_moon3, RADMoon3 = icsneoc2_devicetype_rad_moon3,
RADComet2 = icsneoc2_devicetype_rad_comet2, RADComet2 = icsneoc2_devicetype_rad_comet2,
FIRE3_FlexRay = icsneoc2_devicetype_fire3_flexray, FIRE3_FlexRay = icsneoc2_devicetype_fire3_flexray,
@@ -217,8 +216,6 @@ public:
return "neoVI Connect"; return "neoVI Connect";
case RADGigastar2: case RADGigastar2:
return "RAD-Gigastar 2"; return "RAD-Gigastar 2";
case RADwBMS:
return "RAD-wBMS";
case DONT_REUSE0: case DONT_REUSE0:
case DONT_REUSE1: case DONT_REUSE1:
case DONT_REUSE2: case DONT_REUSE2:
@@ -271,7 +268,6 @@ private:
#define ICSNEO_DEVICETYPE_RADEPSILON ((devicetype_t)icsneoc2_devicetype_rad_epsilon) #define ICSNEO_DEVICETYPE_RADEPSILON ((devicetype_t)icsneoc2_devicetype_rad_epsilon)
#define ICSNEO_DEVICETYPE_RADEPSILONXL ((devicetype_t)icsneoc2_devicetype_rad_epsilon_xl) #define ICSNEO_DEVICETYPE_RADEPSILONXL ((devicetype_t)icsneoc2_devicetype_rad_epsilon_xl)
#define ICSNEO_DEVICETYPE_RADGALAXY2 ((devicetype_t)icsneoc2_devicetype_rad_galaxy2) #define ICSNEO_DEVICETYPE_RADGALAXY2 ((devicetype_t)icsneoc2_devicetype_rad_galaxy2)
#define ICSNEO_DEVICETYPE_RADWBMS ((devicetype_t)icsneoc2_devicetype_rad_wbms)
#define ICSNEO_DEVICETYPE_RADMoon3 ((devicetype_t)icsneoc2_devicetype_rad_moon3) #define ICSNEO_DEVICETYPE_RADMoon3 ((devicetype_t)icsneoc2_devicetype_rad_moon3)
#define ICSNEO_DEVICETYPE_RADCOMET2 ((devicetype_t)icsneoc2_devicetype_rad_comet2) #define ICSNEO_DEVICETYPE_RADCOMET2 ((devicetype_t)icsneoc2_devicetype_rad_comet2)
#define ICSNEO_DEVICETYPE_FIRE3FLEXRAY ((devicetype_t)icsneoc2_devicetype_fire3_flexray) #define ICSNEO_DEVICETYPE_FIRE3FLEXRAY ((devicetype_t)icsneoc2_devicetype_fire3_flexray)
+7 -63
View File
@@ -753,75 +753,16 @@ typedef struct
uint16_t cmp_device_id; uint16_t cmp_device_id;
} CMP_GLOBAL_DATA; } CMP_GLOBAL_DATA;
/* wBMS Structs */
typedef union
{
uint8_t byte;
struct
{
uint8_t onboard_external : 1;
uint8_t type : 1;
uint8_t mode: 3;
uint8_t reserved : 3;
} config;
} sSPI_PORT_SETTING;
typedef struct
{
sSPI_PORT_SETTING port_a; //1
sSPI_PORT_SETTING port_b; //1
} sSPI_PORT_SETTINGS;
#define WBMS_GATEWAY_NETWORK_NONE (0)
#define WBMS_GATEWAY_NETWORK_DWCAN_01 (1)
#define WBMS_GATEWAY_NETWORK_DWCAN_02 (2)
#define WBMS_GATEWAY_NETWORK_UDP_MULTICAST (3)
typedef struct
{
uint8_t wbms1_network;
uint8_t wbms1_canfd_enable;
uint8_t wbms2_network;
uint8_t wbms2_canfd_enable;
uint16_t reserved[6];
} WBMSGatewaySettings;
typedef struct
{
uint8_t wBMSDeviceID;
uint8_t enabled;
} sWIL_FAULT_SERVICING_SETTINGS;
typedef struct
{
uint8_t enabled;
} sWIL_NETWORK_DATA_CAPTURE_SETTINGS;
typedef struct
{
uint8_t using_port_a;
uint8_t using_port_b;
uint8_t attemptConnect;
sWIL_FAULT_SERVICING_SETTINGS fault_servicing_config;
sWIL_NETWORK_DATA_CAPTURE_SETTINGS network_data_capture_config;
uint16_t sensor_buffer_size;
} sWIL_CONNECTION_SETTINGS;
#pragma pack(pop) #pragma pack(pop)
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/communication/network.h" #include "icsneo/communication/communication.h"
#include "icsneo/api/event.h"
#include "icsneo/api/eventmanager.h"
#include <optional> #include <optional>
#include <iostream> #include <iostream>
#include <atomic> #include <atomic>
namespace icsneo { namespace icsneo {
class Device;
enum class MiscIOAnalogVoltage : uint8_t enum class MiscIOAnalogVoltage : uint8_t
{ {
V0 = icsneoc2_misc_io_analog_voltage_v0, V0 = icsneoc2_misc_io_analog_voltage_v0,
@@ -849,7 +790,7 @@ public:
static int64_t GetBaudrateValueForEnum(CANBaudrate enumValue); static int64_t GetBaudrateValueForEnum(CANBaudrate enumValue);
static bool ValidateLINBaudrate(int64_t baudrate); static bool ValidateLINBaudrate(int64_t baudrate);
IDeviceSettings(Device* device, size_t size); IDeviceSettings(std::shared_ptr<Communication> com, size_t size) : com(com), report(com->report), structSize(size) {}
virtual ~IDeviceSettings() {} virtual ~IDeviceSettings() {}
bool ok() const { return !disabled && settingsLoaded; } bool ok() const { return !disabled && settingsLoaded; }
@@ -1396,8 +1337,10 @@ public:
bool disabled = false; bool disabled = false;
bool readonly = false; bool readonly = false;
std::atomic<bool> applyingSettings{false};
protected: protected:
Device* device; std::shared_ptr<Communication> com;
device_eventhandler_t report; device_eventhandler_t report;
size_t structSize; size_t structSize;
@@ -1409,7 +1352,8 @@ protected:
// Parameter createInoperableSettings exists because it is serving as a warning that you probably don't want to do this // Parameter createInoperableSettings exists because it is serving as a warning that you probably don't want to do this
typedef void* warn_t; typedef void* warn_t;
IDeviceSettings(warn_t createInoperableSettings, Device* device); IDeviceSettings(warn_t createInoperableSettings, std::shared_ptr<Communication> com)
: disabled(true), readonly(true), report(com->report), structSize(0) { (void)createInoperableSettings; }
// Devices that embed a Fire3LinuxSettings block in their settings structure override these to // Devices that embed a Fire3LinuxSettings block in their settings structure override these to
// expose it; all other devices report not-available (nullptr / nullopt) and the Linux accessors // expose it; all other devices report not-available (nullptr / nullopt) and the Linux accessors
+1 -1
View File
@@ -12,7 +12,7 @@ namespace icsneo {
class NullSettings : public IDeviceSettings { class NullSettings : public IDeviceSettings {
public: public:
// Calls the protected base constructor with "createInoperableSettings" // Calls the protected base constructor with "createInoperableSettings"
NullSettings(Device* device) : IDeviceSettings(nullptr, device) {} NullSettings(std::shared_ptr<Communication> com) : IDeviceSettings(nullptr, com) {}
}; };
} }
@@ -69,7 +69,7 @@ static_assert(sizeof(etherbadge_settings_t) == 316, "EtherBadge settings size mi
class EtherBADGESettings : public IDeviceSettings { class EtherBADGESettings : public IDeviceSettings {
public: public:
EtherBADGESettings(Device* device) : IDeviceSettings(device, sizeof(etherbadge_settings_t)) {} EtherBADGESettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(etherbadge_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<etherbadge_settings_t>(); auto cfg = getStructurePointer<etherbadge_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -88,7 +88,7 @@ static_assert(sizeof(neoviconnect_settings_t) == 628, "NeoVIConnect settings siz
class NeoVIConnectSettings : public IDeviceSettings { class NeoVIConnectSettings : public IDeviceSettings {
public: public:
NeoVIConnectSettings(Device* device) : IDeviceSettings(device, sizeof(neoviconnect_settings_t)) {} NeoVIConnectSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neoviconnect_settings_t)) {}
const Fire3LinuxSettings* getLinuxSettings() const override { const Fire3LinuxSettings* getLinuxSettings() const override {
auto cfg = getStructurePointer<neoviconnect_settings_t>(); auto cfg = getStructurePointer<neoviconnect_settings_t>();
return cfg ? &cfg->os_settings : nullptr; return cfg ? &cfg->os_settings : nullptr;
@@ -101,7 +101,7 @@ static_assert(sizeof(neovifire_settings_t) == 744, "NeoVIFire settings size mism
class NeoVIFIRESettings : public IDeviceSettings { class NeoVIFIRESettings : public IDeviceSettings {
public: public:
NeoVIFIRESettings(Device* device) : IDeviceSettings(device, sizeof(neovifire_settings_t)) {} NeoVIFIRESettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<neovifire_settings_t>(); auto cfg = getStructurePointer<neovifire_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -125,7 +125,7 @@ static_assert(sizeof(neovifire2_settings_t) == 936, "NeoVIFire2 settings size mi
class NeoVIFIRE2Settings : public IDeviceSettings { class NeoVIFIRE2Settings : public IDeviceSettings {
public: public:
NeoVIFIRE2Settings(Device* device) : IDeviceSettings(device, sizeof(neovifire2_settings_t)) {} NeoVIFIRE2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire2_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<neovifire2_settings_t>(); auto cfg = getStructurePointer<neovifire2_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -166,7 +166,7 @@ static_assert(sizeof(neovifire3_settings_t) == 1722, "NeoVIFire3 settings size m
class NeoVIFIRE3Settings : public IDeviceSettings { class NeoVIFIRE3Settings : public IDeviceSettings {
public: public:
NeoVIFIRE3Settings(Device* device) : IDeviceSettings(device, sizeof(neovifire3_settings_t)) {} NeoVIFIRE3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3_settings_t)) {}
const Fire3LinuxSettings* getLinuxSettings() const override { const Fire3LinuxSettings* getLinuxSettings() const override {
auto cfg = getStructurePointer<neovifire3_settings_t>(); auto cfg = getStructurePointer<neovifire3_settings_t>();
return cfg ? &cfg->os_settings : nullptr; return cfg ? &cfg->os_settings : nullptr;
@@ -149,7 +149,7 @@ static_assert(sizeof(neovifire3flexray_settings_t) == 1372, "NeoVIFire3Flexray s
class NeoVIFIRE3FlexRaySettings : public IDeviceSettings { class NeoVIFIRE3FlexRaySettings : public IDeviceSettings {
public: public:
NeoVIFIRE3FlexRaySettings(Device* device) : IDeviceSettings(device, sizeof(neovifire3flexray_settings_t)) {} NeoVIFIRE3FlexRaySettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3flexray_settings_t)) {}
const Fire3LinuxSettings* getLinuxSettings() const override { const Fire3LinuxSettings* getLinuxSettings() const override {
auto cfg = getStructurePointer<neovifire3flexray_settings_t>(); auto cfg = getStructurePointer<neovifire3flexray_settings_t>();
return cfg ? &cfg->os_settings : nullptr; return cfg ? &cfg->os_settings : nullptr;
@@ -158,7 +158,7 @@ static_assert(sizeof(neovifire3t1slin_settings_t) == 1594, "NeoVIFire3T1SLIN set
class NeoVIFIRE3T1SLINSettings : public IDeviceSettings { class NeoVIFIRE3T1SLINSettings : public IDeviceSettings {
public: public:
NeoVIFIRE3T1SLINSettings(Device* device) : IDeviceSettings(device, sizeof(neovifire3t1slin_settings_t)) {} NeoVIFIRE3T1SLINSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3t1slin_settings_t)) {}
const Fire3LinuxSettings* getLinuxSettings() const override { const Fire3LinuxSettings* getLinuxSettings() const override {
auto cfg = getStructurePointer<neovifire3t1slin_settings_t>(); auto cfg = getStructurePointer<neovifire3t1slin_settings_t>();
return cfg ? &cfg->os_settings : nullptr; return cfg ? &cfg->os_settings : nullptr;
@@ -111,7 +111,7 @@ static_assert(sizeof(neovired2_settings_t) == 918, "NeoVIRED2 settings size mism
class NeoVIRED2Settings : public IDeviceSettings { class NeoVIRED2Settings : public IDeviceSettings {
public: public:
NeoVIRED2Settings(Device* device) : IDeviceSettings(device, sizeof(neovired2_settings_t)) {} NeoVIRED2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovired2_settings_t)) {}
const Fire3LinuxSettings* getLinuxSettings() const override { const Fire3LinuxSettings* getLinuxSettings() const override {
auto cfg = getStructurePointer<neovired2_settings_t>(); auto cfg = getStructurePointer<neovired2_settings_t>();
return cfg ? &cfg->os_settings : nullptr; return cfg ? &cfg->os_settings : nullptr;
@@ -100,7 +100,7 @@ public:
Node Node
}; };
RADA2BSettings(Device* device) : IDeviceSettings(device, sizeof(rada2b_settings_t)) {} RADA2BSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(rada2b_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<rada2b_settings_t>(); auto cfg = getStructurePointer<rada2b_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -141,27 +141,27 @@ public:
} }
} }
TDMMode getTDMMode(RADA2BDevice a2bDevice) const { TDMMode getTDMMode(RADA2BDevice device) const {
auto cfg = getStructurePointer<rada2b_settings_t>(); auto cfg = getStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node; auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
return static_cast<TDMMode>(deviceSettings.tdmMode); return static_cast<TDMMode>(deviceSettings.tdmMode);
} }
uint8_t getNumChannels(RADA2BDevice a2bDevice) const { uint8_t getNumChannels(RADA2BDevice device) const {
return tdmModeToChannelNum(getTDMMode(a2bDevice)); return tdmModeToChannelNum(getTDMMode(device));
} }
ChannelSize getChannelSize(RADA2BDevice a2bDevice) const { ChannelSize getChannelSize(RADA2BDevice device) const {
auto cfg = getStructurePointer<rada2b_settings_t>(); auto cfg = getStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node; auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
return static_cast<ChannelSize>(deviceSettings.flags & a2bSettingsFlag16bit); return static_cast<ChannelSize>(deviceSettings.flags & a2bSettingsFlag16bit);
} }
uint8_t getChannelOffset(RADA2BDevice a2bDevice, A2BMessage::Direction dir) const { uint8_t getChannelOffset(RADA2BDevice device, A2BMessage::Direction dir) const {
auto cfg = getStructurePointer<rada2b_settings_t>(); auto cfg = getStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node; auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
if(dir == A2BMessage::Direction::Upstream) { if(dir == A2BMessage::Direction::Upstream) {
return deviceSettings.upstreamChannelOffset; return deviceSettings.upstreamChannelOffset;
@@ -170,30 +170,30 @@ public:
return deviceSettings.downstreamChannelOffset; return deviceSettings.downstreamChannelOffset;
} }
NodeType getNodeType(RADA2BDevice a2bDevice) const { NodeType getNodeType(RADA2BDevice device) const {
auto cfg = getStructurePointer<rada2b_settings_t>(); auto cfg = getStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node; auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
return static_cast<NodeType>(deviceSettings.nodeType); return static_cast<NodeType>(deviceSettings.nodeType);
} }
void setNodeType(RADA2BDevice a2bDevice, NodeType newType) { void setNodeType(RADA2BDevice device, NodeType newType) {
auto cfg = getMutableStructurePointer<rada2b_settings_t>(); auto cfg = getMutableStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node; auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
deviceSettings.nodeType = static_cast<uint8_t>(newType); deviceSettings.nodeType = static_cast<uint8_t>(newType);
} }
void setTDMMode(RADA2BDevice a2bDevice, TDMMode newMode) { void setTDMMode(RADA2BDevice device, TDMMode newMode) {
auto cfg = getMutableStructurePointer<rada2b_settings_t>(); auto cfg = getMutableStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node; auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
deviceSettings.tdmMode = static_cast<uint8_t>(newMode); deviceSettings.tdmMode = static_cast<uint8_t>(newMode);
} }
void setChannelOffset(RADA2BDevice a2bDevice, A2BMessage::Direction dir, uint8_t newOffset) { void setChannelOffset(RADA2BDevice device, A2BMessage::Direction dir, uint8_t newOffset) {
auto cfg = getMutableStructurePointer<rada2b_settings_t>(); auto cfg = getMutableStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node; auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
if(dir == A2BMessage::Direction::Upstream) { if(dir == A2BMessage::Direction::Upstream) {
deviceSettings.upstreamChannelOffset = newOffset; deviceSettings.upstreamChannelOffset = newOffset;
@@ -203,9 +203,9 @@ public:
} }
} }
void setChannelSize(RADA2BDevice a2bDevice, ChannelSize newChannelSize) { void setChannelSize(RADA2BDevice device, ChannelSize newChannelSize) {
auto cfg = getMutableStructurePointer<rada2b_settings_t>(); auto cfg = getMutableStructurePointer<rada2b_settings_t>();
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node; auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
if(newChannelSize == ChannelSize::chSize16) { if(newChannelSize == ChannelSize::chSize16) {
deviceSettings.flags |= a2bSettingsFlag16bit; deviceSettings.flags |= a2bSettingsFlag16bit;
@@ -89,7 +89,7 @@ static_assert(sizeof(radcomet2_settings_t) == 498, "RADComet2 settings size mism
class RADComet2Settings : public IDeviceSettings { class RADComet2Settings : public IDeviceSettings {
public: public:
RADComet2Settings(Device* device) : IDeviceSettings(device, sizeof(radcomet2_settings_t)) {} RADComet2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radcomet2_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radcomet2_settings_t>(); auto cfg = getStructurePointer<radcomet2_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -86,7 +86,7 @@ static_assert(sizeof(radcomet3_settings_t) == 674, "RADComet3 settings size mism
class RADComet3Settings : public IDeviceSettings { class RADComet3Settings : public IDeviceSettings {
public: public:
RADComet3Settings(Device* device) : IDeviceSettings(device, sizeof(radcomet3_settings_t)) {} RADComet3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radcomet3_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radcomet3_settings_t>(); auto cfg = getStructurePointer<radcomet3_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -86,7 +86,7 @@ static_assert(sizeof(radepsilon_settings_t) == 400, "RADEpsilon settings size mi
class RADEpsilonSettings : public IDeviceSettings { class RADEpsilonSettings : public IDeviceSettings {
public: public:
RADEpsilonSettings(Device* device) : IDeviceSettings(device, sizeof(radepsilon_settings_t)) {} RADEpsilonSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radepsilon_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radepsilon_settings_t>(); auto cfg = getStructurePointer<radepsilon_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -109,7 +109,7 @@ static_assert(sizeof(radgalaxy_settings_t) == 776, "RADGalaxy settings size mism
class RADGalaxySettings : public IDeviceSettings { class RADGalaxySettings : public IDeviceSettings {
public: public:
RADGalaxySettings(Device* device) : IDeviceSettings(device, sizeof(radgalaxy_settings_t)) {} RADGalaxySettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgalaxy_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radgalaxy_settings_t>(); auto cfg = getStructurePointer<radgalaxy_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -125,7 +125,7 @@ static_assert(sizeof(radgalaxy2_settings_t) == 960, "RADGalaxy2 settings size mi
class RADGalaxy2Settings : public IDeviceSettings { class RADGalaxy2Settings : public IDeviceSettings {
public: public:
RADGalaxy2Settings(Device* device) : IDeviceSettings(device, sizeof(radgalaxy2_settings_t)) {} RADGalaxy2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgalaxy2_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radgalaxy2_settings_t>(); auto cfg = getStructurePointer<radgalaxy2_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -42,7 +42,7 @@ static_assert(sizeof(radgemini_settings_t) == 86, "RADGemini settings size misma
class RADGeminiSettings : public IDeviceSettings { class RADGeminiSettings : public IDeviceSettings {
public: public:
RADGeminiSettings(Device* device) : IDeviceSettings(device, sizeof(radgemini_settings_t)) {} RADGeminiSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgemini_settings_t)) {}
}; };
} }
@@ -107,7 +107,7 @@ static_assert(sizeof(radgigastar_settings_t) == 1026, "RADGigastar settings size
class RADGigastarSettings : public IDeviceSettings { class RADGigastarSettings : public IDeviceSettings {
public: public:
RADGigastarSettings(Device* device) : IDeviceSettings(device, sizeof(radgigastar_settings_t)) {} RADGigastarSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgigastar_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radgigastar_settings_t>(); auto cfg = getStructurePointer<radgigastar_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -156,7 +156,7 @@ namespace icsneo
class RADGigastar2Settings : public IDeviceSettings class RADGigastar2Settings : public IDeviceSettings
{ {
public: public:
RADGigastar2Settings(Device* device) : IDeviceSettings(device, sizeof(radgigastar2_settings_t)) {} RADGigastar2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgigastar2_settings_t)) {}
const CAN_SETTINGS *getCANSettingsFor(Network net) const override const CAN_SETTINGS *getCANSettingsFor(Network net) const override
{ {
auto cfg = getStructurePointer<radgigastar2_settings_t>(); auto cfg = getStructurePointer<radgigastar2_settings_t>();
@@ -90,7 +90,7 @@ static_assert(sizeof(radjupiter_settings_t) == 348, "RAD-Jupiter Settings are no
class RADJupiterSettings : public IDeviceSettings { class RADJupiterSettings : public IDeviceSettings {
public: public:
RADJupiterSettings(Device* device) : IDeviceSettings(device, sizeof(radjupiter_settings_t)) {} RADJupiterSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radjupiter_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radjupiter_settings_t>(); auto cfg = getStructurePointer<radjupiter_settings_t>();
@@ -101,7 +101,7 @@ static_assert(sizeof(radmars_settings_t) == 666, "RAD-Mars settings size mismatc
class RADMarsSettings : public IDeviceSettings { class RADMarsSettings : public IDeviceSettings {
public: public:
RADMarsSettings(Device* device) : IDeviceSettings(device, sizeof(radmars_settings_t)) {} RADMarsSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmars_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<radmars_settings_t>(); auto cfg = getStructurePointer<radmars_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -42,7 +42,7 @@ static_assert(sizeof(radmoon2_settings_t) == 170, "RADMoon2 settings size mismat
class RADMoon2Settings : public IDeviceSettings { class RADMoon2Settings : public IDeviceSettings {
public: public:
RADMoon2Settings(Device* device) : IDeviceSettings(device, sizeof(radmoon2_settings_t)) {} RADMoon2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoon2_settings_t)) {}
const RAD_GPTP_SETTINGS* getGPTPSettings() const override { const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
auto cfg = getStructurePointer<radmoon2_settings_t>(); auto cfg = getStructurePointer<radmoon2_settings_t>();
@@ -39,7 +39,7 @@ static_assert(sizeof(radmoon3_settings_t) == 68, "RADMoon3 settings size mismatc
class RADMoon3Settings : public IDeviceSettings { class RADMoon3Settings : public IDeviceSettings {
public: public:
RADMoon3Settings(Device* device) : IDeviceSettings(device, sizeof(radmoon3_settings_t)) {} RADMoon3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoon3_settings_t)) {}
}; };
} }
@@ -55,7 +55,7 @@ static_assert(sizeof(radmoonduo_settings_t) == 38, "RAD-Moon Duo settings size e
class RADMoonDuoSettings : public IDeviceSettings { class RADMoonDuoSettings : public IDeviceSettings {
public: public:
RADMoonDuoSettings(Device* device) : IDeviceSettings(device, sizeof(radmoonduo_settings_t)) {} RADMoonDuoSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoonduo_settings_t)) {}
}; };
} }
@@ -46,7 +46,7 @@ static_assert(sizeof(radmoont1s_settings_t) == 160, "RADMoonT1S settings size mi
class RADMoonT1SSettings : public IDeviceSettings { class RADMoonT1SSettings : public IDeviceSettings {
public: public:
RADMoonT1SSettings(Device* device) : IDeviceSettings(device, sizeof(radmoont1s_settings_t)) {} RADMoonT1SSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoont1s_settings_t)) {}
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override { std::optional<bool> isT1SPLCAEnabledFor(Network net) const override {
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net); const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
@@ -74,7 +74,7 @@ static_assert(sizeof(radpluto_settings_t) == 322, "RAD-Pluto Settings are not pa
class RADPlutoSettings : public IDeviceSettings { class RADPlutoSettings : public IDeviceSettings {
public: public:
RADPlutoSettings(Device* device) : IDeviceSettings(device, sizeof(radpluto_settings_t)) { RADPlutoSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radpluto_settings_t)) {
} }
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
@@ -75,7 +75,7 @@ static_assert(sizeof(radstar2_settings_t) == 422, "RADStar2 settings size mismat
class RADStar2Settings : public IDeviceSettings { class RADStar2Settings : public IDeviceSettings {
public: public:
RADStar2Settings(Device* device) : IDeviceSettings(device, sizeof(radstar2_settings_t)) { RADStar2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radstar2_settings_t)) {
} }
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
@@ -38,7 +38,7 @@ typedef struct {
class RADSupermoonSettings : public IDeviceSettings { class RADSupermoonSettings : public IDeviceSettings {
public: public:
RADSupermoonSettings(Device* device) : IDeviceSettings(device, sizeof(radsupermoon_settings_t)) {} RADSupermoonSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radsupermoon_settings_t)) {}
}; };
} }
@@ -1,182 +0,0 @@
#ifndef __RADWBMS_H_
#define __RADWBMS_H_
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/radwbms/radwbmssettings.h"
#include "icsneo/disk/neomemorydiskdriver.h"
namespace icsneo {
class RADwBMS : public Device {
public:
enum class FirmwareVariant {
Invalid = 0,
WIL_1_1 = 0x0101000C,
WIL_2_0 = 0x02000058,
WIL_2_0_9_26 = 0x0200091A,
WIL_2_1 = 0x02010047,
WIL_2_2 = 0x0202000F,
WIL_2_3 = 0x0203020B,
WIL_3_1_0_9 = 0x03010009,
WIL_3_2_0 = 0x03020000,
WIL_3_3_0_27 = 0x0303001B,
};
// Serial numbers start with BS
// USB PID is 0x110B, standard driver is CDACM
// Ethernet MAC allocation is 0x1B, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADwBMS, DeviceType::RADwBMS, "BS");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::DWCAN_01,
Network::NetID::DWCAN_02,
Network::NetID::ETHERNET_01,
};
return supportedNetworks;
}
size_t getEthernetActivationLineCount() const override { return 1; }
bool supportsReboot() const override { return true; }
ProductID getProductID() const override {
return ProductID::RADwBMS;
}
FirmwareVariant variantToFlash = FirmwareVariant::Invalid;
void setVariantToFlash(FirmwareVariant variant) {
variantToFlash = variant;
}
FirmwareVariant getCurrentVariant() {
if(supportsComponentVersions()) {
refreshComponentVersions();
const auto& components = getComponentVersions();
for(const auto& component : components) {
if(!component.valid) {
continue;
}
if(component.identifier == static_cast<uint32_t>(ChipID::RADBMS_WIL)) {
FirmwareVariant res = FirmwareVariant::Invalid;
switch(static_cast<FirmwareVariant>(component.dotVersion)) {
case FirmwareVariant::WIL_1_1:
case FirmwareVariant::WIL_2_0:
case FirmwareVariant::WIL_2_0_9_26:
case FirmwareVariant::WIL_2_1:
case FirmwareVariant::WIL_2_2:
case FirmwareVariant::WIL_2_3:
case FirmwareVariant::WIL_3_1_0_9:
case FirmwareVariant::WIL_3_2_0:
case FirmwareVariant::WIL_3_3_0_27:
res = static_cast<FirmwareVariant>(component.dotVersion);
break;
default:
res = FirmwareVariant::Invalid;
break;
}
if(variantToFlash == FirmwareVariant::Invalid) {
// Set the variantToFlash if it hasn't been set yet, we always flash the same firmware variant as the current if it is unspecified
variantToFlash = res;
}
return res;
}
}
}
return FirmwareVariant::Invalid;
}
const std::vector<ChipInfo>& getChipInfo() const override {
switch (variantToFlash) {
case FirmwareVariant::WIL_1_1: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_1_1_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_2_0: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_2_0_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_2_0_9_26: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_2_0_9_26_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_2_1: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_2_1_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_2_2: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_2_2_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_2_3: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_2_3_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_3_1_0_9: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_3_1_0_9_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_3_2_0: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_3_2_0_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::WIL_3_3_0_27: {
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_3_3_0_27_ief", 0, FirmwareType::IEF}};
return chips;
}
case FirmwareVariant::Invalid:
break; // invalid will be handled below
}
// Return empty chip information if the WIL version is not set
static std::vector<ChipInfo> chips = {};
return chips;
}
BootloaderPipeline getBootloader() override {
return BootloaderPipeline()
.add<EnterBootloaderPhase>()
.add<FlashPhase>(ChipID::RADBMS_MCHIP, BootloaderCommunication::RED)
.add<EnterApplicationPhase>(ChipID::RADBMS_MCHIP)
.add<WaitPhase>(std::chrono::milliseconds(3000))
.add<ReconnectPhase>();
}
std::vector<VersionReport> getChipVersions(bool refreshComponents = true) override {
if(variantToFlash == FirmwareVariant::Invalid) {
getCurrentVariant();
}
return Device::getChipVersions(refreshComponents);
}
protected:
RADwBMS(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADwBMSSettings, Disk::NeoMemoryDiskDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
}
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
std::optional<MemoryAddress> getCoreminiStartAddressFlash() const override {
return 2048 * 512;
}
std::optional<MemoryAddress> getCoreminiStartAddressSD() const override {
return 0;
}
bool supportsEraseMemory() const override {
return true;
}
};
}; // namespace icsneo
#endif // __RADWBMS_H_
@@ -1,80 +0,0 @@
#ifndef __RADWBMSSETTINGS_H_
#define __RADWBMSSETTINGS_H_
#include <stdint.h>
#include "icsneo/device/idevicesettings.h"
#ifdef __cplusplus
namespace icsneo {
#endif // __cplusplus
#pragma pack(push, 2)
typedef struct
{
uint16_t perf_en;
uint64_t termination_enables;
CAN_SETTINGS can1;
CANFD_SETTINGS canfd1;
CAN_SETTINGS can2;
CANFD_SETTINGS canfd2;
uint16_t network_enables;
uint16_t network_enables_2;
uint16_t network_enables_3;
int16_t iso15765_separation_time_offset;
struct
{
uint32_t disableUsbCheckOnBoot : 1;
uint32_t enableLatencyTest : 1;
uint32_t enablePcEthernetComm : 1;
uint32_t reserved : 29;
} flags;
ETHERNET_SETTINGS ethernet;
ETHERNET_SETTINGS2 ethernet2;
uint32_t pwr_man_timeout;
uint16_t pwr_man_enable;
uint16_t network_enabled_on_boot;
uint8_t rsvd[10]; //Was sWILBridgeConfig
sSPI_PORT_SETTINGS spi_config;
sWIL_CONNECTION_SETTINGS wbms_wil_1;
sWIL_CONNECTION_SETTINGS wbms_wil_2;
uint16_t wil1_nwk_metadata_buff_count;
uint16_t wil2_nwk_metadata_buff_count;
WBMSGatewaySettings gateway;
uint16_t network_enables_4;
uint64_t network_enables_5;
} radwbms_settings_t;
#pragma pack(pop)
#ifdef __cplusplus
static_assert(sizeof(radwbms_settings_t) == 156, "RAD-wBMS settings size mismatch");
#include <iostream>
class RADwBMSSettings : public IDeviceSettings {
public:
RADwBMSSettings(Device* device) : IDeviceSettings(device, sizeof(radwbms_settings_t)) {}
};
}
#endif // __cplusplus
#endif // __RADWBMSSETTINGS_H_
@@ -37,7 +37,7 @@ static_assert(sizeof(valuecan3_settings_t) == 40, "ValueCAN3 settings size misma
class ValueCAN3Settings : public IDeviceSettings { class ValueCAN3Settings : public IDeviceSettings {
public: public:
ValueCAN3Settings(Device* device) : IDeviceSettings(device, sizeof(valuecan3_settings_t)) {} ValueCAN3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan3_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan3_settings_t>(); auto cfg = getStructurePointer<valuecan3_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -10,7 +10,7 @@ namespace icsneo {
class ValueCAN4_1_2Settings : public IDeviceSettings { class ValueCAN4_1_2Settings : public IDeviceSettings {
public: public:
ValueCAN4_1_2Settings(Device* device) : IDeviceSettings(device, sizeof(valuecan4_1_2_settings_t)) {} ValueCAN4_1_2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_1_2_settings_t)) {}
// We do not override getCANSettingsFor or getCANFDSettingsFor here because they will be device specific // We do not override getCANSettingsFor or getCANFDSettingsFor here because they will be device specific
}; };
@@ -9,7 +9,7 @@ namespace icsneo {
class ValueCAN4_1Settings : public ValueCAN4_1_2Settings { class ValueCAN4_1Settings : public ValueCAN4_1_2Settings {
public: public:
ValueCAN4_1Settings(Device* device) : ValueCAN4_1_2Settings(device) {} ValueCAN4_1Settings(std::shared_ptr<Communication> com) : ValueCAN4_1_2Settings(com) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_1_2_settings_t>(); auto cfg = getStructurePointer<valuecan4_1_2_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -10,7 +10,7 @@ namespace icsneo {
class ValueCAN4_2ELSettings : public ValueCAN4_4_2ELSettings { class ValueCAN4_2ELSettings : public ValueCAN4_4_2ELSettings {
public: public:
ValueCAN4_2ELSettings(Device* device) : ValueCAN4_4_2ELSettings(device) {} ValueCAN4_2ELSettings(std::shared_ptr<Communication> com) : ValueCAN4_4_2ELSettings(com) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>(); auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -9,7 +9,7 @@ namespace icsneo {
class ValueCAN4_2Settings : public ValueCAN4_1_2Settings { class ValueCAN4_2Settings : public ValueCAN4_1_2Settings {
public: public:
ValueCAN4_2Settings(Device* device) : ValueCAN4_1_2Settings(device) {} ValueCAN4_2Settings(std::shared_ptr<Communication> com) : ValueCAN4_1_2Settings(com) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_1_2_settings_t>(); auto cfg = getStructurePointer<valuecan4_1_2_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -10,7 +10,7 @@ namespace icsneo {
class ValueCAN4_4_2ELSettings : public IDeviceSettings { class ValueCAN4_4_2ELSettings : public IDeviceSettings {
public: public:
ValueCAN4_4_2ELSettings(Device* device) : IDeviceSettings(device, sizeof(valuecan4_4_2el_settings_t)) {} ValueCAN4_4_2ELSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_4_2el_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>(); auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -10,7 +10,7 @@ namespace icsneo {
class ValueCAN4_4Settings : public ValueCAN4_4_2ELSettings { class ValueCAN4_4Settings : public ValueCAN4_4_2ELSettings {
public: public:
ValueCAN4_4Settings(Device* device) : ValueCAN4_4_2ELSettings(device) {} ValueCAN4_4Settings(std::shared_ptr<Communication> com) : ValueCAN4_4_2ELSettings(com) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>(); auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -10,7 +10,7 @@ namespace icsneo {
class ValueCAN4IndustrialSettings : public IDeviceSettings { class ValueCAN4IndustrialSettings : public IDeviceSettings {
public: public:
ValueCAN4IndustrialSettings(Device* device) : IDeviceSettings(device, sizeof(valuecan4_industrial_settings_t)) {} ValueCAN4IndustrialSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_industrial_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<valuecan4_industrial_settings_t>(); auto cfg = getStructurePointer<valuecan4_industrial_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
@@ -48,7 +48,7 @@ static_assert(sizeof(vividcan_settings_t) == 64, "VividCAN settings size mismatc
class VividCANSettings : public IDeviceSettings { class VividCANSettings : public IDeviceSettings {
public: public:
VividCANSettings(Device* device) : IDeviceSettings(device, sizeof(vividcan_settings_t)) {} VividCANSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(vividcan_settings_t)) {}
const CAN_SETTINGS* getCANSettingsFor(Network net) const override { const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
auto cfg = getStructurePointer<vividcan_settings_t>(); auto cfg = getStructurePointer<vividcan_settings_t>();
if(cfg == nullptr) if(cfg == nullptr)
+1 -8
View File
@@ -44,10 +44,7 @@ typedef unsigned __int64 uint64_t;
#include "cicsSpyStatusBits.h" #include "cicsSpyStatusBits.h"
#if defined(_MSC_VER) #if defined(_MSC_VER)
#pragma warning(push) #pragma warning(disable : 4200)
#pragma warning(disable : 4200) // zero-sized array in struct/union
#pragma warning(disable : 4201) // nameless struct/union
#pragma warning(disable : 4121) // member alignment sensitive to packing
#endif #endif
// MSVC++ 10.0 _MSC_VER == 1600 64-bit version doesn't allow multi-line #if directives... // MSVC++ 10.0 _MSC_VER == 1600 64-bit version doesn't allow multi-line #if directives...
@@ -5443,8 +5440,4 @@ CHECK_STRUCT_SIZE(FlashAccessoryFirmwareParams);
#undef CHECK_STRUCT_SIZE #undef CHECK_STRUCT_SIZE
#endif /* INTREPID_NO_CHECK_STRUCT_SIZE */ #endif /* INTREPID_NO_CHECK_STRUCT_SIZE */
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#endif /* _ICSNVC40_H */ #endif /* _ICSNVC40_H */
+1 -2
View File
@@ -372,11 +372,10 @@ icsneoc2_error_t icsneoc2_device_mac_addresses_enumerate(const icsneoc2_device_t
* *
* @param[in] mac_address The MAC address object to get the network ID of. * @param[in] mac_address The MAC address object to get the network ID of.
* @param[out] network_id Pointer to an icsneoc2_netid_t to copy the network ID into. * @param[out] network_id Pointer to an icsneoc2_netid_t to copy the network ID into.
* Unrecognized values are normalized to icsneoc2_netid_invalid.
* *
* @return icsneoc2_error_t icsneoc2_error success if successful, icsneoc2_error_invalid_parameters on failure. * @return icsneoc2_error_t icsneoc2_error success if successful, icsneoc2_error_invalid_parameters on failure.
*/ */
icsneoc2_error_t icsneoc2_mac_network_id_get(const icsneoc2_mac_addr_entry_t* mac_address, icsneoc2_netid_t* network_id); icsneoc2_error_t icsneoc2_mac_network_id_get(const icsneoc2_mac_addr_entry_t* mac_address, _icsneoc2_netid_t* network_id);
/** /**
* Get the MAC Address bytes of a MAC address. * Get the MAC Address bytes of a MAC address.
-2
View File
@@ -42,7 +42,6 @@ typedef enum _icsneoc2_devicetype_t {
icsneoc2_devicetype_rad_epsilon = 0x00000018, icsneoc2_devicetype_rad_epsilon = 0x00000018,
icsneoc2_devicetype_rad_epsilon_xl = 0x0000001e, icsneoc2_devicetype_rad_epsilon_xl = 0x0000001e,
icsneoc2_devicetype_rad_galaxy2 = 0x00000021, icsneoc2_devicetype_rad_galaxy2 = 0x00000021,
icsneoc2_devicetype_rad_wbms = 0x00000022,
icsneoc2_devicetype_rad_moon3 = 0x00000023, icsneoc2_devicetype_rad_moon3 = 0x00000023,
icsneoc2_devicetype_rad_comet2 = 0x00000024, icsneoc2_devicetype_rad_comet2 = 0x00000024,
icsneoc2_devicetype_fire3_flexray = 0x00000025, icsneoc2_devicetype_fire3_flexray = 0x00000025,
@@ -666,7 +665,6 @@ typedef enum _icsneoc2_chip_id_t {
icsneoc2_chip_id_rada2b_revb_zchip = 116, icsneoc2_chip_id_rada2b_revb_zchip = 116,
icsneoc2_chip_id_radgigastar_ffg_zynq = 117, icsneoc2_chip_id_radgigastar_ffg_zynq = 117,
icsneoc2_chip_id_vem_02_fr_fchip = 118, icsneoc2_chip_id_vem_02_fr_fchip = 118,
icsneoc2_chip_id_radbms_wil = 119,
icsneoc2_chip_id_connect_zchip = 121, icsneoc2_chip_id_connect_zchip = 121,
icsneoc2_chip_id_sfpmodule_88q2221_mchip = 122, icsneoc2_chip_id_sfpmodule_88q2221_mchip = 122,
icsneoc2_chip_id_radgalaxy2_sysmon_chip = 123, icsneoc2_chip_id_radgalaxy2_sysmon_chip = 123,
-1
View File
@@ -33,7 +33,6 @@
#include "icsneo/device/tree/radpluto/radpluto.h" #include "icsneo/device/tree/radpluto/radpluto.h"
#include "icsneo/device/tree/radstar2/radstar2.h" #include "icsneo/device/tree/radstar2/radstar2.h"
#include "icsneo/device/tree/radsupermoon/radsupermoon.h" #include "icsneo/device/tree/radsupermoon/radsupermoon.h"
#include "icsneo/device/tree/radwbms/radwbms.h"
#include "icsneo/device/tree/valuecan3/valuecan3.h" #include "icsneo/device/tree/valuecan3/valuecan3.h"
#include "icsneo/device/tree/valuecan4/valuecan4-1.h" #include "icsneo/device/tree/valuecan4/valuecan4-1.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2.h" #include "icsneo/device/tree/valuecan4/valuecan4-2.h"
@@ -33,7 +33,6 @@
#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"
#include "icsneo/device/tree/radsupermoon/radsupermoon.h" #include "icsneo/device/tree/radsupermoon/radsupermoon.h"
#include "icsneo/device/tree/radwbms/radwbms.h"
#include "icsneo/device/tree/valuecan3/valuecan3.h" #include "icsneo/device/tree/valuecan3/valuecan3.h"
#include "icsneo/device/tree/valuecan4/valuecan4-1.h" #include "icsneo/device/tree/valuecan4/valuecan4-1.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2.h" #include "icsneo/device/tree/valuecan4/valuecan4-2.h"
+3 -2
View File
@@ -108,8 +108,9 @@ void CDCACM::Find(std::vector<FoundDevice>& found) {
releasers.emplace_back(parent); releasers.emplace_back(parent);
current = parent; current = parent;
// On old macOSes, IOUSBDevice is the type of the class we want // On old macOSes, IOUSBDevice is the type of the class we want
// On newer macOSes, IOUSBDevice may further be subclassed as IOUSBHostDevice // On macOS 12+, IOUSBHostDevice is the main USB device class (separate hierarchy from IOUSBDevice)
if(IOObjectConformsTo(parent, kIOUSBDeviceClassName)) { if(IOObjectConformsTo(parent, kIOUSBDeviceClassName) ||
IOObjectConformsTo(parent, "IOUSBHostDevice")) {
usb = parent; usb = parent;
break; break;
} }
+1 -5
View File
@@ -243,7 +243,6 @@ bool Servd::enableCommunication(bool enable, bool& sendMsg) {
} }
void Servd::read() { void Servd::read() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
std::vector<uint8_t> buf(2 * 1024 * 1024); std::vector<uint8_t> buf(2 * 1024 * 1024);
while(!isDisconnected() && !isClosing()) { while(!isDisconnected() && !isClosing()) {
bool hasData; bool hasData;
@@ -261,14 +260,11 @@ void Servd::read() {
setIsDisconnected(true); setIsDisconnected(true);
return; return;
} }
if(!pushRx(buf.data(), bufSize)) { pushRx(buf.data(), bufSize);
EventManager::GetInstance().add(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
}
} }
} }
void Servd::write() { void Servd::write() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
WriteOperation writeOp; WriteOperation writeOp;
while(!isDisconnected() && !isClosing()) { while(!isDisconnected() && !isClosing()) {
if(!writeQueue.wait_dequeue_timed(writeOp, std::chrono::milliseconds(100))) { if(!writeQueue.wait_dequeue_timed(writeOp, std::chrono::milliseconds(100))) {
-47
View File
@@ -127,28 +127,6 @@ TEST(icsneoc2, test_icsneoc2_device_is_valid)
ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_is_valid(NULL)); ASSERT_EQ(icsneoc2_error_invalid_parameters, icsneoc2_device_is_valid(NULL));
} }
TEST(icsneoc2, test_icsneoc2_mac_address_get_query_length)
{
icsneoc2_mac_addr_entry_t mac_address = {};
size_t value_length = 0;
ASSERT_EQ(icsneoc2_error_success, icsneoc2_mac_address_get(&mac_address, NULL, &value_length));
ASSERT_EQ(ICSNEO_MAC_ADDRESS_LEN, value_length);
}
TEST(icsneoc2, test_icsneoc2_mac_address_get_truncated_length)
{
icsneoc2_mac_addr_entry_t mac_address = {};
const uint8_t expected[ICSNEO_MAC_ADDRESS_LEN] = {0x00, 0xFC, 0x70, 0x1E, 0x18, 0x70};
std::copy(std::begin(expected), std::end(expected), mac_address.address);
uint8_t value[3] = {};
size_t value_length = sizeof(value);
ASSERT_EQ(icsneoc2_error_success, icsneoc2_mac_address_get(&mac_address, value, &value_length));
ASSERT_EQ(sizeof(value), value_length);
ASSERT_EQ(0, memcmp(expected, value, sizeof(value)));
}
TEST(icsneoc2, test_icsneoc2_error_invalid_parameters_and_invalid_device) TEST(icsneoc2, test_icsneoc2_error_invalid_parameters_and_invalid_device)
{ {
bool placeholderBool = false; bool placeholderBool = false;
@@ -2153,28 +2131,3 @@ TEST(icsneoc2, test_gptp_enum_alignment)
ASSERT_EQ(sizeof(RADGPTPRole), sizeof(icsneoc2_gptp_role_t)); ASSERT_EQ(sizeof(RADGPTPRole), sizeof(icsneoc2_gptp_role_t));
} }
TEST(icsneoc2, test_mac_network_id_get)
{
icsneoc2_mac_addr_entry_t entry {};
icsneoc2_netid_t network_id = 0;
entry.network_id = icsneoc2_netid_ethernet_01;
ASSERT_EQ(icsneoc2_error_success, icsneoc2_mac_network_id_get(&entry, &network_id));
ASSERT_EQ(icsneoc2_netid_ethernet_01, network_id);
entry.network_id = 43;
network_id = 0;
ASSERT_EQ(icsneoc2_error_success, icsneoc2_mac_network_id_get(&entry, &network_id));
ASSERT_EQ(icsneoc2_netid_invalid, network_id);
entry.network_id = icsneoc2_netid_invalid;
network_id = 0;
ASSERT_EQ(icsneoc2_error_success, icsneoc2_mac_network_id_get(&entry, &network_id));
ASSERT_EQ(icsneoc2_netid_invalid, network_id);
ASSERT_EQ(icsneoc2_error_invalid_parameters,
icsneoc2_mac_network_id_get(nullptr, &network_id));
ASSERT_EQ(icsneoc2_error_invalid_parameters,
icsneoc2_mac_network_id_get(&entry, nullptr));
}