mirror of
https://github.com/intrepidcs/libicsneo.git
synced 2026-08-05 09:28:40 +02:00
Add device sharing support
This commit is contained in:
@@ -65,8 +65,8 @@ void FirmIO::Find(std::vector<FoundDevice>& found) {
|
||||
memcpy(foundDevice.serial, serial->deviceSerial.c_str(), sizeof(foundDevice.serial) - 1);
|
||||
foundDevice.serial[sizeof(foundDevice.serial) - 1] = '\0';
|
||||
|
||||
foundDevice.makeDriver = [](const device_eventhandler_t& report, neodevice_t&) {
|
||||
return std::unique_ptr<Driver>(new FirmIO(report));
|
||||
foundDevice.makeDriver = [](const device_eventhandler_t& report, neodevice_t& forDevice) {
|
||||
return std::unique_ptr<Driver>(new FirmIO(report, forDevice));
|
||||
};
|
||||
|
||||
found.push_back(foundDevice);
|
||||
|
||||
@@ -47,7 +47,7 @@ void FTDI::Find(std::vector<FoundDevice>& found) {
|
||||
}
|
||||
}
|
||||
|
||||
FTDI::FTDI(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice) {
|
||||
FTDI::FTDI(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err, forDevice) {
|
||||
openable = strlen(forDevice.serial) > 0 && device.handle >= 0 && device.handle < (neodevice_handle_t)handles.size();
|
||||
}
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ bool PCAP::IsHandleValid(neodevice_handle_t handle) {
|
||||
return (netifIndex < knownInterfaces.size());
|
||||
}
|
||||
|
||||
PCAP::PCAP(device_eventhandler_t err, neodevice_t& forDevice) : Driver(err), device(forDevice), ethPacketizer(err) {
|
||||
PCAP::PCAP(device_eventhandler_t err, neodevice_t& forDevice) : Driver(err, forDevice), ethPacketizer(err) {
|
||||
if(IsHandleValid(device.handle)) {
|
||||
iface = knownInterfaces[(device.handle >> 24) & 0xFF];
|
||||
iface.fp = nullptr; // We're going to open our own connection to the interface. This should already be nullptr but just in case.
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
#include <iostream> // TODO: Remove later
|
||||
#include <sys/mman.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "icsneo/platform/posix/sharedmemory.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
SharedMemory::~SharedMemory() {
|
||||
close();
|
||||
}
|
||||
|
||||
bool SharedMemory::open(const std::string& name, uint32_t size, bool create) {
|
||||
if(create)
|
||||
shm_unlink(name.c_str());
|
||||
const auto fd = create ? shm_open(name.c_str(), O_CREAT | O_RDWR | O_EXCL, 0600) : shm_open(name.c_str(), O_RDWR, 0);
|
||||
if(fd == -1) {
|
||||
report(APIEvent::Type::SharedMemoryFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
mName.emplace(name);
|
||||
if(create && ftruncate(fd, size) == -1) {
|
||||
report(APIEvent::Type::SharedMemoryFileTruncateError, APIEvent::Severity::Error);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
const auto shm = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if(shm == MAP_FAILED) {
|
||||
report(APIEvent::Type::SharedMemoryMappingError, APIEvent::Severity::Error);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
mData.emplace(std::make_pair((uint8_t*)shm, size));
|
||||
mCreated.emplace(create);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedMemory::close() {
|
||||
bool failed = false;
|
||||
if(mData) {
|
||||
if(munmap((void*)mData->first, mData->second) == -1) {
|
||||
report(APIEvent::Type::SharedMemoryUnmapError, APIEvent::Severity::EventWarning);
|
||||
failed = true;
|
||||
}
|
||||
mData.reset();
|
||||
}
|
||||
if(mName && mCreated && *mCreated) {
|
||||
if(shm_unlink(mName->c_str()) == -1) {
|
||||
report(APIEvent::Type::SharedMemoryFailedToUnlink, APIEvent::Severity::EventWarning);
|
||||
failed = true;
|
||||
}
|
||||
mName.reset();
|
||||
}
|
||||
if(failed)
|
||||
report(APIEvent::Type::SharedMemoryFailedToClose, APIEvent::Severity::Error);
|
||||
return !failed;
|
||||
}
|
||||
|
||||
uint8_t* SharedMemory::data() {
|
||||
if(!mData) {
|
||||
report(APIEvent::Type::SharedMemoryDataIsNull, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
return mData->first;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
#include <iostream> // TODO: Remove later
|
||||
#include <fcntl.h>
|
||||
#include "icsneo/platform/posix/sharedsemaphore.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
SharedSemaphore::~SharedSemaphore() {
|
||||
close();
|
||||
}
|
||||
|
||||
bool SharedSemaphore::open(const std::string& name, bool create, unsigned initialCount) {
|
||||
const auto slashPrefixed = "/" + name;
|
||||
if(create)
|
||||
sem_unlink(slashPrefixed.c_str()); // try clean-up, it's fine if it errors
|
||||
const auto sem = create ? sem_open(slashPrefixed.c_str(), O_CREAT | O_EXCL, 0600, initialCount) : sem_open(slashPrefixed.c_str(), 0);
|
||||
if(sem == SEM_FAILED) {
|
||||
report(APIEvent::Type::SharedSemaphoreFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
mName.emplace(slashPrefixed);
|
||||
semaphore.emplace(sem);
|
||||
created.emplace(create);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedSemaphore::close() {
|
||||
closing = true;
|
||||
|
||||
post(); // wake any waiting
|
||||
|
||||
bool failed = false;
|
||||
if(semaphore) {
|
||||
if(sem_close(semaphore.value()) == -1) {
|
||||
report(APIEvent::Type::SharedSemaphoreFailedToClose, APIEvent::Severity::Error);
|
||||
failed = true;
|
||||
}
|
||||
semaphore.reset();
|
||||
}
|
||||
if(mName && created && *created) {
|
||||
if(sem_unlink(mName->c_str()) == -1) {
|
||||
report(APIEvent::Type::SharedSemaphoreFailedToUnlink, APIEvent::Severity::Error);
|
||||
failed = true;
|
||||
}
|
||||
mName.reset();
|
||||
}
|
||||
return !failed;
|
||||
}
|
||||
|
||||
bool SharedSemaphore::wait(const std::chrono::milliseconds& timeout) {
|
||||
if(!semaphore) {
|
||||
report(APIEvent::Type::SharedSemaphoreNotOpenForWait, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
const auto timedwait = [&]() -> bool {
|
||||
#if defined(__MACH__)
|
||||
// TODO: Quite inefficient due to Darwin's lack of sem_timedwait()
|
||||
const auto tryTill = std::chrono::steady_clock::now() + timeout;
|
||||
while (std::chrono::steady_clock::now() <= tryTill) {
|
||||
if(sem_trywait(*semaphore) == 0)
|
||||
return true;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
return false;
|
||||
#else // UNIX
|
||||
struct timespec ts;
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
ts.tv_sec += static_cast<unsigned int>(timeout.count() / 1000);
|
||||
ts.tv_nsec += static_cast<int>((timeout.count() % 1000) * 1000000);
|
||||
// potentially promote another second
|
||||
if(ts.tv_nsec >= 1000000000) {
|
||||
ts.tv_nsec -= 1000000000;
|
||||
++ts.tv_sec;
|
||||
}
|
||||
return sem_timedwait(*semaphore, &ts) != -1;
|
||||
#endif
|
||||
};
|
||||
if(!timedwait()) {
|
||||
if(errno == ETIMEDOUT)
|
||||
return false; // unable to lock within timeout
|
||||
if(errno != EINTR) // we don't need a warning for this
|
||||
report(APIEvent::Type::SharedSemaphoreFailedToWait, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
if(closing)
|
||||
return false; // we were woken by close()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedSemaphore::post() {
|
||||
if(!semaphore) {
|
||||
report(APIEvent::Type::SharedSemaphoreNotOpenForPost, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
if(sem_post(*semaphore) == -1) {
|
||||
report(APIEvent::Type::SharedSemaphoreFailedToPost, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -166,8 +166,8 @@ void PCAP::Find(std::vector<FoundDevice>& found) {
|
||||
memcpy(foundDevice.serial, serial->deviceSerial.c_str(), sizeof(foundDevice.serial) - 1);
|
||||
foundDevice.serial[sizeof(foundDevice.serial) - 1] = '\0';
|
||||
|
||||
foundDevice.makeDriver = [](const device_eventhandler_t& reportFn, neodevice_t& device) {
|
||||
return std::unique_ptr<Driver>(new PCAP(reportFn, device));
|
||||
foundDevice.makeDriver = [](const device_eventhandler_t& reportFn, neodevice_t& forDevice) {
|
||||
return std::unique_ptr<Driver>(new PCAP(reportFn, forDevice));
|
||||
};
|
||||
|
||||
found.push_back(foundDevice);
|
||||
@@ -184,7 +184,7 @@ bool PCAP::IsHandleValid(neodevice_handle_t handle) {
|
||||
return (netifIndex < knownInterfaces.size());
|
||||
}
|
||||
|
||||
PCAP::PCAP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice), pcap(PCAPDLL::getInstance()), ethPacketizer(err) {
|
||||
PCAP::PCAP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err, forDevice), pcap(PCAPDLL::getInstance()), ethPacketizer(err) {
|
||||
if(IsHandleValid(device.handle)) {
|
||||
iface = knownInterfaces[(device.handle >> 24) & 0xFF];
|
||||
iface.fp = nullptr; // We're going to open our own connection to the interface. This should already be nullptr but just in case.
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#include "icsneo/api/event.h"
|
||||
#include "icsneo/platform/windows/sharedmemory.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
SharedMemory::~SharedMemory() {
|
||||
close();
|
||||
}
|
||||
|
||||
bool SharedMemory::open(const std::string& name, uint32_t size, bool create) {
|
||||
HANDLE shm;
|
||||
if(create)
|
||||
shm = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, name.c_str());
|
||||
else
|
||||
shm = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name.c_str());
|
||||
|
||||
if(shm == NULL) {
|
||||
report(APIEvent::Type::SharedMemoryFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
mHandle.emplace(shm);
|
||||
const auto dataStart = MapViewOfFile(shm, FILE_MAP_ALL_ACCESS, 0, 0, size);
|
||||
if(dataStart == NULL) {
|
||||
report(APIEvent::Type::SharedMemoryMappingError, APIEvent::Severity::Error);
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
mData.emplace(std::make_pair((uint8_t*)dataStart, size));
|
||||
mCreated.emplace(create);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedMemory::close() {
|
||||
bool failed = false; // TODO: need to close properly
|
||||
if(failed) {
|
||||
report(APIEvent::Type::SharedMemoryFailedToClose, APIEvent::Severity::Error);
|
||||
}
|
||||
return !failed;
|
||||
}
|
||||
|
||||
uint8_t* SharedMemory::data() {
|
||||
if(!mData) {
|
||||
report(APIEvent::Type::SharedMemoryDataIsNull, APIEvent::Severity::Error);
|
||||
return nullptr;
|
||||
}
|
||||
return mData->first;
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "icsneo/platform/windows/sharedsemaphore.h"
|
||||
|
||||
using namespace icsneo;
|
||||
|
||||
SharedSemaphore::~SharedSemaphore() {
|
||||
close();
|
||||
}
|
||||
|
||||
bool SharedSemaphore::open(const std::string& name, bool create, unsigned initialCount) {
|
||||
HANDLE sem;
|
||||
if(create)
|
||||
sem = CreateSemaphore(NULL, initialCount, LONG_MAX, name.c_str());
|
||||
else
|
||||
sem = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, name.c_str());
|
||||
|
||||
if(sem == NULL) {
|
||||
report(APIEvent::Type::SharedSemaphoreFailedToOpen, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
semaphore.emplace(sem);
|
||||
created.emplace(create);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedSemaphore::close() {
|
||||
if(!semaphore)
|
||||
return false;
|
||||
|
||||
closing = true;
|
||||
|
||||
post(); // wake any waiting
|
||||
|
||||
if(CloseHandle(*semaphore) == 0) {
|
||||
report(APIEvent::Type::SharedSemaphoreFailedToClose, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
semaphore.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedSemaphore::wait(const std::chrono::milliseconds& timeout) {
|
||||
if(!semaphore) {
|
||||
report(APIEvent::Type::SharedSemaphoreNotOpenForWait, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
if(WaitForSingleObject(*semaphore, static_cast<DWORD>(timeout.count())) != 0) {
|
||||
report(APIEvent::Type::SharedSemaphoreFailedToWait, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
if(closing)
|
||||
return false; // we were woken by close()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedSemaphore::post() {
|
||||
if(!semaphore) {
|
||||
report(APIEvent::Type::SharedSemaphoreNotOpenForPost, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
if(ReleaseSemaphore(*semaphore, 1, NULL) == 0) {
|
||||
report(APIEvent::Type::SharedSemaphoreFailedToPost, APIEvent::Severity::Error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -192,7 +192,7 @@ void VCP::Find(std::vector<FoundDevice>& found, std::vector<std::wstring> driver
|
||||
}
|
||||
}
|
||||
|
||||
VCP::VCP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice) {
|
||||
VCP::VCP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err, forDevice) {
|
||||
detail = std::make_shared<Detail>();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user