Repo: Normalize source files to LF

v0.3.0-dev
Paul Hollinsky 2022-03-27 14:37:39 -04:00
parent 781fc2c034
commit 008a1620c8
36 changed files with 3779 additions and 3779 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,48 +1,48 @@
#include "icsneo/icsneocpp.h" #include "icsneo/icsneocpp.h"
#include "icsneo/device/devicefinder.h" #include "icsneo/device/devicefinder.h"
using namespace icsneo; using namespace icsneo;
std::vector<std::shared_ptr<Device>> icsneo::FindAllDevices() { std::vector<std::shared_ptr<Device>> icsneo::FindAllDevices() {
return DeviceFinder::FindAll(); return DeviceFinder::FindAll();
} }
std::vector<DeviceType> icsneo::GetSupportedDevices() { std::vector<DeviceType> icsneo::GetSupportedDevices() {
return DeviceFinder::GetSupportedDevices(); return DeviceFinder::GetSupportedDevices();
} }
size_t icsneo::EventCount(EventFilter filter) { size_t icsneo::EventCount(EventFilter filter) {
return EventManager::GetInstance().eventCount(filter); return EventManager::GetInstance().eventCount(filter);
} }
std::vector<APIEvent> icsneo::GetEvents(EventFilter filter, size_t max) { std::vector<APIEvent> icsneo::GetEvents(EventFilter filter, size_t max) {
return EventManager::GetInstance().get(filter, max); return EventManager::GetInstance().get(filter, max);
} }
std::vector<APIEvent> icsneo::GetEvents(size_t max, EventFilter filter) { std::vector<APIEvent> icsneo::GetEvents(size_t max, EventFilter filter) {
return EventManager::GetInstance().get(max, filter); return EventManager::GetInstance().get(max, filter);
} }
void icsneo::GetEvents(std::vector<APIEvent>& events, EventFilter filter, size_t max) { void icsneo::GetEvents(std::vector<APIEvent>& events, EventFilter filter, size_t max) {
EventManager::GetInstance().get(events, filter, max); EventManager::GetInstance().get(events, filter, max);
} }
void icsneo::GetEvents(std::vector<APIEvent>& events, size_t max, EventFilter filter) { void icsneo::GetEvents(std::vector<APIEvent>& events, size_t max, EventFilter filter) {
EventManager::GetInstance().get(events, max, filter); EventManager::GetInstance().get(events, max, filter);
} }
APIEvent icsneo::GetLastError() { APIEvent icsneo::GetLastError() {
return EventManager::GetInstance().getLastError(); return EventManager::GetInstance().getLastError();
} }
void icsneo::DiscardEvents(EventFilter filter) { void icsneo::DiscardEvents(EventFilter filter) {
EventManager::GetInstance().discard(filter); EventManager::GetInstance().discard(filter);
} }
void icsneo::SetEventLimit(size_t newLimit) { void icsneo::SetEventLimit(size_t newLimit) {
EventManager::GetInstance().setEventLimit(newLimit); EventManager::GetInstance().setEventLimit(newLimit);
} }
size_t icsneo::GetEventLimit() { size_t icsneo::GetEventLimit() {
return EventManager::GetInstance().getEventLimit(); return EventManager::GetInstance().getEventLimit();
} }

View File

@ -1,264 +1,264 @@
#include "icsneo/device/devicefinder.h" #include "icsneo/device/devicefinder.h"
#include "icsneo/platform/devices.h" #include "icsneo/platform/devices.h"
#include "icsneo/device/founddevice.h" #include "icsneo/device/founddevice.h"
#include "generated/extensions/builtin.h" #include "generated/extensions/builtin.h"
#ifdef ICSNEO_ENABLE_RAW_ETHERNET #ifdef ICSNEO_ENABLE_RAW_ETHERNET
#include "icsneo/platform/pcap.h" #include "icsneo/platform/pcap.h"
#endif #endif
#ifdef ICSNEO_ENABLE_CDCACM #ifdef ICSNEO_ENABLE_CDCACM
#include "icsneo/platform/cdcacm.h" #include "icsneo/platform/cdcacm.h"
#endif #endif
#ifdef ICSNEO_ENABLE_FTDI #ifdef ICSNEO_ENABLE_FTDI
#include "icsneo/platform/ftdi.h" #include "icsneo/platform/ftdi.h"
#endif #endif
using namespace icsneo; using namespace icsneo;
template<typename T> template<typename T>
static void makeIfSerialMatches(const FoundDevice& dev, std::vector<std::shared_ptr<Device>>& into) { static void makeIfSerialMatches(const FoundDevice& dev, std::vector<std::shared_ptr<Device>>& into) {
// Relies on the subclass to have a `static constexpr const char* SERIAL_START = "XX"` // Relies on the subclass to have a `static constexpr const char* SERIAL_START = "XX"`
// and also a public constructor `T(const FoundDevice& dev)` // and also a public constructor `T(const FoundDevice& dev)`
// Use macro ICSNEO_FINDABLE_DEVICE() to create these // Use macro ICSNEO_FINDABLE_DEVICE() to create these
if(dev.serial[0] == T::SERIAL_START[0] && dev.serial[1] == T::SERIAL_START[1]) if(dev.serial[0] == T::SERIAL_START[0] && dev.serial[1] == T::SERIAL_START[1])
into.push_back(std::make_shared<T>(dev)); into.push_back(std::make_shared<T>(dev));
} }
template<typename T> template<typename T>
static void makeIfPIDMatches(const FoundDevice& dev, std::vector<std::shared_ptr<Device>>& into) { static void makeIfPIDMatches(const FoundDevice& dev, std::vector<std::shared_ptr<Device>>& into) {
// Relies on the subclass to have a `static constexpr uint16_t PRODUCT_ID = 0x1111` // Relies on the subclass to have a `static constexpr uint16_t PRODUCT_ID = 0x1111`
// and also a public constructor `T(const FoundDevice& dev)` // and also a public constructor `T(const FoundDevice& dev)`
// Use macro ICSNEO_FINDABLE_DEVICE_BY_PID() to create these // Use macro ICSNEO_FINDABLE_DEVICE_BY_PID() to create these
if(dev.productId == T::PRODUCT_ID) if(dev.productId == T::PRODUCT_ID)
into.push_back(std::make_shared<T>(dev)); into.push_back(std::make_shared<T>(dev));
} }
std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() { std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
static std::vector<FoundDevice> driverFoundDevices; static std::vector<FoundDevice> driverFoundDevices;
driverFoundDevices.clear(); driverFoundDevices.clear();
#ifdef ICSNEO_ENABLE_RAW_ETHERNET #ifdef ICSNEO_ENABLE_RAW_ETHERNET
PCAP::Find(driverFoundDevices); PCAP::Find(driverFoundDevices);
#endif #endif
#ifdef ICSNEO_ENABLE_CDCACM #ifdef ICSNEO_ENABLE_CDCACM
CDCACM::Find(driverFoundDevices); CDCACM::Find(driverFoundDevices);
#endif #endif
#ifdef ICSNEO_ENABLE_FTDI #ifdef ICSNEO_ENABLE_FTDI
FTDI::Find(driverFoundDevices); FTDI::Find(driverFoundDevices);
#endif #endif
std::vector<std::shared_ptr<Device>> foundDevices; std::vector<std::shared_ptr<Device>> foundDevices;
// Offer found devices to each of the subclasses // Offer found devices to each of the subclasses
for (const FoundDevice& dev : driverFoundDevices) { for (const FoundDevice& dev : driverFoundDevices) {
#ifdef __ETHERBADGE_H_ #ifdef __ETHERBADGE_H_
makeIfSerialMatches<EtherBADGE>(dev, foundDevices); makeIfSerialMatches<EtherBADGE>(dev, foundDevices);
#endif #endif
#ifdef __NEOOBD2PRO_H_ #ifdef __NEOOBD2PRO_H_
makeIfSerialMatches<NeoOBD2PRO>(dev, foundDevices); makeIfSerialMatches<NeoOBD2PRO>(dev, foundDevices);
#endif #endif
#ifdef __NEOOBD2SIM_H_ #ifdef __NEOOBD2SIM_H_
makeIfSerialMatches<NeoOBD2SIM>(dev, foundDevices); makeIfSerialMatches<NeoOBD2SIM>(dev, foundDevices);
#endif #endif
#ifdef __NEOVIFIRE_H_ #ifdef __NEOVIFIRE_H_
makeIfPIDMatches<NeoVIFIRE>(dev, foundDevices); makeIfPIDMatches<NeoVIFIRE>(dev, foundDevices);
#endif #endif
#ifdef __NEOVIFIRE2_H_ #ifdef __NEOVIFIRE2_H_
makeIfSerialMatches<NeoVIFIRE2>(dev, foundDevices); makeIfSerialMatches<NeoVIFIRE2>(dev, foundDevices);
#endif #endif
#ifdef __NEOVIRED2_H_ #ifdef __NEOVIRED2_H_
makeIfSerialMatches<NeoVIRED2>(dev, foundDevices); makeIfSerialMatches<NeoVIRED2>(dev, foundDevices);
#endif #endif
#ifdef __NEOVIION_H_ #ifdef __NEOVIION_H_
makeIfPIDMatches<NeoVIION>(dev, foundDevices); makeIfPIDMatches<NeoVIION>(dev, foundDevices);
#endif #endif
#ifdef __NEOVIPLASMA_H_ #ifdef __NEOVIPLASMA_H_
makeIfPIDMatches<NeoVIPLASMA>(dev, foundDevices); makeIfPIDMatches<NeoVIPLASMA>(dev, foundDevices);
#endif #endif
#ifdef __RADEPSILON_H_ #ifdef __RADEPSILON_H_
makeIfSerialMatches<RADEpsilon>(dev, foundDevices); makeIfSerialMatches<RADEpsilon>(dev, foundDevices);
#endif #endif
#ifdef __RADGALAXY_H_ #ifdef __RADGALAXY_H_
makeIfSerialMatches<RADGalaxy>(dev, foundDevices); makeIfSerialMatches<RADGalaxy>(dev, foundDevices);
#endif #endif
#ifdef __RADMARS_H_ #ifdef __RADMARS_H_
makeIfSerialMatches<RADMars>(dev, foundDevices); makeIfSerialMatches<RADMars>(dev, foundDevices);
#endif #endif
#ifdef __RADGIGASTAR_H_ #ifdef __RADGIGASTAR_H_
makeIfSerialMatches<RADGigastar>(dev, foundDevices); makeIfSerialMatches<RADGigastar>(dev, foundDevices);
#endif #endif
#ifdef __RADMOON2_H_ #ifdef __RADMOON2_H_
makeIfSerialMatches<RADMoon2>(dev, foundDevices); makeIfSerialMatches<RADMoon2>(dev, foundDevices);
#endif #endif
#ifdef __RADMOONDUO_H_ #ifdef __RADMOONDUO_H_
makeIfSerialMatches<RADMoonDuo>(dev, foundDevices); makeIfSerialMatches<RADMoonDuo>(dev, foundDevices);
#endif #endif
#ifdef __RADPLUTO_H_ #ifdef __RADPLUTO_H_
makeIfSerialMatches<RADPluto>(dev, foundDevices); makeIfSerialMatches<RADPluto>(dev, foundDevices);
#endif #endif
#ifdef __RADSTAR2_H_ #ifdef __RADSTAR2_H_
makeIfSerialMatches<RADStar2>(dev, foundDevices); makeIfSerialMatches<RADStar2>(dev, foundDevices);
#endif #endif
#ifdef __RADSUPERMOON_H_ #ifdef __RADSUPERMOON_H_
makeIfSerialMatches<RADSupermoon>(dev, foundDevices); makeIfSerialMatches<RADSupermoon>(dev, foundDevices);
#endif #endif
#ifdef __VALUECAN3_H_ #ifdef __VALUECAN3_H_
makeIfPIDMatches<ValueCAN3>(dev, foundDevices); makeIfPIDMatches<ValueCAN3>(dev, foundDevices);
#endif #endif
#ifdef __VALUECAN4_1_H_ #ifdef __VALUECAN4_1_H_
makeIfSerialMatches<ValueCAN4_1>(dev, foundDevices); makeIfSerialMatches<ValueCAN4_1>(dev, foundDevices);
#endif #endif
#ifdef __VALUECAN4_2_H_ #ifdef __VALUECAN4_2_H_
makeIfSerialMatches<ValueCAN4_2>(dev, foundDevices); makeIfSerialMatches<ValueCAN4_2>(dev, foundDevices);
#endif #endif
#ifdef __VALUECAN4_2EL_H_ #ifdef __VALUECAN4_2EL_H_
makeIfSerialMatches<ValueCAN4_2EL>(dev, foundDevices); makeIfSerialMatches<ValueCAN4_2EL>(dev, foundDevices);
#endif #endif
#ifdef __VALUECAN4_4_H_ #ifdef __VALUECAN4_4_H_
makeIfSerialMatches<ValueCAN4_4>(dev, foundDevices); makeIfSerialMatches<ValueCAN4_4>(dev, foundDevices);
#endif #endif
#ifdef __VALUECAN4INDUSTRIAL_H_ #ifdef __VALUECAN4INDUSTRIAL_H_
makeIfSerialMatches<ValueCAN4Industrial>(dev, foundDevices); makeIfSerialMatches<ValueCAN4Industrial>(dev, foundDevices);
#endif #endif
#ifdef __VIVIDCAN_H_ #ifdef __VIVIDCAN_H_
makeIfSerialMatches<VividCAN>(dev, foundDevices); makeIfSerialMatches<VividCAN>(dev, foundDevices);
#endif #endif
} }
for(auto& device : foundDevices) { for(auto& device : foundDevices) {
AddBuiltInExtensionsTo(device); AddBuiltInExtensionsTo(device);
} }
return foundDevices; return foundDevices;
} }
const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() { const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
static std::vector<DeviceType> supportedDevices = { static std::vector<DeviceType> supportedDevices = {
#ifdef __ETHERBADGE_H_ #ifdef __ETHERBADGE_H_
EtherBADGE::DEVICE_TYPE, EtherBADGE::DEVICE_TYPE,
#endif #endif
#ifdef __NEOOBD2PRO_H_ #ifdef __NEOOBD2PRO_H_
NeoOBD2PRO::DEVICE_TYPE, NeoOBD2PRO::DEVICE_TYPE,
#endif #endif
#ifdef __NEOOBD2SIM_H_ #ifdef __NEOOBD2SIM_H_
NeoOBD2SIM::DEVICE_TYPE, NeoOBD2SIM::DEVICE_TYPE,
#endif #endif
#ifdef __NEOVIRED2_H_ #ifdef __NEOVIRED2_H_
NeoVIRED2::DEVICE_TYPE, NeoVIRED2::DEVICE_TYPE,
#endif #endif
#ifdef __NEOVIFIRE_H_ #ifdef __NEOVIFIRE_H_
NeoVIFIRE::DEVICE_TYPE, NeoVIFIRE::DEVICE_TYPE,
#endif #endif
#ifdef __NEOVIFIRE2_H_ #ifdef __NEOVIFIRE2_H_
NeoVIFIRE2::DEVICE_TYPE, NeoVIFIRE2::DEVICE_TYPE,
#endif #endif
#ifdef __NEOVIION_H_ #ifdef __NEOVIION_H_
NeoVIION::DEVICE_TYPE, NeoVIION::DEVICE_TYPE,
#endif #endif
#ifdef __NEOVIPLASMA_H_ #ifdef __NEOVIPLASMA_H_
NeoVIPLASMA::DEVICE_TYPE, NeoVIPLASMA::DEVICE_TYPE,
#endif #endif
#ifdef __RADEPSILON_H_ #ifdef __RADEPSILON_H_
RADEpsilon::DEVICE_TYPE, RADEpsilon::DEVICE_TYPE,
#endif #endif
#ifdef __RADGALAXY_H_ #ifdef __RADGALAXY_H_
RADGalaxy::DEVICE_TYPE, RADGalaxy::DEVICE_TYPE,
#endif #endif
#ifdef __RADMARS_H_ #ifdef __RADMARS_H_
RADMars::DEVICE_TYPE, RADMars::DEVICE_TYPE,
#endif #endif
#ifdef __RADGIGASTAR_H_ #ifdef __RADGIGASTAR_H_
RADGigastar::DEVICE_TYPE, RADGigastar::DEVICE_TYPE,
#endif #endif
#ifdef __RADMOON2_H_ #ifdef __RADMOON2_H_
RADMoon2::DEVICE_TYPE, RADMoon2::DEVICE_TYPE,
#endif #endif
#ifdef __RADMOONDUO_H_ #ifdef __RADMOONDUO_H_
RADMoonDuo::DEVICE_TYPE, RADMoonDuo::DEVICE_TYPE,
#endif #endif
#ifdef __RADPLUTO_H_ #ifdef __RADPLUTO_H_
RADPluto::DEVICE_TYPE, RADPluto::DEVICE_TYPE,
#endif #endif
#ifdef __RADSTAR2_H_ #ifdef __RADSTAR2_H_
RADStar2::DEVICE_TYPE, RADStar2::DEVICE_TYPE,
#endif #endif
#ifdef __RADSUPERMOON_H_ #ifdef __RADSUPERMOON_H_
RADSupermoon::DEVICE_TYPE, RADSupermoon::DEVICE_TYPE,
#endif #endif
#ifdef __VALUECAN3_H_ #ifdef __VALUECAN3_H_
ValueCAN3::DEVICE_TYPE, ValueCAN3::DEVICE_TYPE,
#endif #endif
#ifdef __VALUECAN4_1_H_ #ifdef __VALUECAN4_1_H_
ValueCAN4_1::DEVICE_TYPE, ValueCAN4_1::DEVICE_TYPE,
#endif #endif
#ifdef __VALUECAN4_2_H_ #ifdef __VALUECAN4_2_H_
ValueCAN4_2::DEVICE_TYPE, ValueCAN4_2::DEVICE_TYPE,
#endif #endif
#ifdef __VALUECAN4_2EL_H_ #ifdef __VALUECAN4_2EL_H_
ValueCAN4_2EL::DEVICE_TYPE, ValueCAN4_2EL::DEVICE_TYPE,
#endif #endif
#ifdef __VALUECAN4_4_H_ #ifdef __VALUECAN4_4_H_
ValueCAN4_4::DEVICE_TYPE, ValueCAN4_4::DEVICE_TYPE,
#endif #endif
#ifdef __VALUECAN4INDUSTRIAL_H_ #ifdef __VALUECAN4INDUSTRIAL_H_
ValueCAN4Industrial::DEVICE_TYPE, ValueCAN4Industrial::DEVICE_TYPE,
#endif #endif
#ifdef __VIVIDCAN_H_ #ifdef __VIVIDCAN_H_
VividCAN::DEVICE_TYPE, VividCAN::DEVICE_TYPE,
#endif #endif
}; };
return supportedDevices; return supportedDevices;
} }

