mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-09-20 16:08:37 +02:00
Compare commits
7
Commits
77a886bbe0
..
1.4.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
07e4eca14a | ||
|
|
936566170f | ||
|
|
3aaacb6cc8 | ||
|
|
1dda9f5412 | ||
|
|
78c2e3ff89 | ||
|
|
afedd4bb1f | ||
|
|
9b01e488da |
@@ -35,30 +35,6 @@ unit_test windows/x64:
|
||||
- libicsneo-win-x64
|
||||
timeout: 5m
|
||||
|
||||
build windows/x86:
|
||||
stage: build
|
||||
script:
|
||||
- cmd /C ci\build-windows32.bat
|
||||
artifacts:
|
||||
when: always
|
||||
paths:
|
||||
- build
|
||||
expire_in: 3 days
|
||||
tags:
|
||||
- libicsneo-win-x64
|
||||
|
||||
unit_test windows/x86:
|
||||
stage: unit_test
|
||||
script:
|
||||
- build\libicsneo-unit-tests.exe
|
||||
dependencies:
|
||||
- build windows/x86
|
||||
needs:
|
||||
- build windows/x86
|
||||
tags:
|
||||
- libicsneo-win-x64
|
||||
timeout: 5m
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Ubuntu
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
+5
-1
@@ -82,7 +82,7 @@ if(MSVC)
|
||||
add_definitions(-D_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING)
|
||||
add_definitions(-D_ITERATOR_DEBUG_LEVEL=0)
|
||||
else() #if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(LIBICSNEO_COMPILER_WARNINGS -Wall -Wno-switch -Wno-unknown-pragmas)
|
||||
set(LIBICSNEO_COMPILER_WARNINGS -Wall -Wno-unknown-pragmas)
|
||||
endif()
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
@@ -235,6 +235,9 @@ set(SRC_FILES
|
||||
communication/message/networkmutexmessage.cpp
|
||||
communication/message/clientidmessage.cpp
|
||||
communication/message/transmitmessage.cpp
|
||||
communication/message/spiportkeymessage.cpp
|
||||
communication/message/genericapidatamessage.cpp
|
||||
communication/message/genericapistatusmessage.cpp
|
||||
communication/packet/flexraypacket.cpp
|
||||
communication/packet/canpacket.cpp
|
||||
communication/packet/a2bpacket.cpp
|
||||
@@ -345,6 +348,7 @@ add_library(icsneocpp
|
||||
api/icsneocpp/icsneocpp.cpp
|
||||
api/icsneocpp/event.cpp
|
||||
api/icsneocpp/eventmanager.cpp
|
||||
api/icsneocpp/heartbeat.cpp
|
||||
api/icsneocpp/version.cpp
|
||||
${SRC_FILES}
|
||||
)
|
||||
|
||||
@@ -462,6 +462,8 @@ const char* APIEvent::DescriptionForType(Type type) {
|
||||
return TOO_MANY_EVENTS;
|
||||
case Type::Unknown:
|
||||
return UNKNOWN;
|
||||
case Type::Any:
|
||||
break;
|
||||
}
|
||||
return INVALID;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
#include "icsneo/api/heartbeat.h"
|
||||
#include "icsneo/api/lifetime.h"
|
||||
#include "icsneo/device/device.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
Heartbeat::Heartbeat(Device& device) :
|
||||
device(device), mode(device.isOnline() ? Mode::Passive : Mode::Active), thread(&Heartbeat::run, this) {
|
||||
}
|
||||
|
||||
Heartbeat::~Heartbeat() {
|
||||
{
|
||||
std::lock_guard lk(mutex);
|
||||
stop = true;
|
||||
}
|
||||
cv.notify_one();
|
||||
thread.join();
|
||||
}
|
||||
|
||||
void Heartbeat::run() {
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
|
||||
auto filter = std::make_shared<MessageFilter>();
|
||||
filter->includeInternalInAny = true;
|
||||
bool status = false;
|
||||
auto cbHandle = device.com->addMessageCallback(std::make_shared<MessageCallback>(filter, [&](std::shared_ptr<Message> msg) {
|
||||
// TODO: remove DeviceStatus after 2027-08-17, as ResetStatus should be widely supported
|
||||
const bool isHeartbeat =
|
||||
(msg->type == Message::Type::ResetStatus) ||
|
||||
(msg->type == Message::Type::RawMessage && std::static_pointer_cast<RawMessage>(msg)->network == Network::NetID::DeviceStatus);
|
||||
if(!isHeartbeat)
|
||||
return;
|
||||
{
|
||||
std::lock_guard lk(mutex);
|
||||
status = true;
|
||||
}
|
||||
cv.notify_one();
|
||||
}));
|
||||
Lifetime cbLifetime([&] {
|
||||
device.com->removeMessageCallback(cbHandle);
|
||||
});
|
||||
while(true) {
|
||||
std::unique_lock lk(mutex);
|
||||
if(mode == Mode::Active) {
|
||||
if(cv.wait_for(lk, std::chrono::milliseconds(100), [&] { return stop; })) {
|
||||
break;
|
||||
}
|
||||
device.com->sendCommand(Command::RequestStatusUpdate);
|
||||
}
|
||||
if(!cv.wait_for(lk, std::chrono::seconds(2), [&] { return status || stop; })) {
|
||||
// we disconnect instead of close because it indicates to the user that a cleanup is still required (our thread join)
|
||||
device.report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
|
||||
device.com->driver->setIsDisconnected(true);
|
||||
break;
|
||||
}
|
||||
if(stop)
|
||||
break;
|
||||
status = false;
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -1,7 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_EXAMPLES=ON \
|
||||
-DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_ENABLE_TCP=OFF || exit 1
|
||||
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_EXAMPLES=ON -DLIBICSNEO_BUILD_UNIT_TESTS=ON -DLIBICSNEO_ENABLE_TCP=OFF || exit 1
|
||||
|
||||
cmake --build build || exit 1
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
|
||||
mkdir build >nul 2>&1
|
||||
|
||||
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DLIBICSNEO_BUILD_UNIT_TESTS=ON ^
|
||||
-DLIBICSNEO_ENABLE_TCP=ON || exit /b 1
|
||||
cmake -GNinja -Bbuild -DCMAKE_BUILD_TYPE=Release -DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DLIBICSNEO_BUILD_UNIT_TESTS=ON-DLIBICSNEO_ENABLE_TCP=ON || exit /b 1
|
||||
|
||||
cmake --build build || exit /b 1
|
||||
|
||||
@@ -26,6 +26,9 @@
|
||||
#include "icsneo/communication/message/ethernetstatusmessage.h"
|
||||
#include "icsneo/communication/message/networkmutexmessage.h"
|
||||
#include "icsneo/communication/message/clientidmessage.h"
|
||||
#include "icsneo/communication/message/spiportkeymessage.h"
|
||||
#include "icsneo/communication/message/genericapidatamessage.h"
|
||||
#include "icsneo/communication/message/genericapistatusmessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/communication/packet/canpacket.h"
|
||||
@@ -341,6 +344,15 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
case ExtendedCommand::LiveData:
|
||||
result = HardwareLiveDataPacket::DecodeToMessage(packet->data, report);
|
||||
return true;
|
||||
case ExtendedCommand::ExecuteSPIPortKeyOperation:
|
||||
result = SPIPortKeyMessage::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::ReadGenericAPIData:
|
||||
result = GenericAPIDataMessage::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::ReadGenericAPIStatus:
|
||||
result = GenericAPIStatusMessage::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
case ExtendedCommand::GetTC10Status:
|
||||
result = TC10StatusMessage::DecodeToMessage(packet->data);
|
||||
return true;
|
||||
@@ -563,6 +575,9 @@ bool Decoder::decode(std::shared_ptr<Message>& result, const std::shared_ptr<Pac
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
report(APIEvent::Type::UnexpectedNetworkType, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
// For the moment other types of messages will automatically be decoded as raw messages
|
||||
|
||||
@@ -234,7 +234,9 @@ bool Encoder::encode(const Packetizer& packetizer, std::vector<uint8_t>& result,
|
||||
result = packetizer.packetWrap(result, false);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
report(APIEvent::Type::MessageFormattingError, APIEvent::Severity::Error);
|
||||
return false; // The message was not a properly formed Message
|
||||
}
|
||||
|
||||
// Early returns may mean we don't reach this far, check the type you're concerned with
|
||||
|
||||
@@ -163,6 +163,8 @@ void A2BMessage::setChannelSample(Direction dir, uint8_t channel, size_t frame,
|
||||
case PCMType::L24:
|
||||
sampleToSet = sampleToSet << 8;
|
||||
break;
|
||||
case PCMType::L32:
|
||||
break;
|
||||
}
|
||||
|
||||
if(channelSize16) {
|
||||
|
||||
@@ -35,7 +35,7 @@ bool EthPhyMessage::appendPhyMessage(bool writeEnable, bool clause45, uint8_t ph
|
||||
|
||||
bool EthPhyMessage::appendPhyMessage(std::shared_ptr<PhyMessage> message)
|
||||
{
|
||||
if(message != nullptr)
|
||||
if(message)
|
||||
{
|
||||
messages.push_back(message);
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "icsneo/communication/message/genericapidatamessage.h"
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<GenericAPIDataMessage> GenericAPIDataMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
if(bytestream.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
|
||||
return nullptr;
|
||||
|
||||
const auto* hdr = reinterpret_cast<const ExtendedResponseMessage::ResponseHeader*>(bytestream.data());
|
||||
|
||||
if(hdr->command != ExtendedCommand::ReadGenericAPIData)
|
||||
return nullptr;
|
||||
|
||||
const size_t required = sizeof(ExtendedResponseMessage::ResponseHeader) + sizeof(GenericAPIDataHeader);
|
||||
if(bytestream.size() < required)
|
||||
return nullptr;
|
||||
|
||||
auto msg = std::make_shared<GenericAPIDataMessage>();
|
||||
|
||||
const auto* packet = reinterpret_cast<const GenericAPIDataPacket*>(bytestream.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
|
||||
|
||||
msg->functionId = packet->header.functionId;
|
||||
msg->buffer.resize(packet->header.bufferLength);
|
||||
std::copy(packet->buffer, packet->buffer + packet->header.bufferLength, msg->buffer.data());
|
||||
return msg;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#include "icsneo/communication/message/genericapistatusmessage.h"
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<GenericAPIStatusMessage> GenericAPIStatusMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
if(bytestream.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
|
||||
return nullptr;
|
||||
|
||||
const auto* hdr = reinterpret_cast<const ExtendedResponseMessage::ResponseHeader*>(bytestream.data());
|
||||
|
||||
if(hdr->command != ExtendedCommand::ReadGenericAPIStatus)
|
||||
return nullptr;
|
||||
|
||||
const size_t required = sizeof(ExtendedResponseMessage::ResponseHeader) + sizeof(GenericAPIStatusResponsePacket);
|
||||
if(bytestream.size() < required)
|
||||
return nullptr;
|
||||
|
||||
auto msg = std::make_shared<GenericAPIStatusMessage>();
|
||||
|
||||
const auto* packet = reinterpret_cast<const GenericAPIStatusResponsePacket*>(bytestream.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
|
||||
|
||||
msg->functionId = packet->functionId;
|
||||
msg->finishedProcessing = static_cast<bool>(packet->finishedProcessing);
|
||||
msg->functionError = packet->functionError;
|
||||
msg->callbackError = packet->callbackError;
|
||||
return msg;
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "icsneo/communication/message/spiportkeymessage.h"
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
#include "icsneo/communication/command.h"
|
||||
#include "icsneo/communication/network.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
std::shared_ptr<SPIPortKeyMessage> SPIPortKeyMessage::DecodeToMessage(const std::vector<uint8_t>& bytestream) {
|
||||
if(bytestream.size() < sizeof(ExtendedResponseMessage::ResponseHeader))
|
||||
return nullptr;
|
||||
|
||||
const auto* hdr = reinterpret_cast<const ExtendedResponseMessage::ResponseHeader*>(bytestream.data());
|
||||
|
||||
if(hdr->command != ExtendedCommand::ExecuteSPIPortKeyOperation)
|
||||
return nullptr;
|
||||
|
||||
const size_t required = sizeof(ExtendedResponseMessage::ResponseHeader) + sizeof(SPIPortKeyPacket);
|
||||
if(bytestream.size() < required)
|
||||
return nullptr;
|
||||
|
||||
auto msg = std::make_shared<SPIPortKeyMessage>();
|
||||
|
||||
const auto* packet = reinterpret_cast<const SPIPortKeyPacket*>(bytestream.data() + sizeof(ExtendedResponseMessage::ResponseHeader));
|
||||
msg->isKeyLoaded = packet->isKeyLoaded;
|
||||
|
||||
return msg;
|
||||
}
|
||||
@@ -142,6 +142,8 @@ void MultiChannelCommunication::hidReadTask() {
|
||||
dispatchMessage(msg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if(currentQueue == nullptr) {
|
||||
|
||||
+54
-114
@@ -92,10 +92,6 @@ Device::~Device() {
|
||||
disableMessagePolling();
|
||||
if(isOpen())
|
||||
close();
|
||||
if(heartbeatThread.joinable()) {
|
||||
stopHeartbeatThread = true;
|
||||
heartbeatThread.join();
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t Device::getTimestampResolution() const {
|
||||
@@ -288,6 +284,8 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
startHeartbeat();
|
||||
|
||||
APIEvent::Type attemptErr = attemptToBeginCommunication();
|
||||
if(attemptErr != APIEvent::Type::NoErrorFound) {
|
||||
// We could not communicate with the device, let's see if an extension can
|
||||
@@ -334,79 +332,6 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
|
||||
EventManager::GetInstance().cancelErrorDowngradingOnCurrentThread();
|
||||
}
|
||||
|
||||
MessageFilter filter;
|
||||
filter.includeInternalInAny = true;
|
||||
internalHandlerCallbackID = com->addMessageCallback(std::make_shared<MessageCallback>(filter, [this](std::shared_ptr<Message> message) {
|
||||
handleInternalMessage(message);
|
||||
}));
|
||||
|
||||
// Clear the previous heartbeat thread, in case open() was called on this instance more than once
|
||||
if(heartbeatThread.joinable())
|
||||
heartbeatThread.join();
|
||||
|
||||
stopHeartbeatThread = false;
|
||||
|
||||
heartbeatThread = std::thread([this]() {
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
|
||||
MessageFilter filter;
|
||||
filter.includeInternalInAny = true;
|
||||
|
||||
std::condition_variable heartbeatCV;
|
||||
std::mutex receivedMessageMutex;
|
||||
bool receivedMessage = false;
|
||||
auto messageReceivedCallbackID = com->addMessageCallback(std::make_shared<MessageCallback>(filter, [&](std::shared_ptr<Message>) {
|
||||
{
|
||||
std::scoped_lock<std::mutex> lk(receivedMessageMutex);
|
||||
receivedMessage = true;
|
||||
}
|
||||
heartbeatCV.notify_all();
|
||||
}));
|
||||
|
||||
// Give the device time to get situated
|
||||
auto i = 150;
|
||||
while(!stopHeartbeatThread && i != 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
i--;
|
||||
}
|
||||
|
||||
while(!stopHeartbeatThread) {
|
||||
std::unique_lock<std::mutex> recvLk(receivedMessageMutex);
|
||||
// Wait for 110ms for a possible heartbeat
|
||||
if(heartbeatCV.wait_for(recvLk, std::chrono::milliseconds(110), [&]() { return receivedMessage; })) {
|
||||
receivedMessage = false;
|
||||
} else if(!stopHeartbeatThread) { // Add this condition here in case the thread was stopped while waiting for the last message
|
||||
|
||||
// Some communication, such as the bootloader and extractor interfaces, must
|
||||
// redirect the input stream from the device as it will no longer be in the
|
||||
// packet format we expect here. As a result, status updates will not reach
|
||||
// us here and suppressDisconnects() must be used. We don't want to request
|
||||
// a status and then redirect the stream, as we'll then be polluting an
|
||||
// otherwise quiet stream. This lock makes sure suppressDisconnects() will
|
||||
// block until we've either gotten our status update or disconnected from
|
||||
// the device.
|
||||
std::unique_lock<std::mutex> lk(heartbeatMutex);
|
||||
if(heartbeatSuppressed()) continue;
|
||||
|
||||
// No heartbeat received, request a status
|
||||
com->sendCommand(Command::RequestStatusUpdate);
|
||||
|
||||
// Check if we got a message, and if not, if settings are being applied
|
||||
if(heartbeatCV.wait_for(recvLk, std::chrono::milliseconds(3500), [&](){ return receivedMessage; })) {
|
||||
receivedMessage = false;
|
||||
} else {
|
||||
if(!stopHeartbeatThread) {
|
||||
close();
|
||||
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
com->removeMessageCallback(messageReceivedCallbackID);
|
||||
});
|
||||
|
||||
if(supportsLiveData())
|
||||
clearAllLiveData();
|
||||
|
||||
@@ -503,7 +428,7 @@ bool Device::close() {
|
||||
return false;
|
||||
}
|
||||
|
||||
stopHeartbeatThread = true;
|
||||
stopHeartbeat();
|
||||
|
||||
if (isMessagePollingEnabled()) {
|
||||
disableMessagePolling();
|
||||
@@ -534,31 +459,15 @@ bool Device::goOnline() {
|
||||
if(!enableNetworkCommunication(true, onlineTimeoutMs))
|
||||
return false;
|
||||
|
||||
auto startTime = std::chrono::system_clock::now();
|
||||
|
||||
ledState = LEDState::Online;
|
||||
|
||||
updateLEDState();
|
||||
|
||||
std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(Network::NetID::Reset_Status);
|
||||
filter->includeInternalInAny = true;
|
||||
|
||||
// Wait until communication is enabled or 5 seconds, whichever comes first
|
||||
while((std::chrono::system_clock::now() - startTime) < std::chrono::seconds(5)) {
|
||||
if(latestResetStatus && latestResetStatus->comEnabled)
|
||||
break;
|
||||
|
||||
bool failOut = false;
|
||||
com->waitForMessageSync([this, &failOut]() {
|
||||
if(!com->sendCommand(Command::RequestStatusUpdate)) {
|
||||
failOut = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}, filter, std::chrono::milliseconds(100));
|
||||
if(failOut)
|
||||
return false;
|
||||
}
|
||||
// (re)start the keeponline
|
||||
keeponline = std::make_unique<Periodic>([this] {
|
||||
static std::vector<uint8_t> timeoutBytes = std::vector<uint8_t>((uint8_t*)&onlineTimeoutMs, (uint8_t*)&onlineTimeoutMs + sizeof(onlineTimeoutMs));
|
||||
return com->sendCommand(Command::KeepAlive, timeoutBytes);
|
||||
}, std::chrono::milliseconds(onlineTimeoutMs / 4));
|
||||
|
||||
if(supportsNetworkMutex) {
|
||||
assignedClientId = com->getClientIDSync();
|
||||
@@ -575,41 +484,46 @@ bool Device::goOnline() {
|
||||
case NetworkMutexEvent::Acquired:
|
||||
lockedNetworks.emplace(*netMutexMsg->networks.begin());
|
||||
break;
|
||||
case NetworkMutexEvent::Expired:
|
||||
case NetworkMutexEvent::Preempted:
|
||||
case NetworkMutexEvent::Released: {
|
||||
auto it = lockedNetworks.find(*netMutexMsg->networks.begin());
|
||||
if (it != lockedNetworks.end())
|
||||
lockedNetworks.erase(it);
|
||||
break;
|
||||
}
|
||||
case NetworkMutexEvent::Queued:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// (re)start the keeponline
|
||||
keeponline = std::make_unique<Periodic>([this] {
|
||||
static std::vector<uint8_t> timeoutBytes = std::vector<uint8_t>((uint8_t*)&onlineTimeoutMs, (uint8_t*)&onlineTimeoutMs + sizeof(onlineTimeoutMs));
|
||||
return com->sendCommand(Command::KeepAlive, timeoutBytes);
|
||||
}, std::chrono::milliseconds(onlineTimeoutMs / 4));
|
||||
|
||||
online = true;
|
||||
|
||||
// restart the heartbeat in online mode
|
||||
restartHeartbeat();
|
||||
|
||||
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOnline(); return true; });
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Device::goOffline() {
|
||||
online = false;
|
||||
|
||||
keeponline.reset();
|
||||
|
||||
// restart the heartbeat in offline mode
|
||||
restartHeartbeat();
|
||||
|
||||
if(networkMutexCallbackHandle)
|
||||
removeMessageCallback(*networkMutexCallbackHandle);
|
||||
|
||||
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOffline(); return true; });
|
||||
|
||||
if(isDisconnected()) {
|
||||
online = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -625,8 +539,6 @@ bool Device::goOffline() {
|
||||
|
||||
updateLEDState();
|
||||
|
||||
online = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1988,11 +1900,9 @@ void Device::stopScriptStatusThreadIfNecessary(std::unique_lock<std::mutex> lk)
|
||||
}
|
||||
|
||||
Lifetime Device::suppressDisconnects() {
|
||||
std::lock_guard<std::mutex> lk(heartbeatMutex);
|
||||
heartbeatSuppressedByUser++;
|
||||
stopHeartbeat();
|
||||
return Lifetime([this] {
|
||||
std::lock_guard<std::mutex> lk2(heartbeatMutex);
|
||||
heartbeatSuppressedByUser--;
|
||||
startHeartbeat();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2128,6 +2038,18 @@ std::optional<EthPhyMessage> Device::sendEthPhyMsg(const EthPhyMessage& message,
|
||||
return std::make_optional<EthPhyMessage>(*retMsg);
|
||||
}
|
||||
|
||||
bool Device::sendSPIPortKeyOperation(uint8_t portIndex, SPIPortKeyMessage::Operation op, std::array<uint8_t, 16> key) {
|
||||
std::vector<uint8_t> args(sizeof(SPIPortKeyMessage::SPIPortKeyPacket));
|
||||
auto& params = *reinterpret_cast<SPIPortKeyMessage::SPIPortKeyPacket*>(args.data());
|
||||
params.op = op;
|
||||
params.portIndex = portIndex;
|
||||
std::copy(key.begin(), key.end(), params.key);
|
||||
if(!com->sendCommand(ExtendedCommand::ExecuteSPIPortKeyOperation, args)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::optional<bool> Device::SetRootDirectoryEntryFlags(uint8_t mask, uint8_t values, uint32_t collectionEntryByteAddress)
|
||||
{
|
||||
if(!supportsWiVI())
|
||||
@@ -3297,11 +3219,12 @@ bool Device::findVSAOffsetFromTimepoint(ICSClock::time_point point, uint64_t& vs
|
||||
std::shared_ptr<VSA> midRecord;
|
||||
auto midRecordStatus = parser.getRecordFromBytes(buffer.data(), Disk::SectorSize, midRecord);
|
||||
switch(midRecordStatus) {
|
||||
case VSAParser::RecordParseStatus::NotARecordStart:
|
||||
case VSAParser::RecordParseStatus::NotARecordStart: {
|
||||
// This part of the buffer does not contain records
|
||||
rightIndex = midIndex - 1;
|
||||
continue;
|
||||
case VSAParser::RecordParseStatus::ConsecutiveExtended:
|
||||
}
|
||||
case VSAParser::RecordParseStatus::ConsecutiveExtended: {
|
||||
// We dropped in the middle of an extended message record
|
||||
auto extendedRecord = std::dynamic_pointer_cast<VSAExtendedMessage>(midRecord);
|
||||
uint64_t pos = readPos;
|
||||
@@ -3317,6 +3240,9 @@ bool Device::findVSAOffsetFromTimepoint(ICSClock::time_point point, uint64_t& vs
|
||||
midRecord = extendedRecord;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if(midIndex <= leftIndex) {
|
||||
// Extended records cause problems with binary search
|
||||
// Just move on to linear search
|
||||
@@ -4156,3 +4082,17 @@ bool Device::unlockAllNetworks()
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Device::startHeartbeat() {
|
||||
if(!heartbeat)
|
||||
heartbeat = std::make_unique<Heartbeat>(*this);
|
||||
}
|
||||
|
||||
void Device::stopHeartbeat() {
|
||||
heartbeat.reset();
|
||||
}
|
||||
|
||||
void Device::restartHeartbeat() {
|
||||
stopHeartbeat();
|
||||
startHeartbeat();
|
||||
}
|
||||
|
||||
+24
-17
@@ -1,9 +1,16 @@
|
||||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/device/idevicesettings.h"
|
||||
#include "icsneo/communication/message/filter/main51messagefilter.h"
|
||||
#include <cstring>
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
IDeviceSettings::IDeviceSettings(Device* device, size_t size)
|
||||
: device(device), report(device->report), structSize(size) {}
|
||||
|
||||
IDeviceSettings::IDeviceSettings(warn_t createInoperableSettings, Device* device)
|
||||
: disabled(true), readonly(true), report(device->report), structSize(0) { (void)createInoperableSettings; }
|
||||
|
||||
std::optional<uint16_t> IDeviceSettings::CalculateGSChecksum(const std::vector<uint8_t>& settings) {
|
||||
const uint16_t* p = reinterpret_cast<const uint16_t*>(settings.data());
|
||||
size_t words = settings.size();
|
||||
@@ -166,7 +173,7 @@ bool IDeviceSettings::refresh() {
|
||||
}
|
||||
|
||||
std::vector<uint8_t> rxSettings;
|
||||
bool ret = com->getSettingsSync(rxSettings);
|
||||
bool ret = device->com->getSettingsSync(rxSettings);
|
||||
if(!ret) {
|
||||
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
|
||||
return false;
|
||||
@@ -231,10 +238,10 @@ bool IDeviceSettings::apply(bool temporary) {
|
||||
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
|
||||
|
||||
// Pause I/O with the device while the settings are applied
|
||||
applyingSettings = true;
|
||||
device->stopHeartbeat();
|
||||
|
||||
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
|
||||
return com->sendCommand(Command::SetSettings, bytestream);
|
||||
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() {
|
||||
return device->com->sendCommand(Command::SetSettings, bytestream);
|
||||
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000)));
|
||||
|
||||
if(!msg || msg->data[0] != 1) { // We did not receive a response
|
||||
@@ -259,8 +266,8 @@ bool IDeviceSettings::apply(bool temporary) {
|
||||
bytestream[6] = (uint8_t)(*gsChecksum >> 8);
|
||||
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
|
||||
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
|
||||
return com->sendCommand(Command::SetSettings, bytestream);
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() {
|
||||
return device->com->sendCommand(Command::SetSettings, bytestream);
|
||||
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000)));
|
||||
if(!msg || msg->data[0] != 1) {
|
||||
// Attempt to get the settings from the device so we're up to date if possible
|
||||
@@ -272,12 +279,12 @@ bool IDeviceSettings::apply(bool temporary) {
|
||||
}
|
||||
|
||||
if(!temporary) {
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
|
||||
return com->sendCommand(Command::SaveSettings);
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() {
|
||||
return device->com->sendCommand(Command::SaveSettings);
|
||||
}, std::make_shared<Main51MessageFilter>(Command::SaveSettings), std::chrono::milliseconds(5000)));
|
||||
}
|
||||
|
||||
applyingSettings = false;
|
||||
device->startHeartbeat();
|
||||
|
||||
refresh(); // Refresh our buffer with what the device has, whether we were successful or not
|
||||
|
||||
@@ -299,10 +306,10 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
|
||||
return false;
|
||||
}
|
||||
|
||||
applyingSettings = true;
|
||||
device->stopHeartbeat();
|
||||
|
||||
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
|
||||
return com->sendCommand(Command::SetDefaultSettings);
|
||||
std::shared_ptr<Main51Message> msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() {
|
||||
return device->com->sendCommand(Command::SetDefaultSettings);
|
||||
}, std::make_shared<Main51MessageFilter>(Command::SetDefaultSettings), std::chrono::milliseconds(5000)));
|
||||
if(!msg || msg->data[0] != 1) {
|
||||
// Attempt to get the settings from the device so we're up to date if possible
|
||||
@@ -336,8 +343,8 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
|
||||
bytestream[6] = (uint8_t)(*gsChecksum >> 8);
|
||||
memcpy(bytestream.data() + 7, getMutableRawStructurePointer(), settings.size());
|
||||
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this, &bytestream]() {
|
||||
return com->sendCommand(Command::SetSettings, bytestream);
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this, &bytestream]() {
|
||||
return device->com->sendCommand(Command::SetSettings, bytestream);
|
||||
}, std::make_shared<Main51MessageFilter>(Command::SetSettings), std::chrono::milliseconds(5000)));
|
||||
if(!msg || msg->data[0] != 1) {
|
||||
// Attempt to get the settings from the device so we're up to date if possible
|
||||
@@ -349,12 +356,12 @@ bool IDeviceSettings::applyDefaults(bool temporary) {
|
||||
}
|
||||
|
||||
if(!temporary) {
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(com->waitForMessageSync([this]() {
|
||||
return com->sendCommand(Command::SaveSettings);
|
||||
msg = std::dynamic_pointer_cast<Main51Message>(device->com->waitForMessageSync([this]() {
|
||||
return device->com->sendCommand(Command::SaveSettings);
|
||||
}, std::make_shared<Main51MessageFilter>(Command::SaveSettings), std::chrono::milliseconds(5000)));
|
||||
}
|
||||
|
||||
applyingSettings = false;
|
||||
device->startHeartbeat();
|
||||
|
||||
refresh(); // Refresh our buffer with what the device has, whether we were successful or not
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef __HEARTBEAT_H__
|
||||
#define __HEARTBEAT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include <thread>
|
||||
#include <condition_variable>
|
||||
#include <mutex>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class Device;
|
||||
|
||||
class Heartbeat {
|
||||
public:
|
||||
Heartbeat(Device& device);
|
||||
~Heartbeat();
|
||||
|
||||
private:
|
||||
enum class Mode {
|
||||
Passive, // ResetStatus messages arrive without requesting
|
||||
Active, // RequestStatusUpdate needs to be sent
|
||||
};
|
||||
Device& device;
|
||||
const Mode mode;
|
||||
bool stop = false;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cv;
|
||||
std::thread thread;
|
||||
|
||||
void run();
|
||||
};
|
||||
|
||||
} // icsneo
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __HEARTBEAT_H__
|
||||
@@ -73,10 +73,14 @@ enum class ExtendedCommand : uint16_t {
|
||||
GetComponentVersions = 0x001A,
|
||||
SoftwareUpdate = 0x001B,
|
||||
Reboot = 0x001C,
|
||||
ReadGenericAPIStatus = 0x001D,
|
||||
SetRootFSEntryFlags = 0x0027,
|
||||
TransmitCoreminiMessage = 0x0028,
|
||||
ReadGenericAPIData = 0x002E,
|
||||
WriteGenericAPICommand = 0x002F,
|
||||
GenericBinaryInfo = 0x0030,
|
||||
LiveData = 0x0035,
|
||||
ExecuteSPIPortKeyOperation = 0x003C,
|
||||
RequestTC10Wake = 0x003D,
|
||||
RequestTC10Sleep = 0x003E,
|
||||
GetTC10Status = 0x003F,
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "icsneo/communication/message/extendedresponsemessage.h"
|
||||
#include "icsneo/device/deviceversion.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include "icsneo/api/heartbeat.h"
|
||||
#include "icsneo/communication/packetizer.h"
|
||||
#include "icsneo/communication/encoder.h"
|
||||
#include "icsneo/communication/decoder.h"
|
||||
|
||||
@@ -31,6 +31,7 @@ public:
|
||||
virtual driver_finder_t getFinder() = 0;
|
||||
|
||||
inline bool isDisconnected() const { return disconnected; };
|
||||
inline void setIsDisconnected(bool isDisconnected) { disconnected = isDisconnected; }
|
||||
inline bool isClosing() const { return closing; }
|
||||
|
||||
bool waitForRx(size_t limit, std::chrono::milliseconds timeout);
|
||||
@@ -62,7 +63,6 @@ protected:
|
||||
};
|
||||
|
||||
inline void setIsClosing(bool isClosing) { closing = isClosing; }
|
||||
inline void setIsDisconnected(bool isDisconnected) { disconnected = isDisconnected; }
|
||||
|
||||
// Overridable in case the driver doesn't want to use writeTask and writeQueue
|
||||
virtual bool writeQueueFull() { return writeQueue.size_approx() > writeQueueSize; }
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#include "icsneo/communication/packet/ethphyregpacket.h"
|
||||
#include "icsneo/communication/message/message.h"
|
||||
#include "icsneo/communication/packet.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
#ifndef __GENERICAPIDATAMESSAGE_H_
|
||||
#define __GENERICAPIDATAMESSAGE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "icsneo/communication/message/message.h"
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class GenericAPIDataMessage : public Message {
|
||||
public:
|
||||
static constexpr size_t GENERIC_API_BUFFER_SIZE = 513;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct GenericAPIDataHeader {
|
||||
uint16_t bufferLength;
|
||||
uint8_t apiIndex;
|
||||
uint8_t instance;
|
||||
uint8_t functionId;
|
||||
};
|
||||
|
||||
struct GenericAPIDataPacket
|
||||
{
|
||||
GenericAPIDataHeader header;
|
||||
uint8_t buffer[GENERIC_API_BUFFER_SIZE];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static std::shared_ptr<GenericAPIDataMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||
|
||||
GenericAPIDataMessage() : Message(Type::GenericAPIData) {}
|
||||
|
||||
uint8_t functionId;
|
||||
std::vector<uint8_t> buffer;
|
||||
};
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __GENERICAPIDATAMESSAGE_H_
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef __GENERICAPISTATUSMESSAGE_H_
|
||||
#define __GENERICAPISTATUSMESSAGE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "icsneo/communication/message/message.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class GenericAPIStatusMessage : public Message {
|
||||
public:
|
||||
#pragma pack(push, 2)
|
||||
struct GenericAPIStatusResponsePacket
|
||||
{
|
||||
uint8_t apiIndex;
|
||||
uint8_t instance;
|
||||
uint8_t functionId;
|
||||
uint8_t functionError;
|
||||
uint8_t callbackError;
|
||||
uint8_t finishedProcessing;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static std::shared_ptr<GenericAPIStatusMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||
|
||||
GenericAPIStatusMessage() : Message(Type::GenericAPIStatus) {}
|
||||
|
||||
uint8_t functionId;
|
||||
bool finishedProcessing;
|
||||
uint8_t functionError;
|
||||
uint8_t callbackError;
|
||||
};
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __GENERICAPISTATUSMESSAGE_H_
|
||||
@@ -48,6 +48,9 @@ public:
|
||||
NetworkMutex = 0x8016,
|
||||
ClientId = 0x8017,
|
||||
AllMACAddresses = 0x8018,
|
||||
SPIPortKeyOperation = 0x8019,
|
||||
GenericAPIData = 0x8020,
|
||||
GenericAPIStatus = 0x8021,
|
||||
};
|
||||
|
||||
Message(Type t) : type(t) {}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#ifndef __SPIPORTKEYMESSAGE_H_
|
||||
#define __SPIPORTKEYMESSAGE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
#include "icsneo/communication/message/message.h"
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class SPIPortKeyMessage : public Message {
|
||||
public:
|
||||
enum class Operation : uint8_t {
|
||||
WriteKey = 0,
|
||||
IsKeySet = 1,
|
||||
ClearKey = 2
|
||||
};
|
||||
|
||||
#pragma pack(push, 2)
|
||||
struct SPIPortKeyPacket
|
||||
{
|
||||
Operation op;
|
||||
uint8_t portIndex;
|
||||
bool isKeyLoaded;
|
||||
uint8_t rsvd;
|
||||
uint8_t key[16];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
static std::shared_ptr<SPIPortKeyMessage> DecodeToMessage(const std::vector<uint8_t>& bytestream);
|
||||
|
||||
SPIPortKeyMessage() : Message(Type::SPIPortKeyOperation) {}
|
||||
|
||||
bool isKeyLoaded;
|
||||
};
|
||||
|
||||
} // namespace icsneo
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __SPIPORTKEYMESSAGE_H_
|
||||
@@ -46,6 +46,9 @@
|
||||
#include "icsneo/communication/message/extendeddatamessage.h"
|
||||
#include "icsneo/communication/message/livedatamessage.h"
|
||||
#include "icsneo/communication/message/tc10statusmessage.h"
|
||||
#include "icsneo/communication/message/spiportkeymessage.h"
|
||||
#include "icsneo/communication/message/genericapidatamessage.h"
|
||||
#include "icsneo/communication/message/genericapistatusmessage.h"
|
||||
#include "icsneo/core/macseccfg.h"
|
||||
#include "icsneo/communication/packet/genericbinarystatuspacket.h"
|
||||
#include "icsneo/communication/packet/livedatapacket.h"
|
||||
@@ -727,6 +730,8 @@ public:
|
||||
std::optional<EthPhyMessage> sendEthPhyMsg(const EthPhyMessage& message, std::chrono::milliseconds timeout = std::chrono::milliseconds(50));
|
||||
|
||||
|
||||
bool sendSPIPortKeyOperation(uint8_t portIndex, SPIPortKeyMessage::Operation op, std::array<uint8_t, 16> key = {});
|
||||
|
||||
/**
|
||||
* Set the flags of the root directory entry specified at given address
|
||||
*
|
||||
@@ -740,6 +745,7 @@ public:
|
||||
*/
|
||||
std::optional<bool> SetRootDirectoryEntryFlags(uint8_t mask, uint8_t values, uint32_t collectionEntryByteAddress);
|
||||
|
||||
device_eventhandler_t report;
|
||||
std::shared_ptr<Communication> com;
|
||||
std::shared_ptr<IDeviceSettings> settings;
|
||||
|
||||
@@ -897,11 +903,14 @@ public:
|
||||
bool unlockAllNetworks();
|
||||
std::shared_ptr<NetworkMutexMessage> getNetworkMutexStatus(Network::NetID network);
|
||||
|
||||
void startHeartbeat();
|
||||
void stopHeartbeat();
|
||||
void restartHeartbeat();
|
||||
|
||||
protected:
|
||||
bool online = false;
|
||||
int messagePollingCallbackID = 0;
|
||||
int internalHandlerCallbackID = 0;
|
||||
device_eventhandler_t report;
|
||||
|
||||
std::mutex ioMutex;
|
||||
std::optional<bool> ethActivationStatus;
|
||||
@@ -934,7 +943,7 @@ protected:
|
||||
std::move(decoder)
|
||||
);
|
||||
setupCommunication(*com);
|
||||
settings = makeSettings<Settings>(com);
|
||||
settings = makeSettings<Settings>(this);
|
||||
setupSettings(*settings);
|
||||
diskReadDriver = std::unique_ptr<DiskRead>(new DiskRead());
|
||||
diskWriteDriver = std::unique_ptr<DiskWrite>(new DiskWrite());
|
||||
@@ -970,8 +979,8 @@ protected:
|
||||
}
|
||||
|
||||
template<typename Settings>
|
||||
std::shared_ptr<IDeviceSettings> makeSettings(std::shared_ptr<Communication> comm) {
|
||||
return std::make_shared<Settings>(comm);
|
||||
std::shared_ptr<IDeviceSettings> makeSettings(Device* device) {
|
||||
return std::make_shared<Settings>(device);
|
||||
}
|
||||
virtual void setupSettings(IDeviceSettings&) {}
|
||||
|
||||
@@ -1036,10 +1045,6 @@ private:
|
||||
|
||||
APIEvent::Type attemptToBeginCommunication();
|
||||
|
||||
// Use heartbeatSuppressed instead when reading
|
||||
std::atomic<int> heartbeatSuppressedByUser{0};
|
||||
bool heartbeatSuppressed() const { return heartbeatSuppressedByUser > 0 || (settings && settings->applyingSettings); }
|
||||
|
||||
void handleNeoVIMessage(std::shared_ptr<CANMessage> message);
|
||||
|
||||
bool firmwareUpdateSupported();
|
||||
@@ -1050,10 +1055,6 @@ private:
|
||||
moodycamel::BlockingConcurrentQueue<std::shared_ptr<Message>> pollingContainer;
|
||||
void enforcePollingMessageLimit();
|
||||
|
||||
std::atomic<bool> stopHeartbeatThread{false};
|
||||
std::mutex heartbeatMutex;
|
||||
std::thread heartbeatThread;
|
||||
|
||||
std::mutex diskMutex;
|
||||
|
||||
// Wireless neoVI Stack
|
||||
@@ -1176,6 +1177,7 @@ private:
|
||||
|
||||
// Keeponline (keepalive for online)
|
||||
std::unique_ptr<Periodic> keeponline;
|
||||
std::unique_ptr<Heartbeat> heartbeat;
|
||||
|
||||
std::optional<uint32_t> assignedClientId;
|
||||
std::unordered_set<icsneo::Network::NetID> lockedNetworks;
|
||||
|
||||
@@ -811,13 +811,17 @@ typedef struct
|
||||
#pragma pack(pop)
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "icsneo/communication/communication.h"
|
||||
#include "icsneo/communication/network.h"
|
||||
#include "icsneo/api/event.h"
|
||||
#include "icsneo/api/eventmanager.h"
|
||||
#include <optional>
|
||||
#include <iostream>
|
||||
#include <atomic>
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
class Device;
|
||||
|
||||
enum class MiscIOAnalogVoltage : uint8_t
|
||||
{
|
||||
V0 = icsneoc2_misc_io_analog_voltage_v0,
|
||||
@@ -845,7 +849,7 @@ public:
|
||||
static int64_t GetBaudrateValueForEnum(CANBaudrate enumValue);
|
||||
static bool ValidateLINBaudrate(int64_t baudrate);
|
||||
|
||||
IDeviceSettings(std::shared_ptr<Communication> com, size_t size) : com(com), report(com->report), structSize(size) {}
|
||||
IDeviceSettings(Device* device, size_t size);
|
||||
virtual ~IDeviceSettings() {}
|
||||
bool ok() const { return !disabled && settingsLoaded; }
|
||||
|
||||
@@ -1392,10 +1396,8 @@ public:
|
||||
bool disabled = false;
|
||||
|
||||
bool readonly = false;
|
||||
|
||||
std::atomic<bool> applyingSettings{false};
|
||||
protected:
|
||||
std::shared_ptr<Communication> com;
|
||||
Device* device;
|
||||
device_eventhandler_t report;
|
||||
size_t structSize;
|
||||
|
||||
@@ -1407,8 +1409,7 @@ protected:
|
||||
|
||||
// Parameter createInoperableSettings exists because it is serving as a warning that you probably don't want to do this
|
||||
typedef void* warn_t;
|
||||
IDeviceSettings(warn_t createInoperableSettings, std::shared_ptr<Communication> com)
|
||||
: disabled(true), readonly(true), report(com->report), structSize(0) { (void)createInoperableSettings; }
|
||||
IDeviceSettings(warn_t createInoperableSettings, Device* device);
|
||||
|
||||
// Devices that embed a Fire3LinuxSettings block in their settings structure override these to
|
||||
// expose it; all other devices report not-available (nullptr / nullopt) and the Linux accessors
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace icsneo {
|
||||
class NullSettings : public IDeviceSettings {
|
||||
public:
|
||||
// Calls the protected base constructor with "createInoperableSettings"
|
||||
NullSettings(std::shared_ptr<Communication> com) : IDeviceSettings(nullptr, com) {}
|
||||
NullSettings(Device* device) : IDeviceSettings(nullptr, device) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ static_assert(sizeof(etherbadge_settings_t) == 316, "EtherBadge settings size mi
|
||||
|
||||
class EtherBADGESettings : public IDeviceSettings {
|
||||
public:
|
||||
EtherBADGESettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(etherbadge_settings_t)) {}
|
||||
EtherBADGESettings(Device* device) : IDeviceSettings(device, sizeof(etherbadge_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<etherbadge_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -88,7 +88,7 @@ static_assert(sizeof(neoviconnect_settings_t) == 628, "NeoVIConnect settings siz
|
||||
|
||||
class NeoVIConnectSettings : public IDeviceSettings {
|
||||
public:
|
||||
NeoVIConnectSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neoviconnect_settings_t)) {}
|
||||
NeoVIConnectSettings(Device* device) : IDeviceSettings(device, sizeof(neoviconnect_settings_t)) {}
|
||||
const Fire3LinuxSettings* getLinuxSettings() const override {
|
||||
auto cfg = getStructurePointer<neoviconnect_settings_t>();
|
||||
return cfg ? &cfg->os_settings : nullptr;
|
||||
|
||||
@@ -101,7 +101,7 @@ static_assert(sizeof(neovifire_settings_t) == 744, "NeoVIFire settings size mism
|
||||
|
||||
class NeoVIFIRESettings : public IDeviceSettings {
|
||||
public:
|
||||
NeoVIFIRESettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire_settings_t)) {}
|
||||
NeoVIFIRESettings(Device* device) : IDeviceSettings(device, sizeof(neovifire_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<neovifire_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -125,7 +125,7 @@ static_assert(sizeof(neovifire2_settings_t) == 936, "NeoVIFire2 settings size mi
|
||||
|
||||
class NeoVIFIRE2Settings : public IDeviceSettings {
|
||||
public:
|
||||
NeoVIFIRE2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire2_settings_t)) {}
|
||||
NeoVIFIRE2Settings(Device* device) : IDeviceSettings(device, sizeof(neovifire2_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<neovifire2_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -166,7 +166,7 @@ static_assert(sizeof(neovifire3_settings_t) == 1722, "NeoVIFire3 settings size m
|
||||
|
||||
class NeoVIFIRE3Settings : public IDeviceSettings {
|
||||
public:
|
||||
NeoVIFIRE3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3_settings_t)) {}
|
||||
NeoVIFIRE3Settings(Device* device) : IDeviceSettings(device, sizeof(neovifire3_settings_t)) {}
|
||||
const Fire3LinuxSettings* getLinuxSettings() const override {
|
||||
auto cfg = getStructurePointer<neovifire3_settings_t>();
|
||||
return cfg ? &cfg->os_settings : nullptr;
|
||||
|
||||
@@ -149,7 +149,7 @@ static_assert(sizeof(neovifire3flexray_settings_t) == 1372, "NeoVIFire3Flexray s
|
||||
|
||||
class NeoVIFIRE3FlexRaySettings : public IDeviceSettings {
|
||||
public:
|
||||
NeoVIFIRE3FlexRaySettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3flexray_settings_t)) {}
|
||||
NeoVIFIRE3FlexRaySettings(Device* device) : IDeviceSettings(device, sizeof(neovifire3flexray_settings_t)) {}
|
||||
const Fire3LinuxSettings* getLinuxSettings() const override {
|
||||
auto cfg = getStructurePointer<neovifire3flexray_settings_t>();
|
||||
return cfg ? &cfg->os_settings : nullptr;
|
||||
|
||||
@@ -158,7 +158,7 @@ static_assert(sizeof(neovifire3t1slin_settings_t) == 1594, "NeoVIFire3T1SLIN set
|
||||
|
||||
class NeoVIFIRE3T1SLINSettings : public IDeviceSettings {
|
||||
public:
|
||||
NeoVIFIRE3T1SLINSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovifire3t1slin_settings_t)) {}
|
||||
NeoVIFIRE3T1SLINSettings(Device* device) : IDeviceSettings(device, sizeof(neovifire3t1slin_settings_t)) {}
|
||||
const Fire3LinuxSettings* getLinuxSettings() const override {
|
||||
auto cfg = getStructurePointer<neovifire3t1slin_settings_t>();
|
||||
return cfg ? &cfg->os_settings : nullptr;
|
||||
|
||||
@@ -111,7 +111,7 @@ static_assert(sizeof(neovired2_settings_t) == 918, "NeoVIRED2 settings size mism
|
||||
|
||||
class NeoVIRED2Settings : public IDeviceSettings {
|
||||
public:
|
||||
NeoVIRED2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(neovired2_settings_t)) {}
|
||||
NeoVIRED2Settings(Device* device) : IDeviceSettings(device, sizeof(neovired2_settings_t)) {}
|
||||
const Fire3LinuxSettings* getLinuxSettings() const override {
|
||||
auto cfg = getStructurePointer<neovired2_settings_t>();
|
||||
return cfg ? &cfg->os_settings : nullptr;
|
||||
|
||||
@@ -100,7 +100,7 @@ public:
|
||||
Node
|
||||
};
|
||||
|
||||
RADA2BSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(rada2b_settings_t)) {}
|
||||
RADA2BSettings(Device* device) : IDeviceSettings(device, sizeof(rada2b_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
@@ -141,27 +141,27 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
TDMMode getTDMMode(RADA2BDevice device) const {
|
||||
TDMMode getTDMMode(RADA2BDevice a2bDevice) const {
|
||||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
return static_cast<TDMMode>(deviceSettings.tdmMode);
|
||||
}
|
||||
|
||||
uint8_t getNumChannels(RADA2BDevice device) const {
|
||||
return tdmModeToChannelNum(getTDMMode(device));
|
||||
uint8_t getNumChannels(RADA2BDevice a2bDevice) const {
|
||||
return tdmModeToChannelNum(getTDMMode(a2bDevice));
|
||||
}
|
||||
|
||||
ChannelSize getChannelSize(RADA2BDevice device) const {
|
||||
ChannelSize getChannelSize(RADA2BDevice a2bDevice) const {
|
||||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
return static_cast<ChannelSize>(deviceSettings.flags & a2bSettingsFlag16bit);
|
||||
}
|
||||
|
||||
uint8_t getChannelOffset(RADA2BDevice device, A2BMessage::Direction dir) const {
|
||||
uint8_t getChannelOffset(RADA2BDevice a2bDevice, A2BMessage::Direction dir) const {
|
||||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
if(dir == A2BMessage::Direction::Upstream) {
|
||||
return deviceSettings.upstreamChannelOffset;
|
||||
@@ -170,30 +170,30 @@ public:
|
||||
return deviceSettings.downstreamChannelOffset;
|
||||
}
|
||||
|
||||
NodeType getNodeType(RADA2BDevice device) const {
|
||||
NodeType getNodeType(RADA2BDevice a2bDevice) const {
|
||||
auto cfg = getStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
return static_cast<NodeType>(deviceSettings.nodeType);
|
||||
}
|
||||
|
||||
void setNodeType(RADA2BDevice device, NodeType newType) {
|
||||
void setNodeType(RADA2BDevice a2bDevice, NodeType newType) {
|
||||
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
deviceSettings.nodeType = static_cast<uint8_t>(newType);
|
||||
}
|
||||
|
||||
void setTDMMode(RADA2BDevice device, TDMMode newMode) {
|
||||
void setTDMMode(RADA2BDevice a2bDevice, TDMMode newMode) {
|
||||
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
deviceSettings.tdmMode = static_cast<uint8_t>(newMode);
|
||||
}
|
||||
|
||||
void setChannelOffset(RADA2BDevice device, A2BMessage::Direction dir, uint8_t newOffset) {
|
||||
void setChannelOffset(RADA2BDevice a2bDevice, A2BMessage::Direction dir, uint8_t newOffset) {
|
||||
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
if(dir == A2BMessage::Direction::Upstream) {
|
||||
deviceSettings.upstreamChannelOffset = newOffset;
|
||||
@@ -203,9 +203,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void setChannelSize(RADA2BDevice device, ChannelSize newChannelSize) {
|
||||
void setChannelSize(RADA2BDevice a2bDevice, ChannelSize newChannelSize) {
|
||||
auto cfg = getMutableStructurePointer<rada2b_settings_t>();
|
||||
auto &deviceSettings = device == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
auto &deviceSettings = a2bDevice == RADA2BDevice::Monitor ? cfg->a2b_monitor : cfg->a2b_node;
|
||||
|
||||
if(newChannelSize == ChannelSize::chSize16) {
|
||||
deviceSettings.flags |= a2bSettingsFlag16bit;
|
||||
|
||||
@@ -89,7 +89,7 @@ static_assert(sizeof(radcomet2_settings_t) == 498, "RADComet2 settings size mism
|
||||
|
||||
class RADComet2Settings : public IDeviceSettings {
|
||||
public:
|
||||
RADComet2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radcomet2_settings_t)) {}
|
||||
RADComet2Settings(Device* device) : IDeviceSettings(device, sizeof(radcomet2_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<radcomet2_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -86,7 +86,7 @@ static_assert(sizeof(radcomet3_settings_t) == 674, "RADComet3 settings size mism
|
||||
|
||||
class RADComet3Settings : public IDeviceSettings {
|
||||
public:
|
||||
RADComet3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radcomet3_settings_t)) {}
|
||||
RADComet3Settings(Device* device) : IDeviceSettings(device, sizeof(radcomet3_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<radcomet3_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -86,7 +86,7 @@ static_assert(sizeof(radepsilon_settings_t) == 400, "RADEpsilon settings size mi
|
||||
|
||||
class RADEpsilonSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADEpsilonSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radepsilon_settings_t)) {}
|
||||
RADEpsilonSettings(Device* device) : IDeviceSettings(device, sizeof(radepsilon_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<radepsilon_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -109,7 +109,7 @@ static_assert(sizeof(radgalaxy_settings_t) == 776, "RADGalaxy settings size mism
|
||||
|
||||
class RADGalaxySettings : public IDeviceSettings {
|
||||
public:
|
||||
RADGalaxySettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgalaxy_settings_t)) {}
|
||||
RADGalaxySettings(Device* device) : IDeviceSettings(device, sizeof(radgalaxy_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<radgalaxy_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -125,7 +125,7 @@ static_assert(sizeof(radgalaxy2_settings_t) == 960, "RADGalaxy2 settings size mi
|
||||
|
||||
class RADGalaxy2Settings : public IDeviceSettings {
|
||||
public:
|
||||
RADGalaxy2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgalaxy2_settings_t)) {}
|
||||
RADGalaxy2Settings(Device* device) : IDeviceSettings(device, sizeof(radgalaxy2_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<radgalaxy2_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -42,7 +42,7 @@ static_assert(sizeof(radgemini_settings_t) == 86, "RADGemini settings size misma
|
||||
|
||||
class RADGeminiSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADGeminiSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgemini_settings_t)) {}
|
||||
RADGeminiSettings(Device* device) : IDeviceSettings(device, sizeof(radgemini_settings_t)) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ static_assert(sizeof(radgigastar_settings_t) == 1026, "RADGigastar settings size
|
||||
|
||||
class RADGigastarSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADGigastarSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgigastar_settings_t)) {}
|
||||
RADGigastarSettings(Device* device) : IDeviceSettings(device, sizeof(radgigastar_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<radgigastar_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace icsneo
|
||||
class RADGigastar2Settings : public IDeviceSettings
|
||||
{
|
||||
public:
|
||||
RADGigastar2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radgigastar2_settings_t)) {}
|
||||
RADGigastar2Settings(Device* device) : IDeviceSettings(device, sizeof(radgigastar2_settings_t)) {}
|
||||
const CAN_SETTINGS *getCANSettingsFor(Network net) const override
|
||||
{
|
||||
auto cfg = getStructurePointer<radgigastar2_settings_t>();
|
||||
|
||||
@@ -90,7 +90,7 @@ static_assert(sizeof(radjupiter_settings_t) == 348, "RAD-Jupiter Settings are no
|
||||
|
||||
class RADJupiterSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADJupiterSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radjupiter_settings_t)) {}
|
||||
RADJupiterSettings(Device* device) : IDeviceSettings(device, sizeof(radjupiter_settings_t)) {}
|
||||
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<radjupiter_settings_t>();
|
||||
|
||||
@@ -101,7 +101,7 @@ static_assert(sizeof(radmars_settings_t) == 666, "RAD-Mars settings size mismatc
|
||||
|
||||
class RADMarsSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADMarsSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmars_settings_t)) {}
|
||||
RADMarsSettings(Device* device) : IDeviceSettings(device, sizeof(radmars_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<radmars_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -42,7 +42,7 @@ static_assert(sizeof(radmoon2_settings_t) == 170, "RADMoon2 settings size mismat
|
||||
|
||||
class RADMoon2Settings : public IDeviceSettings {
|
||||
public:
|
||||
RADMoon2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoon2_settings_t)) {}
|
||||
RADMoon2Settings(Device* device) : IDeviceSettings(device, sizeof(radmoon2_settings_t)) {}
|
||||
|
||||
const RAD_GPTP_SETTINGS* getGPTPSettings() const override {
|
||||
auto cfg = getStructurePointer<radmoon2_settings_t>();
|
||||
|
||||
@@ -39,7 +39,7 @@ static_assert(sizeof(radmoon3_settings_t) == 68, "RADMoon3 settings size mismatc
|
||||
|
||||
class RADMoon3Settings : public IDeviceSettings {
|
||||
public:
|
||||
RADMoon3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoon3_settings_t)) {}
|
||||
RADMoon3Settings(Device* device) : IDeviceSettings(device, sizeof(radmoon3_settings_t)) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ static_assert(sizeof(radmoonduo_settings_t) == 38, "RAD-Moon Duo settings size e
|
||||
|
||||
class RADMoonDuoSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADMoonDuoSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoonduo_settings_t)) {}
|
||||
RADMoonDuoSettings(Device* device) : IDeviceSettings(device, sizeof(radmoonduo_settings_t)) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ static_assert(sizeof(radmoont1s_settings_t) == 160, "RADMoonT1S settings size mi
|
||||
|
||||
class RADMoonT1SSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADMoonT1SSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radmoont1s_settings_t)) {}
|
||||
RADMoonT1SSettings(Device* device) : IDeviceSettings(device, sizeof(radmoont1s_settings_t)) {}
|
||||
|
||||
std::optional<bool> isT1SPLCAEnabledFor(Network net) const override {
|
||||
const ETHERNET10T1S_SETTINGS* t1s = getT1SSettingsFor(net);
|
||||
|
||||
@@ -74,7 +74,7 @@ static_assert(sizeof(radpluto_settings_t) == 322, "RAD-Pluto Settings are not pa
|
||||
|
||||
class RADPlutoSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADPlutoSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radpluto_settings_t)) {
|
||||
RADPlutoSettings(Device* device) : IDeviceSettings(device, sizeof(radpluto_settings_t)) {
|
||||
}
|
||||
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
|
||||
@@ -75,7 +75,7 @@ static_assert(sizeof(radstar2_settings_t) == 422, "RADStar2 settings size mismat
|
||||
|
||||
class RADStar2Settings : public IDeviceSettings {
|
||||
public:
|
||||
RADStar2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radstar2_settings_t)) {
|
||||
RADStar2Settings(Device* device) : IDeviceSettings(device, sizeof(radstar2_settings_t)) {
|
||||
}
|
||||
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
|
||||
@@ -38,7 +38,7 @@ typedef struct {
|
||||
|
||||
class RADSupermoonSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADSupermoonSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radsupermoon_settings_t)) {}
|
||||
RADSupermoonSettings(Device* device) : IDeviceSettings(device, sizeof(radsupermoon_settings_t)) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "icsneo/device/device.h"
|
||||
#include "icsneo/device/devicetype.h"
|
||||
#include "icsneo/device/tree/radwbms/radwbmssettings.h"
|
||||
#include "icsneo/disk/neomemorydiskdriver.h"
|
||||
|
||||
namespace icsneo {
|
||||
|
||||
@@ -126,6 +127,8 @@ public:
|
||||
static std::vector<ChipInfo> chips = {{ChipID::RADBMS_MCHIP, true, "MCHIP", "rad_bms_mchip_WIL_3_3_0_27_ief", 0, FirmwareType::IEF}};
|
||||
return chips;
|
||||
}
|
||||
case FirmwareVariant::Invalid:
|
||||
break; // invalid will be handled below
|
||||
}
|
||||
// Return empty chip information if the WIL version is not set
|
||||
static std::vector<ChipInfo> chips = {};
|
||||
|
||||
@@ -70,7 +70,7 @@ static_assert(sizeof(radwbms_settings_t) == 156, "RAD-wBMS settings size mismatc
|
||||
|
||||
class RADwBMSSettings : public IDeviceSettings {
|
||||
public:
|
||||
RADwBMSSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(radwbms_settings_t)) {}
|
||||
RADwBMSSettings(Device* device) : IDeviceSettings(device, sizeof(radwbms_settings_t)) {}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ static_assert(sizeof(valuecan3_settings_t) == 40, "ValueCAN3 settings size misma
|
||||
|
||||
class ValueCAN3Settings : public IDeviceSettings {
|
||||
public:
|
||||
ValueCAN3Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan3_settings_t)) {}
|
||||
ValueCAN3Settings(Device* device) : IDeviceSettings(device, sizeof(valuecan3_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<valuecan3_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace icsneo {
|
||||
|
||||
class ValueCAN4_1_2Settings : public IDeviceSettings {
|
||||
public:
|
||||
ValueCAN4_1_2Settings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_1_2_settings_t)) {}
|
||||
ValueCAN4_1_2Settings(Device* device) : IDeviceSettings(device, sizeof(valuecan4_1_2_settings_t)) {}
|
||||
// We do not override getCANSettingsFor or getCANFDSettingsFor here because they will be device specific
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace icsneo {
|
||||
|
||||
class ValueCAN4_1Settings : public ValueCAN4_1_2Settings {
|
||||
public:
|
||||
ValueCAN4_1Settings(std::shared_ptr<Communication> com) : ValueCAN4_1_2Settings(com) {}
|
||||
ValueCAN4_1Settings(Device* device) : ValueCAN4_1_2Settings(device) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<valuecan4_1_2_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace icsneo {
|
||||
|
||||
class ValueCAN4_2ELSettings : public ValueCAN4_4_2ELSettings {
|
||||
public:
|
||||
ValueCAN4_2ELSettings(std::shared_ptr<Communication> com) : ValueCAN4_4_2ELSettings(com) {}
|
||||
ValueCAN4_2ELSettings(Device* device) : ValueCAN4_4_2ELSettings(device) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace icsneo {
|
||||
|
||||
class ValueCAN4_2Settings : public ValueCAN4_1_2Settings {
|
||||
public:
|
||||
ValueCAN4_2Settings(std::shared_ptr<Communication> com) : ValueCAN4_1_2Settings(com) {}
|
||||
ValueCAN4_2Settings(Device* device) : ValueCAN4_1_2Settings(device) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<valuecan4_1_2_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace icsneo {
|
||||
|
||||
class ValueCAN4_4_2ELSettings : public IDeviceSettings {
|
||||
public:
|
||||
ValueCAN4_4_2ELSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_4_2el_settings_t)) {}
|
||||
ValueCAN4_4_2ELSettings(Device* device) : IDeviceSettings(device, sizeof(valuecan4_4_2el_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace icsneo {
|
||||
|
||||
class ValueCAN4_4Settings : public ValueCAN4_4_2ELSettings {
|
||||
public:
|
||||
ValueCAN4_4Settings(std::shared_ptr<Communication> com) : ValueCAN4_4_2ELSettings(com) {}
|
||||
ValueCAN4_4Settings(Device* device) : ValueCAN4_4_2ELSettings(device) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<valuecan4_4_2el_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace icsneo {
|
||||
|
||||
class ValueCAN4IndustrialSettings : public IDeviceSettings {
|
||||
public:
|
||||
ValueCAN4IndustrialSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(valuecan4_industrial_settings_t)) {}
|
||||
ValueCAN4IndustrialSettings(Device* device) : IDeviceSettings(device, sizeof(valuecan4_industrial_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<valuecan4_industrial_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -48,7 +48,7 @@ static_assert(sizeof(vividcan_settings_t) == 64, "VividCAN settings size mismatc
|
||||
|
||||
class VividCANSettings : public IDeviceSettings {
|
||||
public:
|
||||
VividCANSettings(std::shared_ptr<Communication> com) : IDeviceSettings(com, sizeof(vividcan_settings_t)) {}
|
||||
VividCANSettings(Device* device) : IDeviceSettings(device, sizeof(vividcan_settings_t)) {}
|
||||
const CAN_SETTINGS* getCANSettingsFor(Network net) const override {
|
||||
auto cfg = getStructurePointer<vividcan_settings_t>();
|
||||
if(cfg == nullptr)
|
||||
|
||||
@@ -44,7 +44,10 @@ typedef unsigned __int64 uint64_t;
|
||||
#include "cicsSpyStatusBits.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable : 4200)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4200) // zero-sized array in struct/union
|
||||
#pragma warning(disable : 4201) // nameless struct/union
|
||||
#pragma warning(disable : 4121) // member alignment sensitive to packing
|
||||
#endif
|
||||
|
||||
// MSVC++ 10.0 _MSC_VER == 1600 64-bit version doesn't allow multi-line #if directives...
|
||||
@@ -5440,4 +5443,8 @@ CHECK_STRUCT_SIZE(FlashAccessoryFirmwareParams);
|
||||
#undef CHECK_STRUCT_SIZE
|
||||
#endif /* INTREPID_NO_CHECK_STRUCT_SIZE */
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif /* _ICSNVC40_H */
|
||||
|
||||
+5
-1
@@ -243,6 +243,7 @@ bool Servd::enableCommunication(bool enable, bool& sendMsg) {
|
||||
}
|
||||
|
||||
void Servd::read() {
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
std::vector<uint8_t> buf(2 * 1024 * 1024);
|
||||
while(!isDisconnected() && !isClosing()) {
|
||||
bool hasData;
|
||||
@@ -260,11 +261,14 @@ void Servd::read() {
|
||||
setIsDisconnected(true);
|
||||
return;
|
||||
}
|
||||
pushRx(buf.data(), bufSize);
|
||||
if(!pushRx(buf.data(), bufSize)) {
|
||||
EventManager::GetInstance().add(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Servd::write() {
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
WriteOperation writeOp;
|
||||
while(!isDisconnected() && !isClosing()) {
|
||||
if(!writeQueue.wait_dequeue_timed(writeOp, std::chrono::milliseconds(100))) {
|
||||
|
||||
Reference in New Issue
Block a user