mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 01:18:36 +02:00
Add device sharing support
This commit is contained in:
+101
-53
@@ -13,6 +13,10 @@
|
||||
#include <sstream>
|
||||
#include <chrono>
|
||||
|
||||
#ifdef ICSNEO_ENABLE_DEVICE_SHARING
|
||||
#include "icsneo/communication/socket.h"
|
||||
#endif
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
static const uint8_t fromBase36Table[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
@@ -178,6 +182,15 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef ICSNEO_ENABLE_DEVICE_SHARING
|
||||
{
|
||||
auto socket = lockSocket();
|
||||
if(!(socket.writeTyped(RPC::DEVICE_OPEN) && socket.writeString(getSerial())))
|
||||
return false;
|
||||
if(bool ret; !(socket.readTyped(ret) && ret))
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
APIEvent::Type attemptErr = attemptToBeginCommunication();
|
||||
if(attemptErr != APIEvent::Type::NoErrorFound) {
|
||||
// We could not communicate with the device, let's see if an extension can
|
||||
@@ -199,6 +212,7 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool block = false;
|
||||
forEachExtension([&block, &flags, &handler](const std::shared_ptr<DeviceExtension>& ext) {
|
||||
@@ -228,59 +242,61 @@ bool Device::open(OpenFlags flags, OpenStatusHandler handler) {
|
||||
handleInternalMessage(message);
|
||||
}));
|
||||
|
||||
heartbeatThread = std::thread([this]() {
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
if(com->driver->enableHeartbeat()) {
|
||||
heartbeatThread = std::thread([this]() {
|
||||
EventManager::GetInstance().downgradeErrorsOnCurrentThread();
|
||||
|
||||
MessageFilter filter;
|
||||
filter.includeInternalInAny = true;
|
||||
std::atomic<bool> receivedMessage{false};
|
||||
auto messageReceivedCallbackID = com->addMessageCallback(std::make_shared<MessageCallback>(filter, [&receivedMessage](std::shared_ptr<Message> message) {
|
||||
receivedMessage = true;
|
||||
}));
|
||||
MessageFilter filter;
|
||||
filter.includeInternalInAny = true;
|
||||
std::atomic<bool> receivedMessage{false};
|
||||
auto messageReceivedCallbackID = com->addMessageCallback(std::make_shared<MessageCallback>(filter, [&receivedMessage](std::shared_ptr<Message> message) {
|
||||
receivedMessage = true;
|
||||
}));
|
||||
|
||||
// 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) {
|
||||
// Wait for 110ms for a possible heartbeat
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(110));
|
||||
if(receivedMessage) {
|
||||
receivedMessage = false;
|
||||
} else {
|
||||
// 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::lock_guard<std::mutex> lk(heartbeatMutex);
|
||||
if(heartbeatSuppressed())
|
||||
continue;
|
||||
|
||||
// No heartbeat received, request a status
|
||||
com->sendCommand(Command::RequestStatusUpdate);
|
||||
// The response should come back quickly if the com is quiet
|
||||
// Give the device time to get situated
|
||||
auto i = 150;
|
||||
while(!stopHeartbeatThread && i != 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
// Check if we got a message, and if not, if settings are being applied
|
||||
i--;
|
||||
}
|
||||
|
||||
while(!stopHeartbeatThread) {
|
||||
// Wait for 110ms for a possible heartbeat
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(110));
|
||||
if(receivedMessage) {
|
||||
receivedMessage = false;
|
||||
} else {
|
||||
if(!stopHeartbeatThread && !isDisconnected())
|
||||
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
|
||||
break;
|
||||
// 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::lock_guard<std::mutex> lk(heartbeatMutex);
|
||||
if(heartbeatSuppressed())
|
||||
continue;
|
||||
|
||||
// No heartbeat received, request a status
|
||||
com->sendCommand(Command::RequestStatusUpdate);
|
||||
// The response should come back quickly if the com is quiet
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
// Check if we got a message, and if not, if settings are being applied
|
||||
if(receivedMessage) {
|
||||
receivedMessage = false;
|
||||
} else {
|
||||
if(!stopHeartbeatThread && !isDisconnected())
|
||||
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
com->removeMessageCallback(messageReceivedCallbackID);
|
||||
});
|
||||
|
||||
com->removeMessageCallback(messageReceivedCallbackID);
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -338,19 +354,36 @@ bool Device::close() {
|
||||
stopHeartbeatThread = false;
|
||||
|
||||
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onDeviceClose(); return true; });
|
||||
|
||||
#ifdef ICSNEO_ENABLE_DEVICE_SHARING
|
||||
{
|
||||
auto socket = lockSocket();
|
||||
if(!(socket.writeTyped(RPC::DEVICE_CLOSE) && socket.writeString(getSerial())))
|
||||
return false;
|
||||
if(bool ret; !(socket.readTyped(ret) && ret))
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
return com->close();
|
||||
}
|
||||
|
||||
bool Device::goOnline() {
|
||||
#ifdef ICSNEO_ENABLE_DEVICE_SHARING
|
||||
{
|
||||
auto socket = lockSocket();
|
||||
if(!(socket.writeTyped(RPC::DEVICE_GO_ONLINE) && socket.writeString(getSerial())))
|
||||
return false;
|
||||
if(bool ret; !(socket.readTyped(ret) && ret))
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
|
||||
if(!com->sendCommand(Command::EnableNetworkCommunication, true))
|
||||
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;
|
||||
|
||||
@@ -370,9 +403,13 @@ bool Device::goOnline() {
|
||||
if(failOut)
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
online = true;
|
||||
|
||||
ledState = LEDState::Online;
|
||||
|
||||
updateLEDState();
|
||||
|
||||
forEachExtension([](const std::shared_ptr<DeviceExtension>& ext) { ext->onGoOnline(); return true; });
|
||||
return true;
|
||||
}
|
||||
@@ -385,15 +422,21 @@ bool Device::goOffline() {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef ICSNEO_ENABLE_DEVICE_SHARING
|
||||
{
|
||||
auto socket = lockSocket();
|
||||
if(!(socket.writeTyped(RPC::DEVICE_GO_OFFLINE) && socket.writeString(getSerial())))
|
||||
return false;
|
||||
if(bool ret; !(socket.readTyped(ret) && ret))
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
|
||||
if(!com->sendCommand(Command::EnableNetworkCommunication, false))
|
||||
return false;
|
||||
|
||||
auto startTime = std::chrono::system_clock::now();
|
||||
|
||||
ledState = (latestResetStatus && latestResetStatus->cmRunning) ? LEDState::CoreMiniRunning : LEDState::Offline;
|
||||
|
||||
updateLEDState();
|
||||
|
||||
std::shared_ptr<MessageFilter> filter = std::make_shared<MessageFilter>(Network::NetID::Reset_Status);
|
||||
filter->includeInternalInAny = true;
|
||||
|
||||
@@ -407,6 +450,11 @@ bool Device::goOffline() {
|
||||
|
||||
com->waitForMessageSync(filter, std::chrono::milliseconds(100));
|
||||
}
|
||||
#endif
|
||||
|
||||
ledState = (latestResetStatus && latestResetStatus->cmRunning) ? LEDState::CoreMiniRunning : LEDState::Offline;
|
||||
|
||||
updateLEDState();
|
||||
|
||||
online = false;
|
||||
|
||||
|
||||
+32
-1
@@ -1,8 +1,13 @@
|
||||
#include <array>
|
||||
#include "icsneo/device/devicefinder.h"
|
||||
#include "icsneo/platform/devices.h"
|
||||
#include "icsneo/device/founddevice.h"
|
||||
#include "icsneo/communication/sdio.h"
|
||||
#include "generated/extensions/builtin.h"
|
||||
|
||||
#ifdef ICSNEO_ENABLE_DEVICE_SHARING
|
||||
#include "icsneo/communication/socket.h"
|
||||
#else
|
||||
#ifdef ICSNEO_ENABLE_FIRMIO
|
||||
#include "icsneo/platform/firmio.h"
|
||||
#endif
|
||||
@@ -18,6 +23,7 @@
|
||||
#ifdef ICSNEO_ENABLE_FTDI
|
||||
#include "icsneo/platform/ftdi.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
@@ -43,6 +49,9 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
|
||||
static std::vector<FoundDevice> newDriverFoundDevices;
|
||||
newDriverFoundDevices.clear();
|
||||
|
||||
#ifdef ICSNEO_ENABLE_DEVICE_SHARING
|
||||
SDIO::Find(newDriverFoundDevices);
|
||||
#else
|
||||
#ifdef ICSNEO_ENABLE_FIRMIO
|
||||
FirmIO::Find(newDriverFoundDevices);
|
||||
#endif
|
||||
@@ -58,6 +67,7 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
|
||||
#ifdef ICSNEO_ENABLE_FTDI
|
||||
FTDI::Find(newDriverFoundDevices);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Weak because we don't want to keep devices open if they go out of scope elsewhere
|
||||
static std::vector<std::weak_ptr<Device>> foundDevices;
|
||||
@@ -218,7 +228,27 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
|
||||
}
|
||||
|
||||
const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
|
||||
static std::vector<DeviceType> supportedDevices = {
|
||||
static std::vector<DeviceType> supportedDevices;
|
||||
|
||||
if (!supportedDevices.empty())
|
||||
return supportedDevices;
|
||||
|
||||
#ifdef ICSNEO_ENABLE_DEVICE_SHARING
|
||||
{
|
||||
auto socket = lockSocket();
|
||||
if(!socket.writeTyped(RPC::DEVICE_FINDER_GET_SUPORTED_DEVICES))
|
||||
return supportedDevices;
|
||||
uint16_t count;
|
||||
if(!socket.readTyped(count))
|
||||
return supportedDevices;
|
||||
std::vector<devicetype_t> devices(count);
|
||||
socket.read(devices.data(), devices.size() * sizeof(devicetype_t));
|
||||
supportedDevices.reserve(count);
|
||||
for(auto& dev : devices)
|
||||
supportedDevices.emplace_back(DeviceType(dev));
|
||||
}
|
||||
#else
|
||||
supportedDevices = {
|
||||
|
||||
#ifdef __ETHERBADGE_H_
|
||||
EtherBADGE::DEVICE_TYPE,
|
||||
@@ -321,6 +351,7 @@ const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
|
||||
#endif
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
return supportedDevices;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user