View File

@ -1,61 +1,61 @@
#ifndef __DRIVER_H_ #ifndef __DRIVER_H_
#define __DRIVER_H_ #define __DRIVER_H_
#ifdef __cplusplus #ifdef __cplusplus
#include <vector> #include <vector>
#include <chrono> #include <chrono>
#include <atomic> #include <atomic>
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <condition_variable> #include <condition_variable>
#include "icsneo/api/eventmanager.h" #include "icsneo/api/eventmanager.h"
#include "icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h" #include "icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h"
namespace icsneo { namespace icsneo {
class Driver { class Driver {
public: public:
Driver(const device_eventhandler_t& handler) : report(handler) {} Driver(const device_eventhandler_t& handler) : report(handler) {}
virtual ~Driver() {} virtual ~Driver() {}
virtual bool open() = 0; virtual bool open() = 0;
virtual bool isOpen() = 0; virtual bool isOpen() = 0;
virtual void modeChangeIncoming() {} virtual void modeChangeIncoming() {}
virtual void awaitModeChangeComplete() {} virtual void awaitModeChangeComplete() {}
virtual bool isDisconnected() { return disconnected; }; virtual bool isDisconnected() { return disconnected; };
virtual bool close() = 0; virtual bool close() = 0;
virtual bool read(std::vector<uint8_t>& bytes, size_t limit = 0); virtual bool read(std::vector<uint8_t>& bytes, size_t limit = 0);
virtual bool readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds(100), size_t limit = 0); virtual bool readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds(100), size_t limit = 0);
virtual bool write(const std::vector<uint8_t>& bytes); virtual bool write(const std::vector<uint8_t>& bytes);
virtual bool isEthernet() const { return false; } virtual bool isEthernet() const { return false; }
device_eventhandler_t report; device_eventhandler_t report;
size_t writeQueueSize = 50; size_t writeQueueSize = 50;
bool writeBlocks = true; // Otherwise it just fails when the queue is full bool writeBlocks = true; // Otherwise it just fails when the queue is full
protected: protected:
class WriteOperation { class WriteOperation {
public: public:
WriteOperation() {} WriteOperation() {}
WriteOperation(const std::vector<uint8_t>& b) : bytes(b) {} WriteOperation(const std::vector<uint8_t>& b) : bytes(b) {}
std::vector<uint8_t> bytes; std::vector<uint8_t> bytes;
}; };
enum IOTaskState { enum IOTaskState {
LAUNCH, LAUNCH,
WAIT WAIT
}; };
virtual void readTask() = 0; virtual void readTask() = 0;
virtual void writeTask() = 0; virtual void writeTask() = 0;
moodycamel::BlockingConcurrentQueue<uint8_t> readQueue; moodycamel::BlockingConcurrentQueue<uint8_t> readQueue;
moodycamel::BlockingConcurrentQueue<WriteOperation> writeQueue; moodycamel::BlockingConcurrentQueue<WriteOperation> writeQueue;
std::thread readThread, writeThread; std::thread readThread, writeThread;
std::atomic<bool> closing{false}; std::atomic<bool> closing{false};
std::atomic<bool> disconnected{false}; std::atomic<bool> disconnected{false};
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,50 +1,50 @@
#ifndef __MESSAGECALLBACK_H_ #ifndef __MESSAGECALLBACK_H_
#define __MESSAGECALLBACK_H_ #define __MESSAGECALLBACK_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/communication/message/message.h" #include "icsneo/communication/message/message.h"
#include "icsneo/communication/message/filter/messagefilter.h" #include "icsneo/communication/message/filter/messagefilter.h"
#include <memory> #include <memory>
#include <functional> #include <functional>
namespace icsneo { namespace icsneo {
class MessageCallback { class MessageCallback {
public: public:
typedef std::function< void( std::shared_ptr<Message> ) > fn_messageCallback; typedef std::function< void( std::shared_ptr<Message> ) > fn_messageCallback;
MessageCallback(fn_messageCallback cb, std::shared_ptr<MessageFilter> f) MessageCallback(fn_messageCallback cb, std::shared_ptr<MessageFilter> f)
: callback(cb), filter(f ? f : std::make_shared<MessageFilter>()) { : callback(cb), filter(f ? f : std::make_shared<MessageFilter>()) {
if(!cb) if(!cb)
throw std::bad_function_call(); throw std::bad_function_call();
} }
MessageCallback(fn_messageCallback cb, MessageFilter f = MessageFilter()) MessageCallback(fn_messageCallback cb, MessageFilter f = MessageFilter())
: MessageCallback(cb, std::make_shared<MessageFilter>(f)) {} : MessageCallback(cb, std::make_shared<MessageFilter>(f)) {}
// Allow the filter to be placed first if the user wants (maybe in the case of a lambda) // Allow the filter to be placed first if the user wants (maybe in the case of a lambda)
MessageCallback(std::shared_ptr<MessageFilter> f, fn_messageCallback cb) MessageCallback(std::shared_ptr<MessageFilter> f, fn_messageCallback cb)
: MessageCallback(cb, f) {} : MessageCallback(cb, f) {}
MessageCallback(MessageFilter f, fn_messageCallback cb) MessageCallback(MessageFilter f, fn_messageCallback cb)
: MessageCallback(cb, std::make_shared<MessageFilter>(f)) {} : MessageCallback(cb, std::make_shared<MessageFilter>(f)) {}
virtual bool callIfMatch(const std::shared_ptr<Message>& message) const { virtual bool callIfMatch(const std::shared_ptr<Message>& message) const {
bool ret = filter->match(message); bool ret = filter->match(message);
if(ret) if(ret)
callback(message); callback(message);
return ret; return ret;
} }
const MessageFilter& getFilter() const { return *filter; } const MessageFilter& getFilter() const { return *filter; }
const fn_messageCallback& getCallback() const { return callback; } const fn_messageCallback& getCallback() const { return callback; }
protected: protected:
const fn_messageCallback callback; const fn_messageCallback callback;
const std::shared_ptr<MessageFilter> filter; const std::shared_ptr<MessageFilter> filter;
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,25 +1,25 @@
#ifndef __CANMESSAGE_H_ #ifndef __CANMESSAGE_H_
#define __CANMESSAGE_H_ #define __CANMESSAGE_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/communication/message/message.h" #include "icsneo/communication/message/message.h"
namespace icsneo { namespace icsneo {
class CANMessage : public Frame { class CANMessage : public Frame {
public: public:
uint32_t arbid; uint32_t arbid;
uint8_t dlcOnWire; uint8_t dlcOnWire;
bool isRemote = false; // Not allowed if CAN FD bool isRemote = false; // Not allowed if CAN FD
bool isExtended = false; bool isExtended = false;
bool isCANFD = false; bool isCANFD = false;
bool baudrateSwitch = false; // CAN FD only bool baudrateSwitch = false; // CAN FD only
bool errorStateIndicator = false; // CAN FD only bool errorStateIndicator = false; // CAN FD only
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,68 +1,68 @@
#ifndef __MESSAGEFILTER_H_ #ifndef __MESSAGEFILTER_H_
#define __MESSAGEFILTER_H_ #define __MESSAGEFILTER_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/communication/network.h" #include "icsneo/communication/network.h"
#include "icsneo/communication/message/message.h" #include "icsneo/communication/message/message.h"
#include <memory> #include <memory>
namespace icsneo { namespace icsneo {
class MessageFilter { class MessageFilter {
public: public:
MessageFilter() {} MessageFilter() {}
MessageFilter(Message::Type type) : includeInternalInAny(neomessagetype_t(type) & 0x8000), messageType(type) {} MessageFilter(Message::Type type) : includeInternalInAny(neomessagetype_t(type) & 0x8000), messageType(type) {}
MessageFilter(Network::NetID netid) : MessageFilter(Network::GetTypeOfNetID(netid), netid) {} MessageFilter(Network::NetID netid) : MessageFilter(Network::GetTypeOfNetID(netid), netid) {}
MessageFilter(Network::Type type, Network::NetID net = Network::NetID::Any) : networkType(type), netid(net) { MessageFilter(Network::Type type, Network::NetID net = Network::NetID::Any) : networkType(type), netid(net) {
// If a Network::Type::Internal is used, we want to also get internal Message::Types // If a Network::Type::Internal is used, we want to also get internal Message::Types
// The NetID we want may be in there // The NetID we want may be in there
includeInternalInAny = (networkType == Network::Type::Internal); includeInternalInAny = (networkType == Network::Type::Internal);
} }
virtual ~MessageFilter() = default; virtual ~MessageFilter() = default;
// When getting "all" types of messages, include the ones marked as "internal only" // When getting "all" types of messages, include the ones marked as "internal only"
bool includeInternalInAny = false; bool includeInternalInAny = false;
virtual bool match(const std::shared_ptr<Message>& message) const { virtual bool match(const std::shared_ptr<Message>& message) const {
if(!matchMessageType(message->type)) if(!matchMessageType(message->type))
return false; return false;
if(message->type == Message::Type::Frame || message->type == Message::Type::Main51 || if(message->type == Message::Type::Frame || message->type == Message::Type::Main51 ||
message->type == Message::Type::RawMessage || message->type == Message::Type::ReadSettings) { message->type == Message::Type::RawMessage || message->type == Message::Type::ReadSettings) {
RawMessage& frame = *static_cast<RawMessage*>(message.get()); RawMessage& frame = *static_cast<RawMessage*>(message.get());
if(!matchNetworkType(frame.network.getType())) if(!matchNetworkType(frame.network.getType()))
return false; return false;
if(!matchNetID(frame.network.getNetID())) if(!matchNetID(frame.network.getNetID()))
return false; return false;
} }
return true; return true;
} }
protected: protected:
Message::Type messageType = Message::Type::Invalid; // Used here for "any" Message::Type messageType = Message::Type::Invalid; // Used here for "any"
bool matchMessageType(Message::Type mtype) const { bool matchMessageType(Message::Type mtype) const {
if(messageType == Message::Type::Invalid && ((neomessagetype_t(mtype) & 0x8000) == 0 || includeInternalInAny)) if(messageType == Message::Type::Invalid && ((neomessagetype_t(mtype) & 0x8000) == 0 || includeInternalInAny))
return true; return true;
return messageType == mtype; return messageType == mtype;
} }
Network::Type networkType = Network::Type::Any; Network::Type networkType = Network::Type::Any;
bool matchNetworkType(Network::Type mtype) const { bool matchNetworkType(Network::Type mtype) const {
if(networkType == Network::Type::Any && (mtype != Network::Type::Internal || includeInternalInAny)) if(networkType == Network::Type::Any && (mtype != Network::Type::Internal || includeInternalInAny))
return true; return true;
return networkType == mtype; return networkType == mtype;
} }
Network::NetID netid = Network::NetID::Any; Network::NetID netid = Network::NetID::Any;
bool matchNetID(Network::NetID mnetid) const { bool matchNetID(Network::NetID mnetid) const {
if(netid == Network::NetID::Any) if(netid == Network::NetID::Any)
return true; return true;
return netid == mnetid; return netid == mnetid;
} }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,30 +1,30 @@
#ifndef __ISO9141MESSAGE_H_ #ifndef __ISO9141MESSAGE_H_
#define __ISO9141MESSAGE_H_ #define __ISO9141MESSAGE_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/communication/message/message.h" #include "icsneo/communication/message/message.h"
#include <array> #include <array>
namespace icsneo { namespace icsneo {
class ISO9141Message : public Frame { class ISO9141Message : public Frame {
public: public:
std::array<uint8_t, 3> header; std::array<uint8_t, 3> header;
bool isInit = false; bool isInit = false;
bool isBreak = false; bool isBreak = false;
bool framingError = false; bool framingError = false;
bool overflowError = false; bool overflowError = false;
bool parityError = false; bool parityError = false;
bool rxTimeoutError = false; bool rxTimeoutError = false;
// Checksum not yet implemted, it's just at the end of the data if enabled for now // Checksum not yet implemted, it's just at the end of the data if enabled for now
// bool checksumError = false; // bool checksumError = false;
// bool hasChecksum = false; // bool hasChecksum = false;
// uint8_t checksum = 0; // uint8_t checksum = 0;
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,77 +1,77 @@
#ifndef __MESSAGE_H_ #ifndef __MESSAGE_H_
#define __MESSAGE_H_ #define __MESSAGE_H_
#include <stdint.h> #include <stdint.h>
typedef uint16_t neomessagetype_t; typedef uint16_t neomessagetype_t;
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/communication/network.h" #include "icsneo/communication/network.h"
#include <vector> #include <vector>
namespace icsneo { namespace icsneo {
class Message { class Message {
public: public:
enum class Type : neomessagetype_t { enum class Type : neomessagetype_t {
Frame = 0, Frame = 0,
CANErrorCount = 0x100, CANErrorCount = 0x100,
// Past 0x8000 are all for internal use only // Past 0x8000 are all for internal use only
Invalid = 0x8000, Invalid = 0x8000,
RawMessage = 0x8001, RawMessage = 0x8001,
ReadSettings = 0x8002, ReadSettings = 0x8002,
ResetStatus = 0x8003, ResetStatus = 0x8003,
DeviceVersion = 0x8004, DeviceVersion = 0x8004,
Main51 = 0x8005, Main51 = 0x8005,
FlexRayControl = 0x8006, FlexRayControl = 0x8006,
EthernetPhyRegister = 0x8007, EthernetPhyRegister = 0x8007,
LogicalDiskInfo = 0x8008, LogicalDiskInfo = 0x8008,
}; };
Message(Type t) : type(t) {} Message(Type t) : type(t) {}
virtual ~Message() = default; virtual ~Message() = default;
const Type type; const Type type;
uint64_t timestamp = 0; uint64_t timestamp = 0;
}; };
class RawMessage : public Message { class RawMessage : public Message {
public: public:
RawMessage(Message::Type type = Message::Type::RawMessage) : Message(type) {} RawMessage(Message::Type type = Message::Type::RawMessage) : Message(type) {}
RawMessage(Message::Type type, Network net) : Message(type), network(net) {} RawMessage(Message::Type type, Network net) : Message(type), network(net) {}
RawMessage(Network net) : Message(Message::Type::RawMessage), network(net) {} RawMessage(Network net) : Message(Message::Type::RawMessage), network(net) {}
RawMessage(Network net, std::vector<uint8_t> d) : Message(Message::Type::RawMessage), network(net), data(d) {} RawMessage(Network net, std::vector<uint8_t> d) : Message(Message::Type::RawMessage), network(net), data(d) {}
Network network; Network network;
std::vector<uint8_t> data; std::vector<uint8_t> data;
}; };
class Frame : public RawMessage { class Frame : public RawMessage {
public: public:
Frame() : RawMessage(Message::Type::Frame) {} Frame() : RawMessage(Message::Type::Frame) {}
uint16_t description = 0; uint16_t description = 0;
bool transmitted = false; bool transmitted = false;
bool error = false; bool error = false;
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#ifdef __ICSNEOC_H_ #ifdef __ICSNEOC_H_
#define ICSNEO_MESSAGE_TYPE_FRAME (0x0) #define ICSNEO_MESSAGE_TYPE_FRAME (0x0)
#define ICSNEO_MESSAGE_TYPE_CAN_ERROR_COUNT (0x100) #define ICSNEO_MESSAGE_TYPE_CAN_ERROR_COUNT (0x100)
#define ICSNEO_MESSAGE_TYPE_INVALID (0x8000) #define ICSNEO_MESSAGE_TYPE_INVALID (0x8000)
#define ICSNEO_MESSAGE_TYPE_RAW_MESSAGE (0x8001) #define ICSNEO_MESSAGE_TYPE_RAW_MESSAGE (0x8001)
#define ICSNEO_MESSAGE_TYPE_READ_SETTINGS (0x8002) #define ICSNEO_MESSAGE_TYPE_READ_SETTINGS (0x8002)
#define ICSNEO_MESSAGE_TYPE_RESET_STATUS (0x8003) #define ICSNEO_MESSAGE_TYPE_RESET_STATUS (0x8003)
#define ICSNEO_MESSAGE_TYPE_DEVICE_VERSION (0x8004) #define ICSNEO_MESSAGE_TYPE_DEVICE_VERSION (0x8004)
#define ICSNEO_MESSAGE_TYPE_MAIN51 (0x8005) #define ICSNEO_MESSAGE_TYPE_MAIN51 (0x8005)
#define ICSNEO_MESSAGE_TYPE_FLEXRAY_CONTROL (0x8006) #define ICSNEO_MESSAGE_TYPE_FLEXRAY_CONTROL (0x8006)
#endif // __ICSNEOC_H_ #endif // __ICSNEOC_H_
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -1,23 +1,23 @@
#ifndef __DEVICEFINDER_H_ #ifndef __DEVICEFINDER_H_
#define __DEVICEFINDER_H_ #define __DEVICEFINDER_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include <vector> #include <vector>
#include <memory> #include <memory>
namespace icsneo { namespace icsneo {
class DeviceFinder { class DeviceFinder {
public: public:
static std::vector<std::shared_ptr<Device>> FindAll(); static std::vector<std::shared_ptr<Device>> FindAll();
static const std::vector<DeviceType>& GetSupportedDevices(); static const std::vector<DeviceType>& GetSupportedDevices();
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,90 +1,90 @@
#ifndef __RADMOON2_H_ #ifndef __RADMOON2_H_
#define __RADMOON2_H_ #define __RADMOON2_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/radmoon2/radmoon2settings.h" #include "icsneo/device/tree/radmoon2/radmoon2settings.h"
namespace icsneo { namespace icsneo {
class RADMoon2 : public Device { class RADMoon2 : public Device {
public: public:
// Serial numbers start with RM // Serial numbers start with RM
// USB PID is 0x1202, standard driver is FTDI3 // USB PID is 0x1202, standard driver is FTDI3
ICSNEO_FINDABLE_DEVICE(RADMoon2, DeviceType::RADMoon2, "RM"); ICSNEO_FINDABLE_DEVICE(RADMoon2, DeviceType::RADMoon2, "RM");
enum class SKU { enum class SKU {
Standard, Standard,
APM1000E, // Keysight Branding APM1000E, // Keysight Branding
APM1000E_CLK, // Clock Option and Keysight Branding APM1000E_CLK, // Clock Option and Keysight Branding
}; };
SKU getSKU() const { SKU getSKU() const {
switch(getSerial().back()) { switch(getSerial().back()) {
case 'A': case 'A':
case 'B': case 'B':
return SKU::APM1000E; return SKU::APM1000E;
case 'C': case 'C':
case 'D': case 'D':
return SKU::APM1000E_CLK; return SKU::APM1000E_CLK;
default: default:
return SKU::Standard; return SKU::Standard;
} }
} }
std::string getProductName() const override { std::string getProductName() const override {
switch(getSKU()) { switch(getSKU()) {
case SKU::Standard: break; case SKU::Standard: break;
case SKU::APM1000E: case SKU::APM1000E:
return "Keysight APM1000E"; return "Keysight APM1000E";
case SKU::APM1000E_CLK: case SKU::APM1000E_CLK:
return "Keysight APM1000E-CLK"; return "Keysight APM1000E-CLK";
} }
return Device::getProductName(); return Device::getProductName();
} }
// RADMoon 2 does not go online, you can only set settings and // RADMoon 2 does not go online, you can only set settings and
// view PHY information (when supported) // view PHY information (when supported)
bool goOnline() override { bool goOnline() override {
report(APIEvent::Type::OnlineNotSupported, APIEvent::Severity::Error); report(APIEvent::Type::OnlineNotSupported, APIEvent::Severity::Error);
return false; return false;
} }
bool goOffline() override { bool goOffline() override {
report(APIEvent::Type::OnlineNotSupported, APIEvent::Severity::Error); report(APIEvent::Type::OnlineNotSupported, APIEvent::Severity::Error);
return false; return false;
} }
bool getEthPhyRegControlSupported() const override { return true; } bool getEthPhyRegControlSupported() const override { return true; }
protected: protected:
RADMoon2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { RADMoon2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADMoon2Settings>(makeDriver); initialize<RADMoon2Settings>(makeDriver);
} }
void setupPacketizer(Packetizer& packetizer) override { void setupPacketizer(Packetizer& packetizer) override {
Device::setupPacketizer(packetizer); Device::setupPacketizer(packetizer);
packetizer.disableChecksum = true; packetizer.disableChecksum = true;
packetizer.align16bit = false; packetizer.align16bit = false;
} }
virtual void setupEncoder(Encoder& encoder) override { virtual void setupEncoder(Encoder& encoder) override {
Device::setupEncoder(encoder); Device::setupEncoder(encoder);
encoder.supportEthPhy = true; encoder.supportEthPhy = true;
} }
void setupDecoder(Decoder& decoder) override { void setupDecoder(Decoder& decoder) override {
Device::setupDecoder(decoder); Device::setupDecoder(decoder);
decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns
} }
bool requiresVehiclePower() const override { return false; } bool requiresVehiclePower() const override { return false; }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,54 +1,54 @@
#ifndef __RADMOONDUO_H_ #ifndef __RADMOONDUO_H_
#define __RADMOONDUO_H_ #define __RADMOONDUO_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/radmoonduo/radmoonduosettings.h" #include "icsneo/device/tree/radmoonduo/radmoonduosettings.h"
namespace icsneo { namespace icsneo {
class RADMoonDuo : public Device { class RADMoonDuo : public Device {
public: public:
// Serial numbers start with MD // Serial numbers start with MD
// USB PID is 1106, standard driver is CDCACM // USB PID is 1106, standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(RADMoonDuo, DeviceType::RADMoonDuo, "MD"); ICSNEO_FINDABLE_DEVICE(RADMoonDuo, DeviceType::RADMoonDuo, "MD");
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
// If Converter1 Target is set to USB/CM, OP_Ethernet2 will be exposed to the PC // If Converter1 Target is set to USB/CM, OP_Ethernet2 will be exposed to the PC
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
Network::NetID::OP_Ethernet2 Network::NetID::OP_Ethernet2
}; };
return supportedNetworks; return supportedNetworks;
} }
bool getEthPhyRegControlSupported() const override { return true; } bool getEthPhyRegControlSupported() const override { return true; }
protected: protected:
RADMoonDuo(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { RADMoonDuo(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADMoonDuoSettings>(makeDriver); initialize<RADMoonDuoSettings>(makeDriver);
} }
virtual void setupEncoder(Encoder& encoder) override { virtual void setupEncoder(Encoder& encoder) override {
Device::setupEncoder(encoder); Device::setupEncoder(encoder);
encoder.supportEthPhy = true; encoder.supportEthPhy = true;
} }
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); } void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
bool requiresVehiclePower() const override { return false; } bool requiresVehiclePower() const override { return false; }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,88 +1,88 @@
#ifndef __RADSUPERMOON_H_ #ifndef __RADSUPERMOON_H_
#define __RADSUPERMOON_H_ #define __RADSUPERMOON_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/radsupermoon/radsupermoonsettings.h" #include "icsneo/device/tree/radsupermoon/radsupermoonsettings.h"
namespace icsneo { namespace icsneo {
class RADSupermoon : public Device { class RADSupermoon : public Device {
public: public:
// Serial numbers start with SM // Serial numbers start with SM
// USB PID is 0x1201, standard driver is FTDI3 // USB PID is 0x1201, standard driver is FTDI3
ICSNEO_FINDABLE_DEVICE(RADSupermoon, DeviceType::RADSupermoon, "SM"); ICSNEO_FINDABLE_DEVICE(RADSupermoon, DeviceType::RADSupermoon, "SM");
enum class SKU { enum class SKU {
Standard, Standard,
APM1000ET, // Keysight Branding APM1000ET, // Keysight Branding
}; };
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
Network::NetID::Ethernet, Network::NetID::Ethernet,
Network::NetID::OP_Ethernet1, Network::NetID::OP_Ethernet1,
Network::NetID::OP_Ethernet2 Network::NetID::OP_Ethernet2
}; };
return supportedNetworks; return supportedNetworks;
} }
SKU getSKU() const { SKU getSKU() const {
switch(getSerial().back()) { switch(getSerial().back()) {
case 'A': case 'A':
return SKU::APM1000ET; return SKU::APM1000ET;
default: default:
return SKU::Standard; return SKU::Standard;
} }
} }
std::string getProductName() const override { std::string getProductName() const override {
switch(getSKU()) { switch(getSKU()) {
case SKU::Standard: break; case SKU::Standard: break;
case SKU::APM1000ET: case SKU::APM1000ET:
return "Keysight APM1000ET"; return "Keysight APM1000ET";
} }
return Device::getProductName(); return Device::getProductName();
} }
bool getEthPhyRegControlSupported() const override { return true; } bool getEthPhyRegControlSupported() const override { return true; }
protected: protected:
RADSupermoon(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { RADSupermoon(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADSupermoonSettings>(makeDriver); initialize<RADSupermoonSettings>(makeDriver);
} }
void setupPacketizer(Packetizer& packetizer) override { void setupPacketizer(Packetizer& packetizer) override {
Device::setupPacketizer(packetizer); Device::setupPacketizer(packetizer);
packetizer.disableChecksum = true; packetizer.disableChecksum = true;
packetizer.align16bit = false; packetizer.align16bit = false;
} }
virtual void setupEncoder(Encoder& encoder) override { virtual void setupEncoder(Encoder& encoder) override {
Device::setupEncoder(encoder); Device::setupEncoder(encoder);
encoder.supportEthPhy = true; encoder.supportEthPhy = true;
} }
void setupDecoder(Decoder& decoder) override { void setupDecoder(Decoder& decoder) override {
Device::setupDecoder(decoder); Device::setupDecoder(decoder);
decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns
} }
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); } void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
bool requiresVehiclePower() const override { return false; } bool requiresVehiclePower() const override { return false; }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,46 +1,46 @@
#ifndef __VALUECAN3_H_ #ifndef __VALUECAN3_H_
#define __VALUECAN3_H_ #define __VALUECAN3_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h" #include "icsneo/platform/ftdi.h"
#include "icsneo/device/tree/valuecan3/valuecan3settings.h" #include "icsneo/device/tree/valuecan3/valuecan3settings.h"
namespace icsneo { namespace icsneo {
class ValueCAN3 : public Device { class ValueCAN3 : public Device {
public: public:
// USB PID is 0x0601, standard driver is FTDI // USB PID is 0x0601, standard driver is FTDI
ICSNEO_FINDABLE_DEVICE_BY_PID(ValueCAN3, DeviceType::VCAN3, 0x0701); ICSNEO_FINDABLE_DEVICE_BY_PID(ValueCAN3, DeviceType::VCAN3, 0x0701);
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN, Network::NetID::HSCAN,
Network::NetID::MSCAN Network::NetID::MSCAN
}; };
return supportedNetworks; return supportedNetworks;
} }
private: private:
ValueCAN3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { ValueCAN3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<ValueCAN3Settings>(makeDriver); initialize<ValueCAN3Settings>(makeDriver);
} }
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); } void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
bool requiresVehiclePower() const override { return false; } bool requiresVehiclePower() const override { return false; }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,47 +1,47 @@
#ifndef __VALUECAN4_1_H_ #ifndef __VALUECAN4_1_H_
#define __VALUECAN4_1_H_ #define __VALUECAN4_1_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/tree/valuecan4/valuecan4.h" #include "icsneo/device/tree/valuecan4/valuecan4.h"
#include "icsneo/device/tree/valuecan4/settings/valuecan4-1settings.h" #include "icsneo/device/tree/valuecan4/settings/valuecan4-1settings.h"
namespace icsneo { namespace icsneo {
class ValueCAN4_1 : public ValueCAN4 { class ValueCAN4_1 : public ValueCAN4 {
public: public:
// Serial numbers start with V1 for 4-1 // Serial numbers start with V1 for 4-1
// USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM // USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(ValueCAN4_1, DeviceType::VCAN4_1, "V1"); ICSNEO_FINDABLE_DEVICE(ValueCAN4_1, DeviceType::VCAN4_1, "V1");
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN Network::NetID::HSCAN
}; };
return supportedNetworks; return supportedNetworks;
} }
protected: protected:
ValueCAN4_1(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) { ValueCAN4_1(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
initialize<ValueCAN4_1Settings>(makeDriver); initialize<ValueCAN4_1Settings>(makeDriver);
} }
void setupEncoder(Encoder& encoder) override { void setupEncoder(Encoder& encoder) override {
ValueCAN4::setupEncoder(encoder); ValueCAN4::setupEncoder(encoder);
encoder.supportCANFD = false; // VCAN 4-1 does not support CAN FD encoder.supportCANFD = false; // VCAN 4-1 does not support CAN FD
} }
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); } void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,67 +1,67 @@
#ifndef __VALUECAN4_2_H_ #ifndef __VALUECAN4_2_H_
#define __VALUECAN4_2_H_ #define __VALUECAN4_2_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/tree/valuecan4/valuecan4.h" #include "icsneo/device/tree/valuecan4/valuecan4.h"
#include "icsneo/device/tree/valuecan4/settings/valuecan4-2settings.h" #include "icsneo/device/tree/valuecan4/settings/valuecan4-2settings.h"
namespace icsneo { namespace icsneo {
class ValueCAN4_2 : public ValueCAN4 { class ValueCAN4_2 : public ValueCAN4 {
public: public:
// Serial numbers start with V2 for 4-2 // Serial numbers start with V2 for 4-2
// USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM // USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(ValueCAN4_2, DeviceType::VCAN4_2, "V2"); ICSNEO_FINDABLE_DEVICE(ValueCAN4_2, DeviceType::VCAN4_2, "V2");
enum class SKU { enum class SKU {
Standard, Standard,
AP0200A, // USB A and Keysight Branding AP0200A, // USB A and Keysight Branding
}; };
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN, Network::NetID::HSCAN,
Network::NetID::HSCAN2 Network::NetID::HSCAN2
}; };
return supportedNetworks; return supportedNetworks;
} }
SKU getSKU() const { SKU getSKU() const {
switch(getSerial().back()) { switch(getSerial().back()) {
case 'A': case 'A':
case 'B': case 'B':
return SKU::AP0200A; return SKU::AP0200A;
default: default:
return SKU::Standard; return SKU::Standard;
} }
} }
std::string getProductName() const override { std::string getProductName() const override {
switch(getSKU()) { switch(getSKU()) {
case SKU::Standard: break; case SKU::Standard: break;
case SKU::AP0200A: case SKU::AP0200A:
return "Keysight AP0200A"; return "Keysight AP0200A";
} }
return Device::getProductName(); return Device::getProductName();
} }
protected: protected:
ValueCAN4_2(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) { ValueCAN4_2(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
initialize<ValueCAN4_2Settings>(makeDriver); initialize<ValueCAN4_2Settings>(makeDriver);
} }
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); } void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,98 +1,98 @@
#ifndef __VALUECAN4_2EL_H_ #ifndef __VALUECAN4_2EL_H_
#define __VALUECAN4_2EL_H_ #define __VALUECAN4_2EL_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/tree/valuecan4/valuecan4.h" #include "icsneo/device/tree/valuecan4/valuecan4.h"
#include "icsneo/device/tree/valuecan4/settings/valuecan4-2elsettings.h" #include "icsneo/device/tree/valuecan4/settings/valuecan4-2elsettings.h"
namespace icsneo { namespace icsneo {
class ValueCAN4_2EL : public ValueCAN4 { class ValueCAN4_2EL : public ValueCAN4 {
public: public:
// Serial numbers start with VE for 4-2EL // Serial numbers start with VE for 4-2EL
// USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM // USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
// Ethernet MAC allocation is 0x0B, standard driver is Raw // Ethernet MAC allocation is 0x0B, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(ValueCAN4_2EL, DeviceType::VCAN4_2EL, "VE"); ICSNEO_FINDABLE_DEVICE(ValueCAN4_2EL, DeviceType::VCAN4_2EL, "VE");
enum class SKU { enum class SKU {
Standard, Standard,
AP04E0A_D26, // HDB26, USB A, and Keysight Branding AP04E0A_D26, // HDB26, USB A, and Keysight Branding
AP04E0A_MUL, // Multi-connectors, USB A, and Keysight Branding AP04E0A_MUL, // Multi-connectors, USB A, and Keysight Branding
AP04E0A_OBD, // OBD, USB A, and Keysight Branding AP04E0A_OBD, // OBD, USB A, and Keysight Branding
}; };
SKU getSKU() const { SKU getSKU() const {
switch(getSerial().back()) { switch(getSerial().back()) {
case 'A': case 'A':
return SKU::AP04E0A_D26; return SKU::AP04E0A_D26;
case 'B': case 'B':
return SKU::AP04E0A_MUL; return SKU::AP04E0A_MUL;
case 'C': case 'C':
return SKU::AP04E0A_OBD; return SKU::AP04E0A_OBD;
default: default:
return SKU::Standard; return SKU::Standard;
} }
} }
std::string getProductName() const override { std::string getProductName() const override {
switch(getSKU()) { switch(getSKU()) {
case SKU::Standard: break; case SKU::Standard: break;
case SKU::AP04E0A_D26: case SKU::AP04E0A_D26:
return "Keysight AP04E0A-D26"; return "Keysight AP04E0A-D26";
case SKU::AP04E0A_MUL: case SKU::AP04E0A_MUL:
return "Keysight AP04E0A-MUL"; return "Keysight AP04E0A-MUL";
case SKU::AP04E0A_OBD: case SKU::AP04E0A_OBD:
return "Keysight AP04E0A-OBD"; return "Keysight AP04E0A-OBD";
} }
return Device::getProductName(); return Device::getProductName();
} }
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN, Network::NetID::HSCAN,
Network::NetID::HSCAN2, Network::NetID::HSCAN2,
Network::NetID::Ethernet, Network::NetID::Ethernet,
Network::NetID::LIN Network::NetID::LIN
}; };
return supportedNetworks; return supportedNetworks;
} }
protected: protected:
ValueCAN4_2EL(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) { ValueCAN4_2EL(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
initialize<ValueCAN4_2ELSettings>(makeDriver); initialize<ValueCAN4_2ELSettings>(makeDriver);
} }
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); } void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
size_t getEthernetActivationLineCount() const override { return 1; } size_t getEthernetActivationLineCount() const override { return 1; }
void handleDeviceStatus(const std::shared_ptr<RawMessage>& message) override { void handleDeviceStatus(const std::shared_ptr<RawMessage>& message) override {
if(message->data.size() < sizeof(valuecan4_2el_status_t)) if(message->data.size() < sizeof(valuecan4_2el_status_t))
return; return;
std::lock_guard<std::mutex> lk(ioMutex); std::lock_guard<std::mutex> lk(ioMutex);
const valuecan4_2el_status_t* status = reinterpret_cast<const valuecan4_2el_status_t*>(message->data.data()); const valuecan4_2el_status_t* status = reinterpret_cast<const valuecan4_2el_status_t*>(message->data.data());
ethActivationStatus = status->ethernetActivationLineEnabled; ethActivationStatus = status->ethernetActivationLineEnabled;
} }
bool currentDriverSupportsDFU() const override { return com->driver->isEthernet(); } bool currentDriverSupportsDFU() const override { return com->driver->isEthernet(); }
void setupPacketizer(Packetizer& packetizer) override { void setupPacketizer(Packetizer& packetizer) override {
ValueCAN4::setupPacketizer(packetizer); ValueCAN4::setupPacketizer(packetizer);
packetizer.align16bit = !com->driver->isEthernet(); packetizer.align16bit = !com->driver->isEthernet();
} }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,78 +1,78 @@
#ifndef __VALUECAN4_4_H_ #ifndef __VALUECAN4_4_H_
#define __VALUECAN4_4_H_ #define __VALUECAN4_4_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/tree/valuecan4/valuecan4.h" #include "icsneo/device/tree/valuecan4/valuecan4.h"
#include "icsneo/device/tree/valuecan4/settings/valuecan4-4settings.h" #include "icsneo/device/tree/valuecan4/settings/valuecan4-4settings.h"
namespace icsneo { namespace icsneo {
class ValueCAN4_4 : public ValueCAN4 { class ValueCAN4_4 : public ValueCAN4 {
public: public:
// Serial numbers start with V4 for 4-4 // Serial numbers start with V4 for 4-4
// USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM // USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(ValueCAN4_4, DeviceType::VCAN4_4, "V4"); ICSNEO_FINDABLE_DEVICE(ValueCAN4_4, DeviceType::VCAN4_4, "V4");
enum class SKU { enum class SKU {
Standard, Standard,
AP0400A_D26, // HDB26, USB A, and Keysight Branding AP0400A_D26, // HDB26, USB A, and Keysight Branding
AP0400A_DB9, // 4xDB9, USB A, and Keysight Branding AP0400A_DB9, // 4xDB9, USB A, and Keysight Branding
AP0400A_OBD, // OBD, USB A, and Keysight Branding AP0400A_OBD, // OBD, USB A, and Keysight Branding
}; };
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN, Network::NetID::HSCAN,
Network::NetID::HSCAN2, Network::NetID::HSCAN2,
Network::NetID::HSCAN3, Network::NetID::HSCAN3,
Network::NetID::HSCAN4 Network::NetID::HSCAN4
}; };
return supportedNetworks; return supportedNetworks;
} }
SKU getSKU() const { SKU getSKU() const {
switch(getSerial().back()) { switch(getSerial().back()) {
case 'A': case 'A':
return SKU::AP0400A_D26; return SKU::AP0400A_D26;
case 'B': case 'B':
return SKU::AP0400A_DB9; return SKU::AP0400A_DB9;
case 'C': case 'C':
return SKU::AP0400A_OBD; return SKU::AP0400A_OBD;
default: default:
return SKU::Standard; return SKU::Standard;
} }
} }
std::string getProductName() const override { std::string getProductName() const override {
switch(getSKU()) { switch(getSKU()) {
case SKU::Standard: break; case SKU::Standard: break;
case SKU::AP0400A_D26: case SKU::AP0400A_D26:
return "Keysight AP0400A-D26"; return "Keysight AP0400A-D26";
case SKU::AP0400A_DB9: case SKU::AP0400A_DB9:
return "Keysight AP0400A-DB9"; return "Keysight AP0400A-DB9";
case SKU::AP0400A_OBD: case SKU::AP0400A_OBD:
return "Keysight AP0400A-OBD"; return "Keysight AP0400A-OBD";
} }
return Device::getProductName(); return Device::getProductName();
} }
protected: protected:
ValueCAN4_4(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) { ValueCAN4_4(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
initialize<ValueCAN4_4Settings>(makeDriver); initialize<ValueCAN4_4Settings>(makeDriver);
} }
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); } void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,30 +1,30 @@
#ifndef __VALUECAN4_H_ #ifndef __VALUECAN4_H_
#define __VALUECAN4_H_ #define __VALUECAN4_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
namespace icsneo { namespace icsneo {
class ValueCAN4 : public Device { class ValueCAN4 : public Device {
public: public:
// All ValueCAN 4 devices share a USB PID of 0x1101 // All ValueCAN 4 devices share a USB PID of 0x1101
protected: protected:
using Device::Device; using Device::Device;
virtual void setupEncoder(Encoder& encoder) override { virtual void setupEncoder(Encoder& encoder) override {
Device::setupEncoder(encoder); Device::setupEncoder(encoder);
encoder.supportCANFD = true; encoder.supportCANFD = true;
} }
bool requiresVehiclePower() const override { return false; } bool requiresVehiclePower() const override { return false; }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,55 +1,55 @@
#ifndef __VALUECAN4INDUSTRIAL_H_ #ifndef __VALUECAN4INDUSTRIAL_H_
#define __VALUECAN4INDUSTRIAL_H_ #define __VALUECAN4INDUSTRIAL_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/tree/valuecan4/valuecan4.h" #include "icsneo/device/tree/valuecan4/valuecan4.h"
#include "icsneo/device/tree/valuecan4/settings/valuecan4industrialsettings.h" #include "icsneo/device/tree/valuecan4/settings/valuecan4industrialsettings.h"
namespace icsneo { namespace icsneo {
class ValueCAN4Industrial : public ValueCAN4 { class ValueCAN4Industrial : public ValueCAN4 {
public: public:
// Serial numbers start with IV for Industrial // Serial numbers start with IV for Industrial
// USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM // USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
// Ethernet MAC allocation is 0x12, standard driver is Raw // Ethernet MAC allocation is 0x12, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(ValueCAN4Industrial, DeviceType::VCAN4_IND, "IV"); ICSNEO_FINDABLE_DEVICE(ValueCAN4Industrial, DeviceType::VCAN4_IND, "IV");
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN, Network::NetID::HSCAN,
Network::NetID::HSCAN2, Network::NetID::HSCAN2,
Network::NetID::Ethernet, Network::NetID::Ethernet,
Network::NetID::LIN Network::NetID::LIN
}; };
return supportedNetworks; return supportedNetworks;
} }
protected: protected:
ValueCAN4Industrial(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) { ValueCAN4Industrial(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
initialize<ValueCAN4IndustrialSettings>(makeDriver); initialize<ValueCAN4IndustrialSettings>(makeDriver);
} }
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); } void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
bool currentDriverSupportsDFU() const override { return com->driver->isEthernet(); } bool currentDriverSupportsDFU() const override { return com->driver->isEthernet(); }
void setupPacketizer(Packetizer& packetizer) override { void setupPacketizer(Packetizer& packetizer) override {
ValueCAN4::setupPacketizer(packetizer); ValueCAN4::setupPacketizer(packetizer);
packetizer.align16bit = !com->driver->isEthernet(); packetizer.align16bit = !com->driver->isEthernet();
} }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,42 +1,42 @@
#ifndef __VIVIDCAN_H_ #ifndef __VIVIDCAN_H_
#define __VIVIDCAN_H_ #define __VIVIDCAN_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/platform/cdcacm.h" #include "icsneo/platform/cdcacm.h"
#include "icsneo/device/tree/vividcan/vividcansettings.h" #include "icsneo/device/tree/vividcan/vividcansettings.h"
namespace icsneo { namespace icsneo {
class VividCAN : public Device { class VividCAN : public Device {
public: public:
// Serial numbers start with VV // Serial numbers start with VV
// USB PID is 0x1102, standard driver is CDCACM // USB PID is 0x1102, standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(VividCAN, DeviceType::VividCAN, "VV"); ICSNEO_FINDABLE_DEVICE(VividCAN, DeviceType::VividCAN, "VV");
// VividCAN does not go online, you can only set settings // VividCAN does not go online, you can only set settings
bool goOnline() override { bool goOnline() override {
report(APIEvent::Type::OnlineNotSupported, APIEvent::Severity::Error); report(APIEvent::Type::OnlineNotSupported, APIEvent::Severity::Error);
return false; return false;
} }
bool goOffline() override { bool goOffline() override {
report(APIEvent::Type::OnlineNotSupported, APIEvent::Severity::Error); report(APIEvent::Type::OnlineNotSupported, APIEvent::Severity::Error);
return false; return false;
} }
protected: protected:
VividCAN(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) { VividCAN(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<VividCANSettings>(makeDriver); initialize<VividCANSettings>(makeDriver);
} }
bool requiresVehiclePower() const override { return false; } bool requiresVehiclePower() const override { return false; }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,39 +1,39 @@
#ifndef __ICSNEOCPP_H_ #ifndef __ICSNEOCPP_H_
#define __ICSNEOCPP_H_ #define __ICSNEOCPP_H_
#ifdef __cplusplus #ifdef __cplusplus
#include <vector> #include <vector>
#include <memory> #include <memory>
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/api/version.h" #include "icsneo/api/version.h"
#include "icsneo/api/eventmanager.h" #include "icsneo/api/eventmanager.h"
#include "icsneo/communication/message/canmessage.h" #include "icsneo/communication/message/canmessage.h"
#include "icsneo/communication/message/ethernetmessage.h" #include "icsneo/communication/message/ethernetmessage.h"
#include "icsneo/communication/message/flexray/flexraymessage.h" #include "icsneo/communication/message/flexray/flexraymessage.h"
#include "icsneo/communication/message/iso9141message.h" #include "icsneo/communication/message/iso9141message.h"
#include "icsneo/communication/message/canerrorcountmessage.h" #include "icsneo/communication/message/canerrorcountmessage.h"
#include "icsneo/communication/message/ethphymessage.h" #include "icsneo/communication/message/ethphymessage.h"
namespace icsneo { namespace icsneo {
std::vector<std::shared_ptr<Device>> FindAllDevices(); std::vector<std::shared_ptr<Device>> FindAllDevices();
std::vector<DeviceType> GetSupportedDevices(); std::vector<DeviceType> GetSupportedDevices();
size_t EventCount(EventFilter filter = EventFilter()); size_t EventCount(EventFilter filter = EventFilter());
std::vector<APIEvent> GetEvents(EventFilter filter, size_t max = 0); std::vector<APIEvent> GetEvents(EventFilter filter, size_t max = 0);
std::vector<APIEvent> GetEvents(size_t max = 0, EventFilter filter = EventFilter()); std::vector<APIEvent> GetEvents(size_t max = 0, EventFilter filter = EventFilter());
void GetEvents(std::vector<APIEvent>& events, EventFilter filter, size_t max = 0); void GetEvents(std::vector<APIEvent>& events, EventFilter filter, size_t max = 0);
void GetEvents(std::vector<APIEvent>& events, size_t max = 0, EventFilter filter = EventFilter()); void GetEvents(std::vector<APIEvent>& events, size_t max = 0, EventFilter filter = EventFilter());
APIEvent GetLastError(); APIEvent GetLastError();
void DiscardEvents(EventFilter filter = EventFilter()); void DiscardEvents(EventFilter filter = EventFilter());
void SetEventLimit(size_t newLimit); void SetEventLimit(size_t newLimit);
size_t GetEventLimit(); size_t GetEventLimit();
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,14 +1,14 @@
#ifndef __CDCACM_H_ #ifndef __CDCACM_H_
#define __CDCACM_H_ #define __CDCACM_H_
#define INTREPID_USB_VENDOR_ID (0x093c) #define INTREPID_USB_VENDOR_ID (0x093c)
#if defined _WIN32 #if defined _WIN32
#include "icsneo/platform/windows/cdcacm.h" #include "icsneo/platform/windows/cdcacm.h"
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__)) #elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include "icsneo/platform/posix/cdcacm.h" #include "icsneo/platform/posix/cdcacm.h"
#else #else
#warning "This platform is not supported by the CDC ACM driver" #warning "This platform is not supported by the CDC ACM driver"
#endif #endif
#endif #endif

View File

@ -1,12 +1,12 @@
#ifndef __DYNAMICLIB_H_ #ifndef __DYNAMICLIB_H_
#define __DYNAMICLIB_H_ #define __DYNAMICLIB_H_
#if defined _WIN32 #if defined _WIN32
#include "icsneo/platform/windows/dynamiclib.h" #include "icsneo/platform/windows/dynamiclib.h"
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__)) #elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include "icsneo/platform/posix/dynamiclib.h" #include "icsneo/platform/posix/dynamiclib.h"
#else #else
#warning "This platform is not supported by the dynamic library driver" #warning "This platform is not supported by the dynamic library driver"
#endif #endif
#endif #endif

View File

@ -1,14 +1,14 @@
#ifndef __FTDI_H_ #ifndef __FTDI_H_
#define __FTDI_H_ #define __FTDI_H_
#define INTREPID_USB_VENDOR_ID (0x093c) #define INTREPID_USB_VENDOR_ID (0x093c)
#if defined _WIN32 #if defined _WIN32
#include "icsneo/platform/windows/ftdi.h" #include "icsneo/platform/windows/ftdi.h"
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__)) #elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include "icsneo/platform/posix/ftdi.h" #include "icsneo/platform/posix/ftdi.h"
#else #else
#warning "This platform is not supported by the FTDI driver" #warning "This platform is not supported by the FTDI driver"
#endif #endif
#endif #endif

View File

@ -1,24 +1,24 @@
#ifndef __DYNAMICLIB_POSIX_H_ #ifndef __DYNAMICLIB_POSIX_H_
#define __DYNAMICLIB_POSIX_H_ #define __DYNAMICLIB_POSIX_H_
#include <dlfcn.h> #include <dlfcn.h>
#ifdef __APPLE__ #ifdef __APPLE__
#include "icsneo/platform/posix/darwin/dynamiclib.h" #include "icsneo/platform/posix/darwin/dynamiclib.h"
#else #else
#include "icsneo/platform/posix/linux/dynamiclib.h" #include "icsneo/platform/posix/linux/dynamiclib.h"
#endif #endif
#define DLLExport __attribute__((visibility("default"))) #define DLLExport __attribute__((visibility("default")))
#define LegacyDLLExport DLLExport #define LegacyDLLExport DLLExport
// #ifndef ICSNEO_NO_AUTO_DESTRUCT // #ifndef ICSNEO_NO_AUTO_DESTRUCT
// #define ICSNEO_DESTRUCTOR __attribute__((destructor)); // #define ICSNEO_DESTRUCTOR __attribute__((destructor));
// #else // #else
#define ICSNEO_DESTRUCTOR #define ICSNEO_DESTRUCTOR
// #endif // #endif
#define icsneo_dynamicLibraryGetFunction(handle, func) dlsym(handle, func) #define icsneo_dynamicLibraryGetFunction(handle, func) dlsym(handle, func)
#define icsneo_dynamicLibraryClose(handle) (dlclose(handle) == 0) #define icsneo_dynamicLibraryClose(handle) (dlclose(handle) == 0)
#endif #endif

View File

@ -1,6 +1,6 @@
#ifndef __TCHAR_POSIX_H_ #ifndef __TCHAR_POSIX_H_
#define __TCHAR_POSIX_H_ #define __TCHAR_POSIX_H_
typedef char TCHAR; typedef char TCHAR;
#endif #endif

View File

@ -1,10 +1,10 @@
#ifndef __REGISTRY_H_ #ifndef __REGISTRY_H_
#define __REGISTRY_H_ #define __REGISTRY_H_
#if defined _WIN32 #if defined _WIN32
#include "icsneo/platform/windows/registry.h" #include "icsneo/platform/windows/registry.h"
#else #else
#warning "This platform is not supported by the registry driver" #warning "This platform is not supported by the registry driver"
#endif #endif
#endif #endif

View File

@ -1,20 +1,20 @@
#ifndef __CDCACM_WINDOWS_H_ #ifndef __CDCACM_WINDOWS_H_
#define __CDCACM_WINDOWS_H_ #define __CDCACM_WINDOWS_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/platform/windows/vcp.h" #include "icsneo/platform/windows/vcp.h"
namespace icsneo { namespace icsneo {
class CDCACM : public VCP { class CDCACM : public VCP {
public: public:
CDCACM(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {} CDCACM(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {}
static void Find(std::vector<FoundDevice>& found) { return VCP::Find(found, { L"usbser" }); } static void Find(std::vector<FoundDevice>& found) { return VCP::Find(found, { L"usbser" }); }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,20 +1,20 @@
#ifndef __DYNAMICLIB_WINDOWS_H_ #ifndef __DYNAMICLIB_WINDOWS_H_
#define __DYNAMICLIB_WINDOWS_H_ #define __DYNAMICLIB_WINDOWS_H_
#include "icsneo/platform/windows.h" #include "icsneo/platform/windows.h"
#ifdef ICSNEOC_MAKEDLL #ifdef ICSNEOC_MAKEDLL
#define DLLExport __declspec(dllexport) #define DLLExport __declspec(dllexport)
#else #else
#define DLLExport __declspec(dllimport) #define DLLExport __declspec(dllimport)
#endif #endif
#define LegacyDLLExport DLLExport _stdcall #define LegacyDLLExport DLLExport _stdcall
// MSVC does not have the ability to specify a destructor // MSVC does not have the ability to specify a destructor
#define ICSNEO_DESTRUCTOR #define ICSNEO_DESTRUCTOR
#define icsneo_dynamicLibraryLoad() LoadLibrary(TEXT("icsneoc.dll")) #define icsneo_dynamicLibraryLoad() LoadLibrary(TEXT("icsneoc.dll"))
#define icsneo_dynamicLibraryGetFunction(handle, func) GetProcAddress((HMODULE) handle, func) #define icsneo_dynamicLibraryGetFunction(handle, func) GetProcAddress((HMODULE) handle, func)
#define icsneo_dynamicLibraryClose(handle) FreeLibrary((HMODULE) handle) #define icsneo_dynamicLibraryClose(handle) FreeLibrary((HMODULE) handle)
#endif #endif

View File

@ -1,20 +1,20 @@
#ifndef __FTDI_WINDOWS_H_ #ifndef __FTDI_WINDOWS_H_
#define __FTDI_WINDOWS_H_ #define __FTDI_WINDOWS_H_
#ifdef __cplusplus #ifdef __cplusplus
#include "icsneo/platform/windows/vcp.h" #include "icsneo/platform/windows/vcp.h"
namespace icsneo { namespace icsneo {
class FTDI : public VCP { class FTDI : public VCP {
public: public:
FTDI(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {} FTDI(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {}
static void Find(std::vector<FoundDevice>& found) { return VCP::Find(found, { L"serenum" /*, L"ftdibus" */ }); } static void Find(std::vector<FoundDevice>& found) { return VCP::Find(found, { L"serenum" /*, L"ftdibus" */ }); }
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,28 +1,28 @@
#ifndef __REGISTRY_WINDOWS_H_ #ifndef __REGISTRY_WINDOWS_H_
#define __REGISTRY_WINDOWS_H_ #define __REGISTRY_WINDOWS_H_
#ifdef __cplusplus #ifdef __cplusplus
#include <string> #include <string>
#include <vector> #include <vector>
namespace icsneo { namespace icsneo {
class Registry { class Registry {
public: public:
static bool EnumerateSubkeys(std::wstring path, std::vector<std::wstring>& subkeys); static bool EnumerateSubkeys(std::wstring path, std::vector<std::wstring>& subkeys);
// Get string value // Get string value
static bool Get(std::wstring path, std::wstring key, std::wstring& value); static bool Get(std::wstring path, std::wstring key, std::wstring& value);
static bool Get(std::string path, std::string key, std::string& value); static bool Get(std::string path, std::string key, std::string& value);
// Get DWORD value // Get DWORD value
static bool Get(std::wstring path, std::wstring key, uint32_t& value); static bool Get(std::wstring path, std::wstring key, uint32_t& value);
static bool Get(std::string path, std::string key, uint32_t& value); static bool Get(std::string path, std::string key, uint32_t& value);
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,48 +1,48 @@
#ifndef __VCP_WINDOWS_H_ #ifndef __VCP_WINDOWS_H_
#define __VCP_WINDOWS_H_ #define __VCP_WINDOWS_H_
#ifdef __cplusplus #ifdef __cplusplus
#include <vector> #include <vector>
#include <string> #include <string>
#include <thread> #include <thread>
#include <atomic> #include <atomic>
#include <chrono> #include <chrono>
#include "icsneo/device/neodevice.h" #include "icsneo/device/neodevice.h"
#include "icsneo/communication/driver.h" #include "icsneo/communication/driver.h"
#include "icsneo/api/eventmanager.h" #include "icsneo/api/eventmanager.h"
namespace icsneo { namespace icsneo {
// Virtual COM Port Communication // Virtual COM Port Communication
class VCP : public Driver { class VCP : public Driver {
public: public:
static void Find(std::vector<FoundDevice>& found, std::vector<std::wstring> driverName); static void Find(std::vector<FoundDevice>& found, std::vector<std::wstring> driverName);
static bool IsHandleValid(neodevice_handle_t handle); static bool IsHandleValid(neodevice_handle_t handle);
typedef void(*fn_boolCallback)(bool success); typedef void(*fn_boolCallback)(bool success);
VCP(const device_eventhandler_t& err, neodevice_t& forDevice); VCP(const device_eventhandler_t& err, neodevice_t& forDevice);
~VCP() { close(); } ~VCP() { close(); }
bool open() { return open(false); } bool open() { return open(false); }
void openAsync(fn_boolCallback callback); void openAsync(fn_boolCallback callback);
bool close(); bool close();
bool isOpen(); bool isOpen();
private: private:
bool open(bool fromAsync); bool open(bool fromAsync);
bool opening = false; bool opening = false;
neodevice_t& device; neodevice_t& device;
struct Detail; struct Detail;
std::shared_ptr<Detail> detail; std::shared_ptr<Detail> detail;
std::vector<std::shared_ptr<std::thread>> threads; std::vector<std::shared_ptr<std::thread>> threads;
void readTask(); void readTask();
void writeTask(); void writeTask();
}; };
} }
#endif // __cplusplus #endif // __cplusplus
#endif #endif

View File

@ -1,120 +1,120 @@
#include "icsneo/platform/windows/registry.h" #include "icsneo/platform/windows/registry.h"
#include "icsneo/platform/windows.h" #include "icsneo/platform/windows.h"
#include <codecvt> #include <codecvt>
#include <vector> #include <vector>
#include <locale> #include <locale>
using namespace icsneo; using namespace icsneo;
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
class Key { class Key {
public: public:
Key(std::wstring path, bool readwrite = false); Key(std::wstring path, bool readwrite = false);
~Key(); ~Key();
HKEY GetKey() { return key; } HKEY GetKey() { return key; }
bool IsOpen() { return key != nullptr; } bool IsOpen() { return key != nullptr; }
private: private:
HKEY key; HKEY key;
}; };
Key::Key(std::wstring path, bool readwrite) { Key::Key(std::wstring path, bool readwrite) {
DWORD dwDisposition; DWORD dwDisposition;
if(readwrite) if(readwrite)
RegCreateKeyExW(HKEY_LOCAL_MACHINE, path.c_str(), 0, nullptr, 0, KEY_QUERY_VALUE | KEY_WRITE, nullptr, &key, &dwDisposition); RegCreateKeyExW(HKEY_LOCAL_MACHINE, path.c_str(), 0, nullptr, 0, KEY_QUERY_VALUE | KEY_WRITE, nullptr, &key, &dwDisposition);
else else
RegOpenKeyExW(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_READ, &key); RegOpenKeyExW(HKEY_LOCAL_MACHINE, path.c_str(), 0, KEY_READ, &key);
} }
Key::~Key() { Key::~Key() {
if(IsOpen()) if(IsOpen())
RegCloseKey(key); RegCloseKey(key);
} }
bool Registry::EnumerateSubkeys(std::wstring path, std::vector<std::wstring>& subkeys) { bool Registry::EnumerateSubkeys(std::wstring path, std::vector<std::wstring>& subkeys) {
Key regKey(path); Key regKey(path);
if(!regKey.IsOpen()) if(!regKey.IsOpen())
return false; return false;
wchar_t className[MAX_PATH]; wchar_t className[MAX_PATH];
memset(className, 0, sizeof(className)); memset(className, 0, sizeof(className));
DWORD classNameLen = MAX_PATH; DWORD classNameLen = MAX_PATH;
DWORD subKeyCount = 0; DWORD subKeyCount = 0;
DWORD maxSubKeyLen, maxClassStringLen, valueCount, maxValueNameLen, maxValueDataLen, securityDescriptorLen; DWORD maxSubKeyLen, maxClassStringLen, valueCount, maxValueNameLen, maxValueDataLen, securityDescriptorLen;
FILETIME lastWriteTime; FILETIME lastWriteTime;
auto ret = RegQueryInfoKeyW( auto ret = RegQueryInfoKeyW(
regKey.GetKey(), regKey.GetKey(),
className, className,
&classNameLen, &classNameLen,
nullptr, nullptr,
&subKeyCount, &subKeyCount,
&maxSubKeyLen, &maxSubKeyLen,
&maxClassStringLen, &maxClassStringLen,
&valueCount, &valueCount,
&maxValueNameLen, &maxValueNameLen,
&maxValueDataLen, &maxValueDataLen,
&securityDescriptorLen, &securityDescriptorLen,
&lastWriteTime); &lastWriteTime);
if(ret != ERROR_SUCCESS) if(ret != ERROR_SUCCESS)
return false; return false;
subkeys.clear(); subkeys.clear();
for(DWORD i = 0; i < subKeyCount; i++) { for(DWORD i = 0; i < subKeyCount; i++) {
DWORD nameLen = MAX_PATH; DWORD nameLen = MAX_PATH;
wchar_t name[MAX_PATH]; wchar_t name[MAX_PATH];
memset(name, 0, sizeof(name)); memset(name, 0, sizeof(name));
ret = RegEnumKeyExW(regKey.GetKey(), i, name, &nameLen, nullptr, nullptr, nullptr, &lastWriteTime); ret = RegEnumKeyExW(regKey.GetKey(), i, name, &nameLen, nullptr, nullptr, nullptr, &lastWriteTime);
if(ret == ERROR_SUCCESS) if(ret == ERROR_SUCCESS)
subkeys.push_back(name); subkeys.push_back(name);
} }
return true; return true;
} }
bool Registry::Get(std::wstring path, std::wstring key, std::wstring& value) { bool Registry::Get(std::wstring path, std::wstring key, std::wstring& value) {
Key regKey(path); Key regKey(path);
if(!regKey.IsOpen()) if(!regKey.IsOpen())
return false; return false;
// Query for the type and size of the data // Query for the type and size of the data
DWORD type, size; DWORD type, size;
auto ret = RegQueryValueExW(regKey.GetKey(), key.c_str(), nullptr, &type, (LPBYTE)nullptr, &size); auto ret = RegQueryValueExW(regKey.GetKey(), key.c_str(), nullptr, &type, (LPBYTE)nullptr, &size);
if(ret != ERROR_SUCCESS) if(ret != ERROR_SUCCESS)
return false; return false;
// Query for the data itself // Query for the data itself
std::vector<wchar_t> data(size / 2 + 1); std::vector<wchar_t> data(size / 2 + 1);
DWORD bytesRead = size; // We want to read up to the size we got earlier DWORD bytesRead = size; // We want to read up to the size we got earlier
ret = RegQueryValueExW(regKey.GetKey(), key.c_str(), nullptr, &type, (LPBYTE)data.data(), &bytesRead); ret = RegQueryValueExW(regKey.GetKey(), key.c_str(), nullptr, &type, (LPBYTE)data.data(), &bytesRead);
if(ret != ERROR_SUCCESS) if(ret != ERROR_SUCCESS)
return false; return false;
value = data.data(); value = data.data();
return true; return true;
} }
bool Registry::Get(std::string path, std::string key, std::string& value) { bool Registry::Get(std::string path, std::string key, std::string& value) {
std::wstring wvalue; std::wstring wvalue;
bool ret = Get(converter.from_bytes(path), converter.from_bytes(key), wvalue); bool ret = Get(converter.from_bytes(path), converter.from_bytes(key), wvalue);
value = converter.to_bytes(wvalue); value = converter.to_bytes(wvalue);
return ret; return ret;
} }
bool Registry::Get(std::wstring path, std::wstring key, uint32_t& value) { bool Registry::Get(std::wstring path, std::wstring key, uint32_t& value) {
Key regKey(path); Key regKey(path);
if(!regKey.IsOpen()) if(!regKey.IsOpen())
return false; return false;
// Query for the data // Query for the data
DWORD type, size = sizeof(DWORD), kvalue; DWORD type, size = sizeof(DWORD), kvalue;
auto ret = RegQueryValueExW(regKey.GetKey(), key.c_str(), nullptr, &type, (LPBYTE)&kvalue, &size); auto ret = RegQueryValueExW(regKey.GetKey(), key.c_str(), nullptr, &type, (LPBYTE)&kvalue, &size);
if(ret != ERROR_SUCCESS || type != REG_DWORD) if(ret != ERROR_SUCCESS || type != REG_DWORD)
return false; return false;
value = kvalue; value = kvalue;
return true; return true;
} }
bool Registry::Get(std::string path, std::string key, uint32_t& value) { bool Registry::Get(std::string path, std::string key, uint32_t& value) {
return Get(converter.from_bytes(path), converter.from_bytes(key), value); return Get(converter.from_bytes(path), converter.from_bytes(key), value);
} }

View File

@ -1,466 +1,466 @@
#include "icsneo/platform/windows/ftdi.h" #include "icsneo/platform/windows/ftdi.h"
#include "icsneo/platform/ftdi.h" #include "icsneo/platform/ftdi.h"
#include "icsneo/platform/registry.h" #include "icsneo/platform/registry.h"
#include "icsneo/device/founddevice.h" #include "icsneo/device/founddevice.h"
#include <windows.h> #include <windows.h>
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <cwctype> #include <cwctype>
#include <algorithm> #include <algorithm>
#include <codecvt> #include <codecvt>
#include <limits> #include <limits>
#include <stdio.h> #include <stdio.h>
using namespace icsneo; using namespace icsneo;
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
static const std::wstring DRIVER_SERVICES_REG_KEY = L"SYSTEM\\CurrentControlSet\\services\\"; static const std::wstring DRIVER_SERVICES_REG_KEY = L"SYSTEM\\CurrentControlSet\\services\\";
static const std::wstring ALL_ENUM_REG_KEY = L"SYSTEM\\CurrentControlSet\\Enum\\"; static const std::wstring ALL_ENUM_REG_KEY = L"SYSTEM\\CurrentControlSet\\Enum\\";
static constexpr unsigned int RETRY_TIMES = 5; static constexpr unsigned int RETRY_TIMES = 5;
static constexpr unsigned int RETRY_DELAY = 50; static constexpr unsigned int RETRY_DELAY = 50;
struct VCP::Detail { struct VCP::Detail {
Detail() { Detail() {
overlappedRead.hEvent = INVALID_HANDLE_VALUE; overlappedRead.hEvent = INVALID_HANDLE_VALUE;
overlappedWrite.hEvent = INVALID_HANDLE_VALUE; overlappedWrite.hEvent = INVALID_HANDLE_VALUE;
overlappedWait.hEvent = INVALID_HANDLE_VALUE; overlappedWait.hEvent = INVALID_HANDLE_VALUE;
} }
HANDLE handle = INVALID_HANDLE_VALUE; HANDLE handle = INVALID_HANDLE_VALUE;
OVERLAPPED overlappedRead = {}; OVERLAPPED overlappedRead = {};
OVERLAPPED overlappedWrite = {}; OVERLAPPED overlappedWrite = {};
OVERLAPPED overlappedWait = {}; OVERLAPPED overlappedWait = {};
}; };
void VCP::Find(std::vector<FoundDevice>& found, std::vector<std::wstring> driverNames) { void VCP::Find(std::vector<FoundDevice>& found, std::vector<std::wstring> driverNames) {
for(auto& driverName : driverNames) { for(auto& driverName : driverNames) {
std::wstringstream regss; std::wstringstream regss;
regss << DRIVER_SERVICES_REG_KEY << driverName << L"\\Enum\\"; regss << DRIVER_SERVICES_REG_KEY << driverName << L"\\Enum\\";
std::wstring driverEnumRegKey = regss.str(); std::wstring driverEnumRegKey = regss.str();
uint32_t deviceCount = 0; uint32_t deviceCount = 0;
if(!Registry::Get(driverEnumRegKey, L"Count", deviceCount)) if(!Registry::Get(driverEnumRegKey, L"Count", deviceCount))
continue; continue;
for(uint32_t i = 0; i < deviceCount; i++) { for(uint32_t i = 0; i < deviceCount; i++) {
FoundDevice device; FoundDevice device;
device.makeDriver = [](const device_eventhandler_t& reportFn, neodevice_t& device) { device.makeDriver = [](const device_eventhandler_t& reportFn, neodevice_t& device) {
return std::unique_ptr<Driver>(new VCP(reportFn, device)); return std::unique_ptr<Driver>(new VCP(reportFn, device));
}; };
// First we want to look at what devices FTDI is enumerating (inside driverEnumRegKey) // First we want to look at what devices FTDI is enumerating (inside driverEnumRegKey)
// The entry for a ValueCAN 3 with SN 138635 looks like "FTDIBUS\VID_093C+PID_0601+138635A\0000" // The entry for a ValueCAN 3 with SN 138635 looks like "FTDIBUS\VID_093C+PID_0601+138635A\0000"
// The entry for a ValueCAN 4 with SN V20227 looks like "USB\VID_093C&PID_1101\V20227" // The entry for a ValueCAN 4 with SN V20227 looks like "USB\VID_093C&PID_1101\V20227"
std::wstringstream ss; std::wstringstream ss;
ss << i; ss << i;
std::wstring entry; std::wstring entry;
if(!Registry::Get(driverEnumRegKey, ss.str(), entry)) if(!Registry::Get(driverEnumRegKey, ss.str(), entry))
continue; continue;
std::transform(entry.begin(), entry.end(), entry.begin(), std::towupper); std::transform(entry.begin(), entry.end(), entry.begin(), std::towupper);
std::wstringstream vss; std::wstringstream vss;
vss << "VID_" << std::setfill(L'0') << std::setw(4) << std::uppercase << std::hex << INTREPID_USB_VENDOR_ID; // Intrepid Vendor ID vss << "VID_" << std::setfill(L'0') << std::setw(4) << std::uppercase << std::hex << INTREPID_USB_VENDOR_ID; // Intrepid Vendor ID
if(entry.find(vss.str()) == std::wstring::npos) if(entry.find(vss.str()) == std::wstring::npos)
continue; continue;
auto pidpos = entry.find(L"PID_"); auto pidpos = entry.find(L"PID_");
if(pidpos == std::wstring::npos) if(pidpos == std::wstring::npos)
continue; continue;
// We will later use this and startchar to parse the PID // We will later use this and startchar to parse the PID
// Okay, this is a device we want // Okay, this is a device we want
// Get the serial number // Get the serial number
auto startchar = entry.find(L"+", pidpos + 1); auto startchar = entry.find(L"+", pidpos + 1);
if(startchar == std::wstring::npos) if(startchar == std::wstring::npos)
startchar = entry.find(L"\\", pidpos + 1); startchar = entry.find(L"\\", pidpos + 1);
bool conversionError = false; bool conversionError = false;
int sn = 0; int sn = 0;
try { try {
sn = std::stoi(entry.substr(startchar + 1)); sn = std::stoi(entry.substr(startchar + 1));
} }
catch(...) { catch(...) {
conversionError = true; conversionError = true;
} }
std::wstringstream oss; std::wstringstream oss;
if(!sn || conversionError) if(!sn || conversionError)
oss << entry.substr(startchar + 1, 6); // This is a device with characters in the serial number oss << entry.substr(startchar + 1, 6); // This is a device with characters in the serial number
else else
oss << sn; oss << sn;
device.productId = uint16_t(std::wcstol(entry.c_str() + pidpos + 4, nullptr, 16)); device.productId = uint16_t(std::wcstol(entry.c_str() + pidpos + 4, nullptr, 16));
if(!device.productId) if(!device.productId)
continue; continue;
std::string serial = converter.to_bytes(oss.str()); std::string serial = converter.to_bytes(oss.str());
// The serial number should not have a path slash in it. If it does, that means we don't have the real serial. // The serial number should not have a path slash in it. If it does, that means we don't have the real serial.
if(serial.find_first_of('\\') != std::string::npos) { if(serial.find_first_of('\\') != std::string::npos) {
// The serial number was not in the first serenum key where we expected it. // The serial number was not in the first serenum key where we expected it.
// We can try to match the ContainerID with the one in ALL_ENUM\USB and get a serial that way // We can try to match the ContainerID with the one in ALL_ENUM\USB and get a serial that way
std::wstringstream uess; std::wstringstream uess;
uess << ALL_ENUM_REG_KEY << L"\\USB\\" << vss.str() << L"&PID_" << std::setfill(L'0') << std::setw(4) uess << ALL_ENUM_REG_KEY << L"\\USB\\" << vss.str() << L"&PID_" << std::setfill(L'0') << std::setw(4)
<< std::uppercase << std::hex << device.productId << L'\\'; << std::uppercase << std::hex << device.productId << L'\\';
std::wstringstream ciss; std::wstringstream ciss;
ciss << ALL_ENUM_REG_KEY << entry; ciss << ALL_ENUM_REG_KEY << entry;
std::wstring containerIDFromEntry, containerIDFromEnum; std::wstring containerIDFromEntry, containerIDFromEnum;
if(!Registry::Get(ciss.str(), L"ContainerID", containerIDFromEntry)) if(!Registry::Get(ciss.str(), L"ContainerID", containerIDFromEntry))
continue; // We did not get a container ID. This can happen on Windows XP and before. continue; // We did not get a container ID. This can happen on Windows XP and before.
if(containerIDFromEntry.empty()) if(containerIDFromEntry.empty())
continue; // The container ID was empty? continue; // The container ID was empty?
std::vector<std::wstring> subkeys; std::vector<std::wstring> subkeys;
if(!Registry::EnumerateSubkeys(uess.str(), subkeys)) if(!Registry::EnumerateSubkeys(uess.str(), subkeys))
continue; // VID/PID combo was not present at all. continue; // VID/PID combo was not present at all.
if(subkeys.empty()) if(subkeys.empty())
continue; // No devices for VID/PID. continue; // No devices for VID/PID.
std::wstring correctSerial; std::wstring correctSerial;
for(auto& subkey : subkeys) { for(auto& subkey : subkeys) {
std::wstringstream skss; std::wstringstream skss;
skss << uess.str() << L'\\' << subkey; skss << uess.str() << L'\\' << subkey;
if(!Registry::Get(skss.str(), L"ContainerID", containerIDFromEnum)) if(!Registry::Get(skss.str(), L"ContainerID", containerIDFromEnum))
continue; continue;
if(containerIDFromEntry != containerIDFromEnum) if(containerIDFromEntry != containerIDFromEnum)
continue; continue;
correctSerial = subkey; correctSerial = subkey;
break; break;
} }
if(correctSerial.empty()) if(correctSerial.empty())
continue; // Didn't find the device within the subkeys of the enumeration continue; // Didn't find the device within the subkeys of the enumeration
sn = 0; sn = 0;
conversionError = false; conversionError = false;
try { try {
sn = std::stoi(correctSerial); sn = std::stoi(correctSerial);
} }
catch(...) { catch(...) {
conversionError = true; conversionError = true;
} }
if(!sn || conversionError) { if(!sn || conversionError) {
// This is a device with characters in the serial number // This is a device with characters in the serial number
if(correctSerial.size() != 6) if(correctSerial.size() != 6)
continue; continue;
serial = converter.to_bytes(correctSerial); serial = converter.to_bytes(correctSerial);
} }
else { else {
std::wstringstream soss; std::wstringstream soss;
soss << sn; soss << sn;
serial = converter.to_bytes(soss.str()); serial = converter.to_bytes(soss.str());
} }
if(serial.find_first_of('\\') != std::string::npos) if(serial.find_first_of('\\') != std::string::npos)
continue; continue;
} }
strcpy_s(device.serial, sizeof(device.serial), serial.c_str()); strcpy_s(device.serial, sizeof(device.serial), serial.c_str());
// Serial number is saved, we want the COM port number now // Serial number is saved, we want the COM port number now
// This will be stored under ALL_ENUM_REG_KEY\entry\Device Parameters\PortName (entry from the FTDI_ENUM) // This will be stored under ALL_ENUM_REG_KEY\entry\Device Parameters\PortName (entry from the FTDI_ENUM)
std::wstringstream dpss; std::wstringstream dpss;
dpss << ALL_ENUM_REG_KEY << entry << L"\\Device Parameters"; dpss << ALL_ENUM_REG_KEY << entry << L"\\Device Parameters";
std::wstring port; std::wstring port;
Registry::Get(dpss.str(), L"PortName", port); // TODO If error do something else (Plasma maybe?) Registry::Get(dpss.str(), L"PortName", port); // TODO If error do something else (Plasma maybe?)
std::transform(port.begin(), port.end(), port.begin(), std::towupper); std::transform(port.begin(), port.end(), port.begin(), std::towupper);
auto compos = port.find(L"COM"); auto compos = port.find(L"COM");
device.handle = 0; device.handle = 0;
if(compos != std::wstring::npos) { if(compos != std::wstring::npos) {
try { try {
device.handle = std::stoi(port.substr(compos + 3)); device.handle = std::stoi(port.substr(compos + 3));
} }
catch(...) {} // In case of this, or any other error, handle has already been initialized to 0 catch(...) {} // In case of this, or any other error, handle has already been initialized to 0
} }
bool alreadyFound = false; bool alreadyFound = false;
FoundDevice* shouldReplace = nullptr; FoundDevice* shouldReplace = nullptr;
for(auto& foundDev : found) { for(auto& foundDev : found) {
if((foundDev.handle == device.handle || foundDev.handle == 0 || device.handle == 0) && serial == foundDev.serial) { if((foundDev.handle == device.handle || foundDev.handle == 0 || device.handle == 0) && serial == foundDev.serial) {
alreadyFound = true; alreadyFound = true;
if(foundDev.handle == 0) if(foundDev.handle == 0)
shouldReplace = &foundDev; shouldReplace = &foundDev;
break; break;
} }
} }
if(!alreadyFound) if(!alreadyFound)
found.push_back(device); found.push_back(device);
else if(shouldReplace != nullptr) else if(shouldReplace != nullptr)
*shouldReplace = device; *shouldReplace = device;
} }
} }
} }
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), device(forDevice) {
detail = std::make_shared<Detail>(); detail = std::make_shared<Detail>();
} }
bool VCP::IsHandleValid(neodevice_handle_t handle) { bool VCP::IsHandleValid(neodevice_handle_t handle) {
if(handle < 1) if(handle < 1)
return false; return false;
if(handle > 256) // Windows default max COM port is COM256 if(handle > 256) // Windows default max COM port is COM256
return false; // TODO Enumerate subkeys of HKLM\HARDWARE\DEVICEMAP\SERIALCOMM as a user might have more serial ports somehow return false; // TODO Enumerate subkeys of HKLM\HARDWARE\DEVICEMAP\SERIALCOMM as a user might have more serial ports somehow
return true; return true;
} }
bool VCP::open(bool fromAsync) { bool VCP::open(bool fromAsync) {
if(isOpen() || (!fromAsync && opening)) { if(isOpen() || (!fromAsync && opening)) {
report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error); report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error);
return false; return false;
} }
if(!IsHandleValid(device.handle)) { if(!IsHandleValid(device.handle)) {
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
} }
opening = true; opening = true;
std::wstringstream comss; std::wstringstream comss;
comss << L"\\\\.\\COM" << device.handle; comss << L"\\\\.\\COM" << device.handle;
// We're going to attempt to open 5 (RETRY_TIMES) times in a row // We're going to attempt to open 5 (RETRY_TIMES) times in a row
for(int i = 0; !isOpen() && i < RETRY_TIMES; i++) { for(int i = 0; !isOpen() && i < RETRY_TIMES; i++) {
detail->handle = CreateFileW(comss.str().c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr, detail->handle = CreateFileW(comss.str().c_str(), GENERIC_READ | GENERIC_WRITE, 0, nullptr,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr); OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
if(GetLastError() == ERROR_SUCCESS) if(GetLastError() == ERROR_SUCCESS)
break; // We have the file handle break; // We have the file handle
std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_DELAY)); std::this_thread::sleep_for(std::chrono::milliseconds(RETRY_DELAY));
} }
opening = false; opening = false;
if(!isOpen()) { if(!isOpen()) {
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
} }
// Set the timeouts // Set the timeouts
COMMTIMEOUTS timeouts; COMMTIMEOUTS timeouts;
if(!GetCommTimeouts(detail->handle, &timeouts)) { if(!GetCommTimeouts(detail->handle, &timeouts)) {
close(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
} }
// See https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_commtimeouts#remarks // See https://docs.microsoft.com/en-us/windows/desktop/api/winbase/ns-winbase-_commtimeouts#remarks
timeouts.ReadIntervalTimeout = MAXDWORD; timeouts.ReadIntervalTimeout = MAXDWORD;
timeouts.ReadTotalTimeoutMultiplier = MAXDWORD; timeouts.ReadTotalTimeoutMultiplier = MAXDWORD;
timeouts.ReadTotalTimeoutConstant = 100; timeouts.ReadTotalTimeoutConstant = 100;
timeouts.WriteTotalTimeoutConstant = 10000; timeouts.WriteTotalTimeoutConstant = 10000;
timeouts.WriteTotalTimeoutMultiplier = 0; timeouts.WriteTotalTimeoutMultiplier = 0;
if(!SetCommTimeouts(detail->handle, &timeouts)) { if(!SetCommTimeouts(detail->handle, &timeouts)) {
close(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
} }
// Set the COM state // Set the COM state
DCB comstate; DCB comstate;
if(!GetCommState(detail->handle, &comstate)) { if(!GetCommState(detail->handle, &comstate)) {
close(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
} }
comstate.BaudRate = 115200; comstate.BaudRate = 115200;
comstate.ByteSize = 8; comstate.ByteSize = 8;
comstate.Parity = NOPARITY; comstate.Parity = NOPARITY;
comstate.StopBits = 0; comstate.StopBits = 0;
comstate.fDtrControl = DTR_CONTROL_ENABLE; comstate.fDtrControl = DTR_CONTROL_ENABLE;
comstate.fRtsControl = RTS_CONTROL_ENABLE; comstate.fRtsControl = RTS_CONTROL_ENABLE;
if(!SetCommState(detail->handle, &comstate)) { if(!SetCommState(detail->handle, &comstate)) {
close(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
} }
PurgeComm(detail->handle, PURGE_RXCLEAR); PurgeComm(detail->handle, PURGE_RXCLEAR);
// Set up events so that overlapped IO can work with them // Set up events so that overlapped IO can work with them
detail->overlappedRead.hEvent = CreateEvent(nullptr, false, false, nullptr); detail->overlappedRead.hEvent = CreateEvent(nullptr, false, false, nullptr);
detail->overlappedWrite.hEvent = CreateEvent(nullptr, false, false, nullptr); detail->overlappedWrite.hEvent = CreateEvent(nullptr, false, false, nullptr);
detail->overlappedWait.hEvent = CreateEvent(nullptr, true, false, nullptr); detail->overlappedWait.hEvent = CreateEvent(nullptr, true, false, nullptr);
if (detail->overlappedRead.hEvent == nullptr || detail->overlappedWrite.hEvent == nullptr || detail->overlappedWait.hEvent == nullptr) { if (detail->overlappedRead.hEvent == nullptr || detail->overlappedWrite.hEvent == nullptr || detail->overlappedWait.hEvent == nullptr) {
close(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
} }
// Set up event so that we will satisfy overlappedWait when a character comes in // Set up event so that we will satisfy overlappedWait when a character comes in
if(!SetCommMask(detail->handle, EV_RXCHAR)) { if(!SetCommMask(detail->handle, EV_RXCHAR)) {
close(); close();
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
return false; return false;
} }
// TODO Set up some sort of shared memory, save which COM port we have open so we don't try to open it again // TODO Set up some sort of shared memory, save which COM port we have open so we don't try to open it again
// Create threads // Create threads
readThread = std::thread(&VCP::readTask, this); readThread = std::thread(&VCP::readTask, this);
writeThread = std::thread(&VCP::writeTask, this); writeThread = std::thread(&VCP::writeTask, this);
return true; return true;
} }
void VCP::openAsync(fn_boolCallback callback) { void VCP::openAsync(fn_boolCallback callback) {
threads.push_back(std::make_shared<std::thread>([&]() { threads.push_back(std::make_shared<std::thread>([&]() {
callback(open(true)); callback(open(true));
})); }));
} }
bool VCP::close() { bool VCP::close() {
if(!isOpen()) { if(!isOpen()) {
report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error); report(APIEvent::Type::DeviceCurrentlyClosed, APIEvent::Severity::Error);
return false; return false;
} }
closing = true; // Signal the threads that we are closing closing = true; // Signal the threads that we are closing
for(auto& t : threads) for(auto& t : threads)
t->join(); // Wait for the threads to close t->join(); // Wait for the threads to close
readThread.join(); readThread.join();
writeThread.join(); writeThread.join();
closing = false; closing = false;
if(!CloseHandle(detail->handle)) { if(!CloseHandle(detail->handle)) {
report(APIEvent::Type::DriverFailedToClose, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToClose, APIEvent::Severity::Error);
return false; return false;
} }
detail->handle = INVALID_HANDLE_VALUE; detail->handle = INVALID_HANDLE_VALUE;
bool ret = true; // If one of the events fails closing, we probably still want to try and close the others bool ret = true; // If one of the events fails closing, we probably still want to try and close the others
if(detail->overlappedRead.hEvent != INVALID_HANDLE_VALUE) { if(detail->overlappedRead.hEvent != INVALID_HANDLE_VALUE) {
if(!CloseHandle(detail->overlappedRead.hEvent)) if(!CloseHandle(detail->overlappedRead.hEvent))
ret = false; ret = false;
detail->overlappedRead.hEvent = INVALID_HANDLE_VALUE; detail->overlappedRead.hEvent = INVALID_HANDLE_VALUE;
} }
if(detail->overlappedWrite.hEvent != INVALID_HANDLE_VALUE) { if(detail->overlappedWrite.hEvent != INVALID_HANDLE_VALUE) {
if(!CloseHandle(detail->overlappedWrite.hEvent)) if(!CloseHandle(detail->overlappedWrite.hEvent))
ret = false; ret = false;
detail->overlappedWrite.hEvent = INVALID_HANDLE_VALUE; detail->overlappedWrite.hEvent = INVALID_HANDLE_VALUE;
} }
if(detail->overlappedWait.hEvent != INVALID_HANDLE_VALUE) { if(detail->overlappedWait.hEvent != INVALID_HANDLE_VALUE) {
if(!CloseHandle(detail->overlappedWait.hEvent)) if(!CloseHandle(detail->overlappedWait.hEvent))
ret = false; ret = false;
detail->overlappedWait.hEvent = INVALID_HANDLE_VALUE; detail->overlappedWait.hEvent = INVALID_HANDLE_VALUE;
} }
uint8_t flush; uint8_t flush;
WriteOperation flushop; WriteOperation flushop;
while(readQueue.try_dequeue(flush)) {} while(readQueue.try_dequeue(flush)) {}
while(writeQueue.try_dequeue(flushop)) {} while(writeQueue.try_dequeue(flushop)) {}
if(!ret) if(!ret)
report(APIEvent::Type::DriverFailedToClose, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToClose, APIEvent::Severity::Error);
// TODO Set up some sort of shared memory, free which COM port we had open so we can try to open it again // TODO Set up some sort of shared memory, free which COM port we had open so we can try to open it again
return ret; return ret;
} }
bool VCP::isOpen() { bool VCP::isOpen() {
return detail->handle != INVALID_HANDLE_VALUE; return detail->handle != INVALID_HANDLE_VALUE;
} }
void VCP::readTask() { void VCP::readTask() {
constexpr size_t READ_BUFFER_SIZE = 10240; constexpr size_t READ_BUFFER_SIZE = 10240;
uint8_t readbuf[READ_BUFFER_SIZE]; uint8_t readbuf[READ_BUFFER_SIZE];
IOTaskState state = LAUNCH; IOTaskState state = LAUNCH;
DWORD bytesRead = 0; DWORD bytesRead = 0;
EventManager::GetInstance().downgradeErrorsOnCurrentThread(); EventManager::GetInstance().downgradeErrorsOnCurrentThread();
while(!closing && !isDisconnected()) { while(!closing && !isDisconnected()) {
switch(state) { switch(state) {
case LAUNCH: { case LAUNCH: {
COMSTAT comStatus; COMSTAT comStatus;
unsigned long errorCodes; unsigned long errorCodes;
ClearCommError(detail->handle, &errorCodes, &comStatus); ClearCommError(detail->handle, &errorCodes, &comStatus);
bytesRead = 0; bytesRead = 0;
if(ReadFile(detail->handle, readbuf, READ_BUFFER_SIZE, nullptr, &detail->overlappedRead)) { if(ReadFile(detail->handle, readbuf, READ_BUFFER_SIZE, nullptr, &detail->overlappedRead)) {
if(GetOverlappedResult(detail->handle, &detail->overlappedRead, &bytesRead, FALSE)) { if(GetOverlappedResult(detail->handle, &detail->overlappedRead, &bytesRead, FALSE)) {
if(bytesRead) if(bytesRead)
readQueue.enqueue_bulk(readbuf, bytesRead); readQueue.enqueue_bulk(readbuf, bytesRead);
} }
continue; continue;
} }
auto lastError = GetLastError(); auto lastError = GetLastError();
if(lastError == ERROR_IO_PENDING) if(lastError == ERROR_IO_PENDING)
state = WAIT; state = WAIT;
else if(lastError != ERROR_SUCCESS) { else if(lastError != ERROR_SUCCESS) {
if(lastError == ERROR_ACCESS_DENIED) { if(lastError == ERROR_ACCESS_DENIED) {
if(!isDisconnected()) { if(!isDisconnected()) {
disconnected = true; disconnected = true;
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error); report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
} }
} else } else
report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error); report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
} }
} }
break; break;
case WAIT: { case WAIT: {
auto ret = WaitForSingleObject(detail->overlappedRead.hEvent, 100); auto ret = WaitForSingleObject(detail->overlappedRead.hEvent, 100);
if(ret == WAIT_OBJECT_0) { if(ret == WAIT_OBJECT_0) {
if(GetOverlappedResult(detail->handle, &detail->overlappedRead, &bytesRead, FALSE)) { if(GetOverlappedResult(detail->handle, &detail->overlappedRead, &bytesRead, FALSE)) {
readQueue.enqueue_bulk(readbuf, bytesRead); readQueue.enqueue_bulk(readbuf, bytesRead);
state = LAUNCH; state = LAUNCH;
} else } else
report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error); report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
} }
if(ret == WAIT_ABANDONED || ret == WAIT_FAILED) { if(ret == WAIT_ABANDONED || ret == WAIT_FAILED) {
state = LAUNCH; state = LAUNCH;
report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error); report(APIEvent::Type::FailedToRead, APIEvent::Severity::Error);
} }
} }
} }
} }
} }
void VCP::writeTask() { void VCP::writeTask() {
IOTaskState state = LAUNCH; IOTaskState state = LAUNCH;
VCP::WriteOperation writeOp; VCP::WriteOperation writeOp;
DWORD bytesWritten = 0; DWORD bytesWritten = 0;
EventManager::GetInstance().downgradeErrorsOnCurrentThread(); EventManager::GetInstance().downgradeErrorsOnCurrentThread();
while(!closing && !isDisconnected()) { while(!closing && !isDisconnected()) {
switch(state) { switch(state) {
case LAUNCH: { case LAUNCH: {
if(!writeQueue.wait_dequeue_timed(writeOp, std::chrono::milliseconds(100))) if(!writeQueue.wait_dequeue_timed(writeOp, std::chrono::milliseconds(100)))
continue; continue;
bytesWritten = 0; bytesWritten = 0;
if(WriteFile(detail->handle, writeOp.bytes.data(), (DWORD)writeOp.bytes.size(), nullptr, &detail->overlappedWrite)) if(WriteFile(detail->handle, writeOp.bytes.data(), (DWORD)writeOp.bytes.size(), nullptr, &detail->overlappedWrite))
continue; continue;
auto winerr = GetLastError(); auto winerr = GetLastError();
if(winerr == ERROR_IO_PENDING) { if(winerr == ERROR_IO_PENDING) {
state = WAIT; state = WAIT;
} }
else if(winerr == ERROR_ACCESS_DENIED) { else if(winerr == ERROR_ACCESS_DENIED) {
if(!isDisconnected()) { if(!isDisconnected()) {
disconnected = true; disconnected = true;
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error); report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
} }
} else } else
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error); report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
} }
break; break;
case WAIT: { case WAIT: {
auto ret = WaitForSingleObject(detail->overlappedWrite.hEvent, 50); auto ret = WaitForSingleObject(detail->overlappedWrite.hEvent, 50);
if(ret == WAIT_OBJECT_0) { if(ret == WAIT_OBJECT_0) {
if(!GetOverlappedResult(detail->handle, &detail->overlappedWrite, &bytesWritten, FALSE)) if(!GetOverlappedResult(detail->handle, &detail->overlappedWrite, &bytesWritten, FALSE))
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error); report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
state = LAUNCH; state = LAUNCH;
} }
if(ret == WAIT_ABANDONED) { if(ret == WAIT_ABANDONED) {
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error); report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
state = LAUNCH; state = LAUNCH;
} }
} }
} }
} }
} }