Drivers: Decouple from devices

This allows us to better implement alternative drivers
for devices, such as for device sharing servers or
talking to CoreMini processors within the same device.
v0.3.0-dev
Paul Hollinsky 2022-03-24 15:48:26 -07:00
parent 0ff12300f3
commit 781fc2c034
66 changed files with 780 additions and 1566 deletions

View File

@ -8,6 +8,9 @@ option(LIBICSNEO_BUILD_ICSNEOC "Build dynamic C library" ON)
option(LIBICSNEO_BUILD_ICSNEOC_STATIC "Build static C library" ON)
option(LIBICSNEO_BUILD_ICSNEOLEGACY "Build icsnVC40 compatibility library" ON)
set(LIBICSNEO_NPCAP_INCLUDE_DIR "" CACHE STRING "Npcap include directory; set to build with Npcap")
option(LIBICSNEO_ENABLE_RAW_ETHERNET "Enable devices which communicate over raw ethernet" ON)
option(LIBICSNEO_ENABLE_CDCACM "Enable devices which communicate over USB CDC ACM" ON)
option(LIBICSNEO_ENABLE_FTDI "Enable devices which communicate over USB FTDI2XX" ON)
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11)
@ -86,30 +89,55 @@ endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
set(PLATFORM_SRC
platform/windows/pcap.cpp
platform/windows/registry.cpp
platform/windows/vcp.cpp
platform/windows/internal/pcapdll.cpp
)
if(LIBICSNEO_ENABLE_RAW_ETHERNET)
list(APPEND PLATFORM_SRC
platform/windows/pcap.cpp
platform/windows/internal/pcapdll.cpp
)
endif()
if(LIBICSNEO_ENABLE_CDCACM OR LIBICSNEO_ENABLE_FTDI)
list(APPEND PLATFORM_SRC
platform/windows/vcp.cpp
)
endif()
else() # Darwin or Linux
set(PLATFORM_SRC
platform/posix/ftdi.cpp
platform/posix/pcap.cpp
platform/posix/cdcacm.cpp
)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
set(PLATFORM_SRC)
if(LIBICSNEO_ENABLE_RAW_ETHERNET)
list(APPEND PLATFORM_SRC
platform/posix/darwin/cdcacmdarwin.cpp
platform/posix/pcap.cpp
)
else() # Linux or other
endif()
if(LIBICSNEO_ENABLE_FTDI)
list(APPEND PLATFORM_SRC
platform/posix/linux/cdcacmlinux.cpp
platform/posix/ftdi.cpp
)
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
message(WARNING
"There is no platform port defined for ${CMAKE_SYSTEM_NAME}!\n"
"The Linux platform code will be used, as it will generally allow building, but some devices may not enumerate properly."
endif()
if(LIBICSNEO_ENABLE_CDCACM)
list(APPEND PLATFORM_SRC
platform/posix/cdcacm.cpp
)
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
list(APPEND PLATFORM_SRC
platform/posix/darwin/cdcacmdarwin.cpp
)
else() # Linux or other
list(APPEND PLATFORM_SRC
platform/posix/linux/cdcacmlinux.cpp
)
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
message(WARNING
"There is no CDCACM platform port defined for ${CMAKE_SYSTEM_NAME}!\n"
"The Linux platform code will be used, as it will generally allow building, but some devices may not enumerate properly."
)
endif()
endif()
endif()
endif()
@ -149,6 +177,7 @@ set(SRC_FILES
device/idevicesettings.cpp
device/devicefinder.cpp
device/device.cpp
device/neodevice.cpp
disk/diskreaddriver.cpp
disk/diskwritedriver.cpp
disk/nulldiskdriver.cpp
@ -220,6 +249,15 @@ set_property(TARGET icsneocpp PROPERTY POSITION_INDEPENDENT_CODE ON)
target_compile_features(icsneocpp PUBLIC cxx_auto_type cxx_constexpr cxx_lambdas cxx_nullptr cxx_range_for cxx_rvalue_references cxx_sizeof_member cxx_strong_enums)
message("Loaded extensions: " ${LIBICSNEO_EXTENSION_TARGETS})
target_link_libraries(icsneocpp PUBLIC ${LIBICSNEO_EXTENSION_TARGETS})
if(LIBICSNEO_ENABLE_RAW_ETHERNET)
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_RAW_ETHERNET)
endif()
if(LIBICSNEO_ENABLE_CDCACM)
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_CDCACM)
endif()
if(LIBICSNEO_ENABLE_FTDI)
target_compile_definitions(icsneocpp PRIVATE ICSNEO_ENABLE_FTDI)
endif()
# fatfs
add_subdirectory(third-party/fatfs)

View File

@ -3,6 +3,7 @@
#include <iterator>
#include <cstring>
#include <cassert>
#include <iostream>
using namespace icsneo;
@ -74,7 +75,7 @@ bool EthernetPacketizer::inputUp(std::vector<uint8_t> bytes) {
memcmp(packet.destMAC, BROADCAST_MAC, sizeof(packet.destMAC)) != 0)
return false; // Packet is not addressed to us or broadcast
if(memcmp(packet.srcMAC, deviceMAC, sizeof(deviceMAC)) != 0)
if(!allowInPacketsFromAnyMAC && memcmp(packet.srcMAC, deviceMAC, sizeof(deviceMAC)) != 0)
return false; // Not a packet from the device we're concerned with
// Handle single packets

View File

@ -1,265 +1,155 @@
#include "icsneo/device/devicefinder.h"
#include "icsneo/platform/devices.h"
#include "icsneo/device/founddevice.h"
#include "generated/extensions/builtin.h"
#ifdef ICSNEO_ENABLE_RAW_ETHERNET
#include "icsneo/platform/pcap.h"
#endif
#ifdef ICSNEO_ENABLE_CDCACM
#include "icsneo/platform/cdcacm.h"
#endif
#ifdef ICSNEO_ENABLE_FTDI
#include "icsneo/platform/ftdi.h"
#endif
using namespace icsneo;
static bool supportedDevicesCached = false;
static std::vector<DeviceType> supportedDevices = {
template<typename T>
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"`
// and also a public constructor `T(const FoundDevice& dev)`
// Use macro ICSNEO_FINDABLE_DEVICE() to create these
if(dev.serial[0] == T::SERIAL_START[0] && dev.serial[1] == T::SERIAL_START[1])
into.push_back(std::make_shared<T>(dev));
}
#ifdef __ETHERBADGE_H_
EtherBADGE::DEVICE_TYPE,
#endif
#ifdef __NEOOBD2PRO_H_
NeoOBD2PRO::DEVICE_TYPE,
#endif
#ifdef __NEOOBD2SIM_H_
NeoOBD2SIM::DEVICE_TYPE,
#endif
#ifdef __NEOVIRED2_H_
NeoVIRED2::DEVICE_TYPE,
#endif
#ifdef __NEOVIFIRE_H_
NeoVIFIRE::DEVICE_TYPE,
#endif
#ifdef __NEOVIFIRE2ETH_H_
NeoVIFIRE2ETH::DEVICE_TYPE,
#endif
#ifdef __NEOVIFIRE2USB_H_
NeoVIFIRE2USB::DEVICE_TYPE,
#endif
#ifdef __NEOVIION_H_
NeoVIION::DEVICE_TYPE,
#endif
#ifdef __NEOVIPLASMA_H_
NeoVIPLASMA::DEVICE_TYPE,
#endif
#ifdef __RADEPSILON_H_
RADEpsilon::DEVICE_TYPE,
#endif
#ifdef __RADGALAXY_H_
RADGalaxy::DEVICE_TYPE,
#endif
#ifdef __RADMARS_ETH_H_
RADMarsETH::DEVICE_TYPE,
#endif
#ifdef __RADMARS_USB_H_
RADMarsUSB::DEVICE_TYPE,
#endif
#ifdef __RADGIGASTAR_ETH_H_
RADGigastarETH::DEVICE_TYPE,
#endif
#ifdef __RADGIGASTAR_USB_H_
RADGigastarUSB::DEVICE_TYPE,
#endif
#ifdef __RADMOON2_H_
RADMoon2::DEVICE_TYPE,
#endif
#ifdef __RADMOONDUO_H_
RADMoonDuo::DEVICE_TYPE,
#endif
#ifdef __RADPLUTOUSB_H_
RADPlutoUSB::DEVICE_TYPE,
#endif
#ifdef __RADSTAR2ETH_H_
RADStar2ETH::DEVICE_TYPE,
#endif
#ifdef __RADSTAR2USB_H_
RADStar2USB::DEVICE_TYPE,
#endif
#ifdef __RADSUPERMOON_H_
RADSupermoon::DEVICE_TYPE,
#endif
#ifdef __VALUECAN3_H_
ValueCAN3::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4_1_H_
ValueCAN4_1::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4_2_H_
ValueCAN4_2::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4_2EL_ETH_H_
ValueCAN4_2EL_ETH::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4_2EL_USB_H_
ValueCAN4_2EL_USB::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4_4_H_
ValueCAN4_4::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4INDUSTRIAL_ETH_H_
ValueCAN4IndustrialETH::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4INDUSTRIAL_USB_H_
ValueCAN4IndustrialUSB::DEVICE_TYPE,
#endif
#ifdef __VIVIDCAN_H_
VividCAN::DEVICE_TYPE,
#endif
};
template<typename T>
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`
// and also a public constructor `T(const FoundDevice& dev)`
// Use macro ICSNEO_FINDABLE_DEVICE_BY_PID() to create these
if(dev.productId == T::PRODUCT_ID)
into.push_back(std::make_shared<T>(dev));
}
std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
static std::vector<FoundDevice> driverFoundDevices;
driverFoundDevices.clear();
#ifdef ICSNEO_ENABLE_RAW_ETHERNET
PCAP::Find(driverFoundDevices);
#endif
#ifdef ICSNEO_ENABLE_CDCACM
CDCACM::Find(driverFoundDevices);
#endif
#ifdef ICSNEO_ENABLE_FTDI
FTDI::Find(driverFoundDevices);
#endif
std::vector<std::shared_ptr<Device>> foundDevices;
std::vector<std::vector<std::shared_ptr<Device>>> findResults;
#if defined(LIBICSNEO_HAVE_PCAP) && LIBICSNEO_HAVE_PCAP == 1
auto pcapDevices = PCAP::FindAll();
#endif
// Offer found devices to each of the subclasses
for (const FoundDevice& dev : driverFoundDevices) {
#ifdef __ETHERBADGE_H_
makeIfSerialMatches<EtherBADGE>(dev, foundDevices);
#endif
#ifdef __ETHERBADGE_H_
findResults.push_back(EtherBADGE::Find());
#endif
#ifdef __NEOOBD2PRO_H_
makeIfSerialMatches<NeoOBD2PRO>(dev, foundDevices);
#endif
#ifdef __NEOOBD2PRO_H_
findResults.push_back(NeoOBD2PRO::Find());
#endif
#ifdef __NEOOBD2SIM_H_
makeIfSerialMatches<NeoOBD2SIM>(dev, foundDevices);
#endif
#ifdef __NEOOBD2SIM_H_
findResults.push_back(NeoOBD2SIM::Find());
#endif
#ifdef __NEOVIFIRE_H_
makeIfPIDMatches<NeoVIFIRE>(dev, foundDevices);
#endif
#ifdef __NEOVIFIRE_H_
findResults.push_back(NeoVIFIRE::Find());
#endif
#ifdef __NEOVIFIRE2_H_
makeIfSerialMatches<NeoVIFIRE2>(dev, foundDevices);
#endif
#ifdef __NEOVIFIRE2ETH_H_
findResults.push_back(NeoVIFIRE2ETH::Find(pcapDevices));
#endif
#ifdef __NEOVIRED2_H_
makeIfSerialMatches<NeoVIRED2>(dev, foundDevices);
#endif
#ifdef __NEOVIFIRE2USB_H_
findResults.push_back(NeoVIFIRE2USB::Find());
#endif
#ifdef __NEOVIION_H_
makeIfPIDMatches<NeoVIION>(dev, foundDevices);
#endif
#ifdef __NEOVIRED2_H_
findResults.push_back(NeoVIRED2::Find(pcapDevices));
#endif
#ifdef __NEOVIPLASMA_H_
makeIfPIDMatches<NeoVIPLASMA>(dev, foundDevices);
#endif
#ifdef __NEOVIION_H_
findResults.push_back(NeoVIION::Find());
#endif
#ifdef __RADEPSILON_H_
makeIfSerialMatches<RADEpsilon>(dev, foundDevices);
#endif
#ifdef __NEOVIPLASMA_H_
findResults.push_back(NeoVIPLASMA::Find());
#endif
#ifdef __RADGALAXY_H_
makeIfSerialMatches<RADGalaxy>(dev, foundDevices);
#endif
#ifdef __RADEPSILON_H_
findResults.push_back(RADEpsilon::Find());
#endif
#ifdef __RADMARS_H_
makeIfSerialMatches<RADMars>(dev, foundDevices);
#endif
#ifdef __RADGALAXY_H_
findResults.push_back(RADGalaxy::Find(pcapDevices));
#endif
#ifdef __RADGIGASTAR_H_
makeIfSerialMatches<RADGigastar>(dev, foundDevices);
#endif
#ifdef __RADMARS_ETH_H_
findResults.push_back(RADMarsETH::Find(pcapDevices));
#endif
#ifdef __RADMOON2_H_
makeIfSerialMatches<RADMoon2>(dev, foundDevices);
#endif
#ifdef __RADMARS_USB_H_
findResults.push_back(RADMarsUSB::Find());
#endif
#ifdef __RADMOONDUO_H_
makeIfSerialMatches<RADMoonDuo>(dev, foundDevices);
#endif
#ifdef __RADGIGASTAR_ETH_H_
findResults.push_back(RADGigastarETH::Find(pcapDevices));
#endif
#ifdef __RADPLUTO_H_
makeIfSerialMatches<RADPluto>(dev, foundDevices);
#endif
#ifdef __RADGIGASTAR_USB_H_
findResults.push_back(RADGigastarUSB::Find());
#endif
#ifdef __RADSTAR2_H_
makeIfSerialMatches<RADStar2>(dev, foundDevices);
#endif
#ifdef __RADMOON2_H_
findResults.push_back(RADMoon2::Find());
#endif
#ifdef __RADSUPERMOON_H_
makeIfSerialMatches<RADSupermoon>(dev, foundDevices);
#endif
#ifdef __RADMOONDUO_H_
findResults.push_back(RADMoonDuo::Find());
#endif
#ifdef __VALUECAN3_H_
makeIfPIDMatches<ValueCAN3>(dev, foundDevices);
#endif
#ifdef __RADPLUTOUSB_H_
findResults.push_back(RADPlutoUSB::Find());
#endif
#ifdef __VALUECAN4_1_H_
makeIfSerialMatches<ValueCAN4_1>(dev, foundDevices);
#endif
#ifdef __RADSTAR2ETH_H_
findResults.push_back(RADStar2ETH::Find(pcapDevices));
#endif
#ifdef __VALUECAN4_2_H_
makeIfSerialMatches<ValueCAN4_2>(dev, foundDevices);
#endif
#ifdef __RADSTAR2USB_H_
findResults.push_back(RADStar2USB::Find());
#endif
#ifdef __VALUECAN4_2EL_H_
makeIfSerialMatches<ValueCAN4_2EL>(dev, foundDevices);
#endif
#ifdef __RADSUPERMOON_H_
findResults.push_back(RADSupermoon::Find());
#endif
#ifdef __VALUECAN4_4_H_
makeIfSerialMatches<ValueCAN4_4>(dev, foundDevices);
#endif
#ifdef __VALUECAN3_H_
findResults.push_back(ValueCAN3::Find());
#endif
#ifdef __VALUECAN4INDUSTRIAL_H_
makeIfSerialMatches<ValueCAN4Industrial>(dev, foundDevices);
#endif
#ifdef __VALUECAN4_1_H_
findResults.push_back(ValueCAN4_1::Find());
#endif
#ifdef __VALUECAN4_2_H_
findResults.push_back(ValueCAN4_2::Find());
#endif
#ifdef __VALUECAN4_2EL_ETH_H_
findResults.push_back(ValueCAN4_2EL_ETH::Find(pcapDevices));
#endif
#ifdef __VALUECAN4_2EL_USB_H_
findResults.push_back(ValueCAN4_2EL_USB::Find());
#endif
#ifdef __VALUECAN4_4_H_
findResults.push_back(ValueCAN4_4::Find());
#endif
#ifdef __VALUECAN4INDUSTRIAL_ETH_H_
findResults.push_back(ValueCAN4IndustrialETH::Find(pcapDevices));
#endif
#ifdef __VALUECAN4INDUSTRIAL_USB_H_
findResults.push_back(ValueCAN4IndustrialUSB::Find());
#endif
#ifdef __VIVIDCAN_H_
findResults.push_back(VividCAN::Find());
#endif
for(auto& results : findResults) {
if(results.size())
foundDevices.insert(foundDevices.end(), std::make_move_iterator(results.begin()), std::make_move_iterator(results.end()));
#ifdef __VIVIDCAN_H_
makeIfSerialMatches<VividCAN>(dev, foundDevices);
#endif
}
for(auto& device : foundDevices) {
@ -270,9 +160,105 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
}
const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
if(!supportedDevicesCached) {
supportedDevices.erase(std::unique(supportedDevices.begin(), supportedDevices.end()), supportedDevices.end());
supportedDevicesCached = true;
}
static std::vector<DeviceType> supportedDevices = {
#ifdef __ETHERBADGE_H_
EtherBADGE::DEVICE_TYPE,
#endif
#ifdef __NEOOBD2PRO_H_
NeoOBD2PRO::DEVICE_TYPE,
#endif
#ifdef __NEOOBD2SIM_H_
NeoOBD2SIM::DEVICE_TYPE,
#endif
#ifdef __NEOVIRED2_H_
NeoVIRED2::DEVICE_TYPE,
#endif
#ifdef __NEOVIFIRE_H_
NeoVIFIRE::DEVICE_TYPE,
#endif
#ifdef __NEOVIFIRE2_H_
NeoVIFIRE2::DEVICE_TYPE,
#endif
#ifdef __NEOVIION_H_
NeoVIION::DEVICE_TYPE,
#endif
#ifdef __NEOVIPLASMA_H_
NeoVIPLASMA::DEVICE_TYPE,
#endif
#ifdef __RADEPSILON_H_
RADEpsilon::DEVICE_TYPE,
#endif
#ifdef __RADGALAXY_H_
RADGalaxy::DEVICE_TYPE,
#endif
#ifdef __RADMARS_H_
RADMars::DEVICE_TYPE,
#endif
#ifdef __RADGIGASTAR_H_
RADGigastar::DEVICE_TYPE,
#endif
#ifdef __RADMOON2_H_
RADMoon2::DEVICE_TYPE,
#endif
#ifdef __RADMOONDUO_H_
RADMoonDuo::DEVICE_TYPE,
#endif
#ifdef __RADPLUTO_H_
RADPluto::DEVICE_TYPE,
#endif
#ifdef __RADSTAR2_H_
RADStar2::DEVICE_TYPE,
#endif
#ifdef __RADSUPERMOON_H_
RADSupermoon::DEVICE_TYPE,
#endif
#ifdef __VALUECAN3_H_
ValueCAN3::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4_1_H_
ValueCAN4_1::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4_2_H_
ValueCAN4_2::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4_2EL_H_
ValueCAN4_2EL::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4_4_H_
ValueCAN4_4::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4INDUSTRIAL_H_
ValueCAN4Industrial::DEVICE_TYPE,
#endif
#ifdef __VIVIDCAN_H_
VividCAN::DEVICE_TYPE,
#endif
};
return supportedDevices;
}

View File

@ -0,0 +1,13 @@
#include "icsneo/device/neodevice.h"
#include "icsneo/device/founddevice.h"
#include <cstring>
neodevice_t::neodevice_t() : device(nullptr), handle(0), type(0) {
memset(serial, 0, sizeof(serial));
}
neodevice_t::neodevice_t(const icsneo::FoundDevice& found, devicetype_t inType)
: device(nullptr), handle(found.handle), type(inType) {
static_assert(sizeof(found.serial) == sizeof(serial), "Serial sizes should match!");
memcpy(serial, found.serial, sizeof(serial));
}

View File

@ -26,14 +26,14 @@ namespace icsneo {
class Communication {
public:
// Note that the Packetizer is not created by the constructor,
// and should be done once the Communication module is in place.
Communication(
device_eventhandler_t report,
std::unique_ptr<Driver>&& driver,
std::function<std::unique_ptr<Packetizer>()> makeConfiguredPacketizer,
std::unique_ptr<Encoder>&& e,
std::unique_ptr<Decoder>&& md) : makeConfiguredPacketizer(makeConfiguredPacketizer), encoder(std::move(e)), decoder(std::move(md)), report(report), driver(std::move(driver)) {
packetizer = makeConfiguredPacketizer();
}
std::unique_ptr<Decoder>&& md) : makeConfiguredPacketizer(makeConfiguredPacketizer), encoder(std::move(e)), decoder(std::move(md)), driver(std::move(driver)), report(report) {}
virtual ~Communication();
bool open();
@ -77,10 +77,10 @@ public:
std::unique_ptr<Packetizer> packetizer;
std::unique_ptr<Encoder> encoder;
std::unique_ptr<Decoder> decoder;
std::unique_ptr<Driver> driver;
device_eventhandler_t report;
protected:
std::unique_ptr<Driver> driver;
static int messageCallbackIDCounter;
std::mutex messageCallbacksLock;
std::map<int, MessageCallback> messageCallbacks;

View File

@ -27,6 +27,7 @@ public:
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 write(const std::vector<uint8_t>& bytes);
virtual bool isEthernet() const { return false; }
device_eventhandler_t report;

View File

@ -61,6 +61,7 @@ public:
uint8_t hostMAC[6] = { 0x00, 0xFC, 0x70, 0xFF, 0xFF, 0xFF };
uint8_t deviceMAC[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
bool allowInPacketsFromAnyMAC = false; // Used when discovering devices
private:
bool reassembling = false;

View File

@ -7,6 +7,7 @@
#include <memory>
#include <utility>
#include <cstring>
#include <cstdint>
#include <atomic>
#include <type_traits>
#include "icsneo/api/eventmanager.h"
@ -16,6 +17,7 @@
#include "icsneo/device/nullsettings.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/device/deviceversion.h"
#include "icsneo/device/founddevice.h"
#include "icsneo/disk/diskreaddriver.h"
#include "icsneo/disk/diskwritedriver.h"
#include "icsneo/disk/nulldiskdriver.h"
@ -32,6 +34,20 @@
#include "icsneo/platform/optional.h"
#include "icsneo/platform/nodiscard.h"
#define ICSNEO_FINDABLE_DEVICE_BASE(className, type) \
static constexpr DeviceType::Enum DEVICE_TYPE = type; \
className(const FoundDevice& dev) : className(neodevice_t(dev, DEVICE_TYPE), dev.makeDriver) {}
// Devices which are discernable by the first two characters of their serial
#define ICSNEO_FINDABLE_DEVICE(className, type, serialStart) \
static constexpr const char* SERIAL_START = serialStart; \
ICSNEO_FINDABLE_DEVICE_BASE(className, type)
// Devices which are discernable by their USB PID
#define ICSNEO_FINDABLE_DEVICE_BY_PID(className, type, pid) \
static constexpr const uint16_t PRODUCT_ID = pid; \
ICSNEO_FINDABLE_DEVICE_BASE(className, type)
namespace icsneo {
class DeviceExtension;
@ -46,7 +62,6 @@ public:
uint16_t getTimestampResolution() const;
DeviceType getType() const { return DeviceType(data.type); }
uint16_t getProductId() const { return productId; }
std::string getSerial() const { return data.serial; }
uint32_t getSerialNumber() const { return Device::SerialStringToNum(getSerial()); }
const neodevice_t& getNeoDevice() const { return data; }
@ -308,7 +323,6 @@ public:
std::unique_ptr<IDeviceSettings> settings;
protected:
uint16_t productId = 0;
bool online = false;
int messagePollingCallbackID = 0;
int internalHandlerCallbackID = 0;
@ -323,21 +337,23 @@ protected:
std::array<optional<double>, 2> miscAnalog;
// START Initialization Functions
Device(neodevice_t neodevice = { 0 }) {
data = neodevice;
Device(neodevice_t neodevice) : data(neodevice) {
data.device = this;
}
template<typename Driver, typename Settings = NullSettings, typename DiskRead = Disk::NullDriver, typename DiskWrite = Disk::NullDriver>
void initialize() {
template<typename Settings = NullSettings, typename DiskRead = Disk::NullDriver, typename DiskWrite = Disk::NullDriver>
void initialize(const driver_factory_t& makeDriver) {
report = makeEventHandler();
auto driver = makeDriver<Driver>();
setupDriver(*driver);
auto encoder = makeEncoder();
setupEncoder(*encoder);
auto decoder = makeDecoder();
setupDecoder(*decoder);
com = makeCommunication(std::move(driver), std::bind(&Device::makeConfiguredPacketizer, this), std::move(encoder), std::move(decoder));
com = makeCommunication(
makeDriver(report, getWritableNeoDevice()),
std::bind(&Device::makeConfiguredPacketizer, this),
std::move(encoder),
std::move(decoder)
);
setupCommunication(*com);
settings = makeSettings<Settings>(com);
setupSettings(*settings);
@ -354,10 +370,6 @@ protected:
};
}
template<typename Driver>
std::unique_ptr<Driver> makeDriver() { return std::unique_ptr<Driver>(new Driver(report, getWritableNeoDevice())); }
virtual void setupDriver(Driver&) {}
virtual std::unique_ptr<Packetizer> makePacketizer() { return std::unique_ptr<Packetizer>(new Packetizer(report)); }
virtual void setupPacketizer(Packetizer&) {}
std::unique_ptr<Packetizer> makeConfiguredPacketizer() {
@ -377,7 +389,9 @@ protected:
std::function<std::unique_ptr<Packetizer>()> makeConfiguredPacketizer,
std::unique_ptr<Encoder> e,
std::unique_ptr<Decoder> d) { return std::make_shared<Communication>(report, std::move(t), makeConfiguredPacketizer, std::move(e), std::move(d)); }
virtual void setupCommunication(Communication&) {}
virtual void setupCommunication(Communication& communication) {
communication.packetizer = communication.makeConfiguredPacketizer();
}
template<typename Settings>
std::unique_ptr<IDeviceSettings> makeSettings(std::shared_ptr<Communication> com) {

View File

@ -0,0 +1,21 @@
#ifndef __FOUNDDEVICE_H_
#define __FOUNDDEVICE_H_
#include "icsneo/communication/driver.h"
#include "icsneo/device/neodevice.h"
namespace icsneo {
typedef std::function< std::unique_ptr<Driver>(device_eventhandler_t err, neodevice_t& forDevice) > driver_factory_t;
class FoundDevice {
public:
neodevice_handle_t handle = 0;
char serial[7] = {};
uint16_t productId = 0;
driver_factory_t makeDriver;
};
} // namespace icsneo
#endif // __FOUNDDEVICE_H_

View File

@ -9,6 +9,7 @@
namespace icsneo {
class Device;
class FoundDevice;
}
typedef icsneo::Device* devicehandle_t;
@ -20,7 +21,13 @@ typedef int32_t neodevice_handle_t;
#pragma pack(push, 1)
#ifdef __cplusplus
typedef struct neodevice_t {
neodevice_t();
neodevice_t(const icsneo::FoundDevice& found, devicetype_t inType);
#else
typedef struct {
#endif
devicehandle_t device; // Pointer back to the C++ device object
neodevice_handle_t handle; // Handle for use by the underlying driver
devicetype_t type;

View File

@ -7,7 +7,6 @@
#include "icsneo/device/devicetype.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/decoder.h"
#include "icsneo/platform/cdcacm.h"
#include "icsneo/device/tree/etherbadge/etherbadgesettings.h"
namespace icsneo {
@ -15,49 +14,35 @@ namespace icsneo {
class EtherBADGE : public Device {
public:
// Serial numbers start with EB
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::EtherBADGE;
static constexpr const uint16_t PRODUCT_ID = 0x1107;
static constexpr const char* SERIAL_START = "EB";
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(PRODUCT_ID))
found.emplace_back(new EtherBADGE(neodevice));
return found;
}
// USB PID is 0x1107, standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(EtherBADGE, DeviceType::EtherBADGE, "EB");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN,
Network::NetID::LIN,
Network::NetID::OP_Ethernet1
};
return supportedNetworks;
}
EtherBADGE(neodevice_t neodevice) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
initialize<CDCACM, EtherBADGESettings>();
protected:
EtherBADGE(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<EtherBADGESettings>(makeDriver);
}
protected:
virtual void setupEncoder(Encoder& encoder) override {
Device::setupEncoder(encoder);
encoder.supportCANFD = true;
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
bool requiresVehiclePower() const override { return false; }
};

View File

@ -5,23 +5,14 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/cdcacm.h"
namespace icsneo {
class NeoOBD2PRO : public Device {
public:
// Serial numbers are NP****
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::OBD2_PRO;
static constexpr const uint16_t PRODUCT_ID = 0x1103;
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(PRODUCT_ID))
found.emplace_back(new NeoOBD2PRO(neodevice));
return found;
}
// Serial numbers start with NP
// USB PID is 0x1103, standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(NeoOBD2PRO, DeviceType::OBD2_PRO, "NP");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
@ -32,19 +23,17 @@ public:
}
private:
NeoOBD2PRO(neodevice_t neodevice) : Device(neodevice) {
initialize<CDCACM>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
NeoOBD2PRO(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize(makeDriver);
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
bool requiresVehiclePower() const override { return false; }
};

View File

@ -5,23 +5,14 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/cdcacm.h"
namespace icsneo {
class NeoOBD2SIM : public Device {
public:
// Serial numbers are OS****
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::OBD2_SIM;
static constexpr const uint16_t PRODUCT_ID = 0x1100;
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(PRODUCT_ID))
found.emplace_back(new NeoOBD2SIM(neodevice));
return found;
}
// Serial numbers start with OS
// USB PID is 0x1100, standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(NeoOBD2SIM, DeviceType::OBD2_SIM, "OS");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
@ -32,19 +23,17 @@ public:
}
private:
NeoOBD2SIM(neodevice_t neodevice) : Device(neodevice) {
initialize<CDCACM>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
NeoOBD2SIM(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize(makeDriver);
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
bool requiresVehiclePower() const override { return false; }
};

View File

@ -5,23 +5,14 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
#include "icsneo/device/tree/neovifire/neovifiresettings.h"
namespace icsneo {
class NeoVIFIRE : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::FIRE;
static constexpr const uint16_t PRODUCT_ID = 0x0701;
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.emplace_back(new NeoVIFIRE(neodevice)); // Creation of the shared_ptr
return found;
}
// USB PID is 0x0701, standard driver is FTDI
ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIFIRE, DeviceType::FIRE, 0x0701);
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
@ -67,19 +58,17 @@ public:
}
private:
NeoVIFIRE(neodevice_t neodevice) : Device(neodevice) {
initialize<FTDI, NeoVIFIRESettings>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
NeoVIFIRE(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<NeoVIFIRESettings>(makeDriver);
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
};
}

View File

@ -5,15 +5,16 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
#include "icsneo/device/tree/neovifire2/neovifire2settings.h"
namespace icsneo {
class NeoVIFIRE2 : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::FIRE2;
static constexpr const char* SERIAL_START = "CY";
// Serial numbers start with CY
// USB PID is 0x1000, standard driver is FTDI
// Ethernet MAC allocation is 0x04, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(NeoVIFIRE2, DeviceType::FIRE2, "CY");
enum class SKU {
Standard,
@ -87,8 +88,22 @@ public:
}
protected:
NeoVIFIRE2(neodevice_t neodevice) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
NeoVIFIRE2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<NeoVIFIRE2Settings>(makeDriver);
}
void setupSettings(IDeviceSettings& ssettings) override {
if(com->driver->isEthernet()) {
// TODO Check firmware version, old firmwares will reset Ethernet settings on settings send
ssettings.readonly = true;
}
}
bool currentDriverSupportsDFU() const override { return com->driver->isEthernet(); }
void setupPacketizer(Packetizer& packetizer) override {
Device::setupPacketizer(packetizer);
packetizer.align16bit = !com->driver->isEthernet();
}
virtual void setupEncoder(Encoder& encoder) override {
@ -96,13 +111,13 @@ protected:
encoder.supportCANFD = true;
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
void handleDeviceStatus(const std::shared_ptr<RawMessage>& message) override {
if(message->data.size() < sizeof(neovifire2_status_t))

View File

@ -1,71 +0,0 @@
#ifndef __NEOVIFIRE2ETH_H_
#define __NEOVIFIRE2ETH_H_
#ifdef __cplusplus
#include "icsneo/device/tree/neovifire2/neovifire2.h"
#include "icsneo/platform/pcap.h"
#include <memory>
namespace icsneo {
class NeoVIFIRE2ETH : public NeoVIFIRE2 {
public:
static constexpr const uint16_t PRODUCT_ID = 0x0004;
static std::vector<std::shared_ptr<Device>> Find(const std::vector<PCAP::PCAPFoundDevice>& pcapDevices) {
std::vector<std::shared_ptr<Device>> found;
for(auto& foundDev : pcapDevices) {
auto fakedev = std::shared_ptr<NeoVIFIRE2ETH>(new NeoVIFIRE2ETH({}));
for (auto& payload : foundDev.discoveryPackets)
fakedev->com->packetizer->input(payload);
for (auto& packet : fakedev->com->packetizer->output()) {
std::shared_ptr<Message> msg;
if (!fakedev->com->decoder->decode(msg, packet))
continue; // We failed to decode this packet
if(!msg || msg->type != Message::Type::Main51)
continue; // Not a message we care about
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
if(!sn)
continue; // Not a serial number message
if(sn->deviceSerial.length() < 2)
continue;
if(sn->deviceSerial.substr(0, 2) != SERIAL_START)
continue; // Not a FIRE 2
auto device = foundDev.device;
device.serial[sn->deviceSerial.copy(device.serial, sizeof(device.serial))] = '\0';
found.push_back(std::make_shared<NeoVIFIRE2ETH>(std::move(device)));
break;
}
}
return found;
}
NeoVIFIRE2ETH(neodevice_t neodevice) : NeoVIFIRE2(neodevice) {
initialize<PCAP, NeoVIFIRE2Settings>();
productId = PRODUCT_ID;
}
bool currentDriverSupportsDFU() const override { return false; }
protected:
void setupSettings(IDeviceSettings& ssettings) override {
// TODO Check firmware version, old firmwares will reset Ethernet settings on settings send
ssettings.readonly = true;
}
void setupPacketizer(Packetizer& packetizer) override {
NeoVIFIRE2::setupPacketizer(packetizer);
packetizer.align16bit = false;
}
};
}
#endif // __cplusplus
#endif

View File

@ -1,34 +0,0 @@
#ifndef __NEOVIFIRE2USB_H_
#define __NEOVIFIRE2USB_H_
#ifdef __cplusplus
#include "icsneo/device/tree/neovifire2/neovifire2.h"
#include "icsneo/platform/ftdi.h"
namespace icsneo {
class NeoVIFIRE2USB : public NeoVIFIRE2 {
public:
static constexpr const uint16_t PRODUCT_ID = 0x1000;
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.emplace_back(new NeoVIFIRE2USB(neodevice)); // Creation of the shared_ptr
return found;
}
private:
NeoVIFIRE2USB(neodevice_t neodevice) : NeoVIFIRE2(neodevice) {
initialize<FTDI, NeoVIFIRE2Settings>();
productId = PRODUCT_ID;
}
};
}
#endif // __cplusplus
#endif

View File

@ -3,7 +3,6 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/pcap.h"
#include "icsneo/disk/extextractordiskreaddriver.h"
#include "icsneo/disk/neomemorydiskdriver.h"
#include "icsneo/device/tree/neovired2/neovired2settings.h"
@ -12,41 +11,9 @@ namespace icsneo {
class NeoVIRED2 : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RED2;
static constexpr const char* SERIAL_START = "D2";
static constexpr const uint16_t PRODUCT_ID = 0x000E;
static std::vector<std::shared_ptr<Device>> Find(const std::vector<PCAP::PCAPFoundDevice>& pcapDevices) {
std::vector<std::shared_ptr<Device>> found;
for(auto& foundDev : pcapDevices) {
auto fakedev = std::shared_ptr<NeoVIRED2>(new NeoVIRED2({}));
for (auto& payload : foundDev.discoveryPackets)
fakedev->com->packetizer->input(payload);
for (auto& packet : fakedev->com->packetizer->output()) {
std::shared_ptr<Message> msg;
if (!fakedev->com->decoder->decode(msg, packet))
continue; // We failed to decode this packet
if(!msg || msg->type != Message::Type::Main51)
continue; // Not a message we care about
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
if(!sn)
continue; // Not a serial number message
if(sn->deviceSerial.length() < 2)
continue;
if(sn->deviceSerial.substr(0, 2) != SERIAL_START)
continue; // Not a RED 2
auto device = foundDev.device;
device.serial[sn->deviceSerial.copy(device.serial, sizeof(device.serial))] = '\0';
found.emplace_back(new NeoVIRED2(std::move(device)));
break;
}
}
return found;
}
// Serial numbers start with D2
// Ethernet MAC allocation is 0x0E, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(NeoVIRED2, DeviceType::RED2, "D2");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
@ -68,10 +35,8 @@ public:
}
protected:
NeoVIRED2(neodevice_t neodevice) : Device(neodevice) {
initialize<PCAP, NeoVIRED2Settings, Disk::ExtExtractorDiskReadDriver, Disk::NeoMemoryDiskDriver>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
NeoVIRED2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<NeoVIRED2Settings, Disk::ExtExtractorDiskReadDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
}
virtual void setupEncoder(Encoder& encoder) override {
@ -84,13 +49,13 @@ protected:
packetizer.align16bit = false;
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
};
}

View File

@ -5,7 +5,6 @@
#include "icsneo/device/tree/plasion/plasion.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
#include "icsneo/disk/plasiondiskreaddriver.h"
#include "icsneo/disk/neomemorydiskdriver.h"
@ -13,22 +12,12 @@ namespace icsneo {
class NeoVIION : public Plasion {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::ION;
static constexpr const uint16_t PRODUCT_ID = 0x0901;
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.emplace_back(new NeoVIION(neodevice));
return found;
}
// USB PID is 0x0901, standard driver is FTDI
ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIION, DeviceType::ION, 0x0901);
private:
NeoVIION(neodevice_t neodevice) : Plasion(neodevice) {
initialize<FTDI, NullSettings, Disk::PlasionDiskReadDriver, Disk::NeoMemoryDiskDriver>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
NeoVIION(neodevice_t neodevice, const driver_factory_t& makeDriver) : Plasion(neodevice) {
initialize<NullSettings, Disk::PlasionDiskReadDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
}
virtual std::shared_ptr<Communication> makeCommunication(

View File

@ -5,28 +5,17 @@
#include "icsneo/device/tree/plasion/plasion.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
namespace icsneo {
class NeoVIPLASMA : public Plasion {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::PLASMA;
static constexpr const uint16_t PRODUCT_ID = 0x0801;
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.emplace_back(new NeoVIPLASMA(neodevice));
return found;
}
// USB PID is 0x0801, standard driver is FTDI
ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIPLASMA, DeviceType::PLASMA, 0x0801);
private:
NeoVIPLASMA(neodevice_t neodevice) : Plasion(neodevice) {
initialize<FTDI>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
NeoVIPLASMA(neodevice_t neodevice, const driver_factory_t& makeDriver) : Plasion(neodevice) {
initialize<NullSettings, Disk::PlasionDiskReadDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
}
virtual std::shared_ptr<Communication> makeCommunication(

View File

@ -5,7 +5,6 @@
#include "icsneo/device/device.h"
#include "icsneo/communication/multichannelcommunication.h"
#include "icsneo/platform/ftdi.h"
#include "icsneo/device/extensions/flexray/extension.h"
namespace icsneo {
@ -45,6 +44,8 @@ public:
size_t getEthernetActivationLineCount() const override { return 1; }
protected:
using Device::Device;
// TODO This is done so that Plasion can still transmit it's basic networks, awaiting slave VNET support
virtual bool isSupportedRXNetwork(const Network&) const override { return true; }
virtual bool isSupportedTXNetwork(const Network&) const override { return true; }
@ -55,7 +56,7 @@ protected:
addExtension(std::make_shared<FlexRay::Extension>(*this, flexRayControllers));
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
// TODO Check configuration for FlexRay ColdStart mode, disable FlexRay 2 if so
@ -87,9 +88,6 @@ protected:
const fire2vnet_status_t* status = reinterpret_cast<const fire2vnet_status_t*>(message->data.data());
ethActivationStatus = status->ethernetActivationLineEnabled;
}
public:
Plasion(neodevice_t neodevice) : Device(neodevice) {}
};
}

View File

@ -3,23 +3,14 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/cdcacm.h"
namespace icsneo {
class RADEpsilon : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADEpsilon;
static constexpr const char* SERIAL_START = "RE";
static constexpr const uint16_t PRODUCT_ID = 0x1109;
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(PRODUCT_ID))
found.emplace_back(new RADEpsilon(neodevice));
return found;
}
// Serial numbers start with RE
// USB PID is 0x1109, standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(RADEpsilon, DeviceType::RADEpsilon, "RE");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
@ -34,10 +25,8 @@ public:
}
protected:
RADEpsilon(neodevice_t neodevice) : Device(neodevice) {
initialize<CDCACM>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
RADEpsilon(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize(makeDriver);
}
virtual void setupEncoder(Encoder& encoder) override {
@ -45,13 +34,13 @@ protected:
encoder.supportCANFD = true;
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
};
}

View File

@ -5,7 +5,6 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/platform/pcap.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/decoder.h"
#include "icsneo/device/tree/radgalaxy/radgalaxysettings.h"
@ -15,41 +14,8 @@ namespace icsneo {
class RADGalaxy : public Device {
public:
// Serial numbers start with RG
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADGalaxy;
static constexpr const uint16_t PRODUCT_ID = 0x0003;
static constexpr const char* SERIAL_START = "RG";
static std::vector<std::shared_ptr<Device>> Find(const std::vector<PCAP::PCAPFoundDevice>& pcapDevices) {
std::vector<std::shared_ptr<Device>> found;
for(auto& foundDev : pcapDevices) {
auto fakedev = std::shared_ptr<RADGalaxy>(new RADGalaxy({}));
for(auto& payload : foundDev.discoveryPackets)
fakedev->com->packetizer->input(payload);
for(auto& packet : fakedev->com->packetizer->output()) {
std::shared_ptr<Message> msg;
if(!fakedev->com->decoder->decode(msg, packet))
continue; // We failed to decode this packet
if(!msg || msg->type != Message::Type::Main51)
continue; // Not a message we care about
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
if(!sn)
continue; // Not a serial number message
if(sn->deviceSerial.length() < 2)
continue;
if(sn->deviceSerial.substr(0, 2) != SERIAL_START)
continue; // Not a RADGalaxy
auto device = foundDev.device;
device.serial[sn->deviceSerial.copy(device.serial, sizeof(device.serial))] = '\0';
found.emplace_back(new RADGalaxy(std::move(device)));
break;
}
}
return found;
}
// Ethernet MAC allocation is 0x03, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADGalaxy, DeviceType::RADGalaxy, "RG");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
@ -85,15 +51,13 @@ public:
return supportedNetworks;
}
RADGalaxy(neodevice_t neodevice) : Device(neodevice) {
initialize<PCAP, RADGalaxySettings>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
size_t getEthernetActivationLineCount() const override { return 1; }
protected:
RADGalaxy(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADGalaxySettings>(makeDriver);
}
void setupPacketizer(Packetizer& packetizer) override {
Device::setupPacketizer(packetizer);
packetizer.disableChecksum = true;

View File

@ -11,16 +11,18 @@ namespace icsneo {
class RADGigastar : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADGigastar;
static constexpr const char* SERIAL_START = "GS";
// Serial numbers start with GS
// USB PID is 0x1204, standard driver is FTDI3
// Ethernet MAC allocation is 0x0F, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADGigastar, DeviceType::RADGigastar, "GS");
size_t getEthernetActivationLineCount() const override { return 1; }
bool getEthPhyRegControlSupported() const override { return true; }
protected:
RADGigastar(neodevice_t neodevice) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
RADGigastar(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADGigastarSettings>(makeDriver);
}
void setupPacketizer(Packetizer& packetizer) override {

View File

@ -1,58 +0,0 @@
#ifndef __RADGIGASTAR_ETH_H_
#define __RADGIGASTAR_ETH_H_
#ifdef __cplusplus
#include "icsneo/device/tree/radgigastar/radgigastar.h"
#include "icsneo/platform/pcap.h"
namespace icsneo {
class RADGigastarETH : public RADGigastar {
public:
static constexpr const uint16_t PRODUCT_ID = 0x000F;
static std::vector<std::shared_ptr<Device>> Find(const std::vector<PCAP::PCAPFoundDevice>& pcapDevices) {
std::vector<std::shared_ptr<Device>> found;
for(auto& foundDev : pcapDevices) {
auto fakedev = std::shared_ptr<RADGigastarETH>(new RADGigastarETH({}));
for (auto& payload : foundDev.discoveryPackets)
fakedev->com->packetizer->input(payload);
for (auto& packet : fakedev->com->packetizer->output()) {
std::shared_ptr<Message> msg;
if (!fakedev->com->decoder->decode(msg, packet))
continue; // We failed to decode this packet
if(!msg || msg->type != Message::Type::Main51)
continue; // Not a message we care about
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
if(!sn)
continue; // Not a serial number message
if(sn->deviceSerial.length() < 2)
continue;
if(sn->deviceSerial.substr(0, 2) != SERIAL_START)
continue; // Not a RADGigastar
auto device = foundDev.device;
device.serial[sn->deviceSerial.copy(device.serial, sizeof(device.serial))] = '\0';
found.push_back(std::shared_ptr<RADGigastarETH>(new RADGigastarETH(std::move(device))));
break;
}
}
return found;
}
private:
RADGigastarETH(neodevice_t neodevice) : RADGigastar(neodevice) {
initialize<PCAP, RADGigastarSettings>();
productId = PRODUCT_ID;
}
};
}
#endif // __cplusplus
#endif

View File

@ -1,34 +0,0 @@
#ifndef __RADGIGASTAR_USB_H_
#define __RADGIGASTAR_USB_H_
#ifdef __cplusplus
#include "icsneo/device/tree/radgigastar/radgigastar.h"
#include "icsneo/platform/ftdi3.h"
namespace icsneo {
class RADGigastarUSB : public RADGigastar {
public:
static constexpr const uint16_t PRODUCT_ID = 0x1204;
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI3::FindByProduct(PRODUCT_ID))
found.emplace_back(new RADGigastarUSB(neodevice)); // Creation of the shared_ptr
return found;
}
private:
RADGigastarUSB(neodevice_t neodevice) : RADGigastar(neodevice) {
initialize<FTDI3, RADGigastarSettings>();
productId = PRODUCT_ID;
}
};
}
#endif // __cplusplus
#endif

View File

@ -11,14 +11,16 @@ namespace icsneo {
class RADMars : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADMars;
static constexpr const char* SERIAL_START = "GL";
// Serial numbers start with GL (previously, RAD-Gigalog)
// USB PID is 0x1203, standard driver is FTDI3
// Ethernet MAC allocation is 0x0A, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADMars, DeviceType::RADMars, "GL");
size_t getEthernetActivationLineCount() const override { return 1; }
protected:
RADMars(neodevice_t neodevice) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
RADMars(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADMarsSettings>(makeDriver);
}
void setupPacketizer(Packetizer& packetizer) override {

View File

@ -1,58 +0,0 @@
#ifndef __RADMARS_ETH_H_
#define __RADMARS_ETH_H_
#ifdef __cplusplus
#include "icsneo/device/tree/radmars/radmars.h"
#include "icsneo/platform/pcap.h"
namespace icsneo {
class RADMarsETH : public RADMars {
public:
static constexpr const uint16_t PRODUCT_ID = 0x000A;
static std::vector<std::shared_ptr<Device>> Find(const std::vector<PCAP::PCAPFoundDevice>& pcapDevices) {
std::vector<std::shared_ptr<Device>> found;
for(auto& foundDev : pcapDevices) {
auto fakedev = std::shared_ptr<RADMarsETH>(new RADMarsETH({}));
for (auto& payload : foundDev.discoveryPackets)
fakedev->com->packetizer->input(payload);
for (auto& packet : fakedev->com->packetizer->output()) {
std::shared_ptr<Message> msg;
if (!fakedev->com->decoder->decode(msg, packet))
continue; // We failed to decode this packet
if(!msg || msg->type != Message::Type::Main51)
continue; // Not a message we care about
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
if(!sn)
continue; // Not a serial number message
if(sn->deviceSerial.length() < 2)
continue;
if(sn->deviceSerial.substr(0, 2) != SERIAL_START)
continue; // Not a RAD-Mars
auto device = foundDev.device;
device.serial[sn->deviceSerial.copy(device.serial, sizeof(device.serial))] = '\0';
found.push_back(std::shared_ptr<RADMarsETH>(new RADMarsETH(std::move(device))));
break;
}
}
return found;
}
private:
RADMarsETH(neodevice_t neodevice) : RADMars(neodevice) {
initialize<PCAP, RADMarsSettings>();
productId = PRODUCT_ID;
}
};
}
#endif // __cplusplus
#endif

View File

@ -1,34 +0,0 @@
#ifndef __RADMARS_USB_H_
#define __RADMARS_USB_H_
#ifdef __cplusplus
#include "icsneo/device/tree/radmars/radmars.h"
#include "icsneo/platform/ftdi3.h"
namespace icsneo {
class RADMarsUSB : public RADMars {
public:
static constexpr const uint16_t PRODUCT_ID = 0x1203;
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI3::FindByProduct(PRODUCT_ID))
found.emplace_back(new RADMarsUSB(neodevice)); // Creation of the shared_ptr
return found;
}
private:
RADMarsUSB(neodevice_t neodevice) : RADMars(neodevice) {
initialize<FTDI3, RADMarsSettings>();
productId = PRODUCT_ID;
}
};
}
#endif // __cplusplus
#endif

View File

@ -6,15 +6,14 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/radmoon2/radmoon2settings.h"
#include "icsneo/platform/ftdi3.h"
namespace icsneo {
class RADMoon2 : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADMoon2;
static constexpr const uint16_t PRODUCT_ID = 0x1202;
static constexpr const char* SERIAL_START = "RM";
// Serial numbers start with RM
// USB PID is 0x1202, standard driver is FTDI3
ICSNEO_FINDABLE_DEVICE(RADMoon2, DeviceType::RADMoon2, "RM");
enum class SKU {
Standard,
@ -22,15 +21,6 @@ public:
APM1000E_CLK, // Clock Option and Keysight Branding
};
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI3::FindByProduct(PRODUCT_ID))
found.emplace_back(new RADMoon2(neodevice));
return found;
}
SKU getSKU() const {
switch(getSerial().back()) {
case 'A':
@ -70,10 +60,8 @@ public:
bool getEthPhyRegControlSupported() const override { return true; }
protected:
RADMoon2(neodevice_t neodevice) : Device(neodevice) {
initialize<FTDI3, RADMoon2Settings>();
productId = PRODUCT_ID;
getWritableNeoDevice().type = DEVICE_TYPE;
RADMoon2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADMoon2Settings>(makeDriver);
}
void setupPacketizer(Packetizer& packetizer) override {

View File

@ -6,24 +6,14 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/radmoonduo/radmoonduosettings.h"
#include "icsneo/platform/cdcacm.h"
namespace icsneo {
class RADMoonDuo : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADMoonDuo;
static constexpr const uint16_t PRODUCT_ID = 0x1106;
static constexpr const char* SERIAL_START = "MD";
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(PRODUCT_ID))
found.emplace_back(new RADMoonDuo(neodevice));
return found;
}
// Serial numbers start with MD
// USB PID is 1106, standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(RADMoonDuo, DeviceType::RADMoonDuo, "MD");
static const std::vector<Network>& GetSupportedNetworks() {
// If Converter1 Target is set to USB/CM, OP_Ethernet2 will be exposed to the PC
@ -36,10 +26,8 @@ public:
bool getEthPhyRegControlSupported() const override { return true; }
protected:
RADMoonDuo(neodevice_t neodevice) : Device(neodevice) {
initialize<CDCACM, RADMoonDuoSettings>();
productId = PRODUCT_ID;
getWritableNeoDevice().type = DEVICE_TYPE;
RADMoonDuo(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADMoonDuoSettings>(makeDriver);
}
virtual void setupEncoder(Encoder& encoder) override {

View File

@ -5,8 +5,6 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/decoder.h"
#include "icsneo/device/tree/radpluto/radplutosettings.h"
namespace icsneo {
@ -14,9 +12,8 @@ namespace icsneo {
class RADPluto : public Device {
public:
// Serial numbers start with PL
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADPluto;
static constexpr const uint16_t PRODUCT_ID = 0x1104;
static constexpr const char* SERIAL_START = "PL";
// USB PID is 1104, standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(RADPluto, DeviceType::RADPluto, "PL");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
@ -35,27 +32,26 @@ public:
return supportedNetworks;
}
RADPluto(neodevice_t neodevice) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
bool getEthPhyRegControlSupported() const override { return true; }
protected:
RADPluto(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADPlutoSettings>(makeDriver);
}
virtual void setupEncoder(Encoder& encoder) override {
Device::setupEncoder(encoder);
encoder.supportCANFD = true;
encoder.supportEthPhy = true;
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
bool requiresVehiclePower() const override { return false; }
};

View File

@ -1,33 +0,0 @@
#ifndef __RADPLUTOUSB_H_
#define __RADPLUTOUSB_H_
#ifdef __cplusplus
#include "icsneo/device/tree/radpluto/radpluto.h"
#include "icsneo/platform/cdcacm.h"
namespace icsneo {
class RADPlutoUSB : public RADPluto {
public:
// Serial numbers start with RP
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(PRODUCT_ID))
found.emplace_back(new RADPlutoUSB(neodevice));
return found;
}
private:
RADPlutoUSB(neodevice_t neodevice) : RADPluto(neodevice) {
initialize<CDCACM, RADPlutoSettings>();
}
};
}
#endif // __cplusplus
#endif

View File

@ -12,9 +12,9 @@ namespace icsneo {
class RADStar2 : public Device {
public:
// Serial numbers start with RS
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADStar2;
static constexpr const uint16_t PRODUCT_ID = 0x0005;
static constexpr const char* SERIAL_START = "RS";
// USB PID is 0x0005, standard driver is FTDI
// Ethernet MAC allocation is 0x05, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADStar2, DeviceType::RADStar2, "RS");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
@ -30,6 +30,10 @@ public:
}
protected:
RADStar2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADStar2Settings>(makeDriver);
}
virtual void setupPacketizer(Packetizer& packetizer) override {
Device::setupPacketizer(packetizer);
packetizer.disableChecksum = true;
@ -46,18 +50,13 @@ protected:
decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
RADStar2(neodevice_t neodevice) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
};
}

View File

@ -1,58 +0,0 @@
#ifndef __RADSTAR2ETH_H_
#define __RADSTAR2ETH_H_
#ifdef __cplusplus
#include "icsneo/device/tree/radstar2/radstar2.h"
#include "icsneo/communication/network.h"
#include "icsneo/communication/message/serialnumbermessage.h"
#include "icsneo/platform/pcap.h"
namespace icsneo {
class RADStar2ETH : public RADStar2 {
public:
// Serial numbers start with RS
static std::vector<std::shared_ptr<Device>> Find(const std::vector<PCAP::PCAPFoundDevice>& pcapDevices) {
std::vector<std::shared_ptr<Device>> found;
for(auto& foundDev : pcapDevices) {
auto fakedev = std::shared_ptr<RADStar2ETH>(new RADStar2ETH({}));
for(auto& payload : foundDev.discoveryPackets)
fakedev->com->packetizer->input(payload);
for(auto& packet : fakedev->com->packetizer->output()) {
std::shared_ptr<Message> msg;
if(!fakedev->com->decoder->decode(msg, packet))
continue; // We failed to decode this packet
if(!msg || msg->type != Message::Type::Main51)
continue; // Not a message we care about
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
if(!sn)
continue; // Not a serial number message
if(sn->deviceSerial.length() < 2)
continue;
if(sn->deviceSerial.substr(0, 2) != SERIAL_START)
continue; // Not a RADStar2
auto device = foundDev.device;
device.serial[sn->deviceSerial.copy(device.serial, sizeof(device.serial))] = '\0';
found.push_back(std::make_shared<RADStar2ETH>(device));
break;
}
}
return found;
}
RADStar2ETH(neodevice_t neodevice) : RADStar2(neodevice) {
initialize<PCAP, RADStar2Settings>();
}
};
}
#endif // __cplusplus
#endif

View File

@ -1,33 +0,0 @@
#ifndef __RADSTAR2USB_H_
#define __RADSTAR2USB_H_
#ifdef __cplusplus
#include "icsneo/device/tree/radstar2/radstar2.h"
#include "icsneo/platform/ftdi.h"
namespace icsneo {
class RADStar2USB : public RADStar2 {
public:
// Serial numbers start with RS
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.emplace_back(new RADStar2USB(neodevice));
return found;
}
private:
RADStar2USB(neodevice_t neodevice) : RADStar2(neodevice) {
initialize<FTDI, RADStar2Settings>();
}
};
}
#endif // __cplusplus
#endif

View File

@ -6,30 +6,20 @@
#include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/radsupermoon/radsupermoonsettings.h"
#include "icsneo/platform/ftdi3.h"
namespace icsneo {
class RADSupermoon : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADSupermoon;
static constexpr const uint16_t PRODUCT_ID = 0x1201;
static constexpr const char* SERIAL_START = "SM";
// Serial numbers start with SM
// USB PID is 0x1201, standard driver is FTDI3
ICSNEO_FINDABLE_DEVICE(RADSupermoon, DeviceType::RADSupermoon, "SM");
enum class SKU {
Standard,
APM1000ET, // Keysight Branding
};
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI3::FindByProduct(PRODUCT_ID))
found.emplace_back(new RADSupermoon(neodevice));
return found;
}
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::Ethernet,
@ -60,10 +50,8 @@ public:
bool getEthPhyRegControlSupported() const override { return true; }
protected:
RADSupermoon(neodevice_t neodevice) : Device(neodevice) {
initialize<FTDI3, RADSupermoonSettings>();
productId = PRODUCT_ID;
getWritableNeoDevice().type = DEVICE_TYPE;
RADSupermoon(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADSupermoonSettings>(makeDriver);
}
void setupPacketizer(Packetizer& packetizer) override {

View File

@ -12,16 +12,8 @@ namespace icsneo {
class ValueCAN3 : public Device {
public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN3;
static constexpr const uint16_t PRODUCT_ID = 0x0601;
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : FTDI::FindByProduct(PRODUCT_ID))
found.emplace_back(new ValueCAN3(neodevice));
return found;
}
// USB PID is 0x0601, standard driver is FTDI
ICSNEO_FINDABLE_DEVICE_BY_PID(ValueCAN3, DeviceType::VCAN3, 0x0701);
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
@ -32,19 +24,17 @@ public:
}
private:
ValueCAN3(neodevice_t neodevice) : Device(neodevice) {
initialize<FTDI, ValueCAN3Settings>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
ValueCAN3(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<ValueCAN3Settings>(makeDriver);
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
bool requiresVehiclePower() const override { return false; }
};

View File

@ -5,27 +5,14 @@
#include "icsneo/device/tree/valuecan4/valuecan4.h"
#include "icsneo/device/tree/valuecan4/settings/valuecan4-1settings.h"
#include "icsneo/platform/cdcacm.h"
#include <string>
namespace icsneo {
class ValueCAN4_1 : public ValueCAN4 {
public:
// Serial numbers start with V1 for 4-1
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_1;
static constexpr const char* SERIAL_START = "V1";
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(USB_PRODUCT_ID)) {
if(std::string(neodevice.serial).substr(0, 2) == SERIAL_START)
found.emplace_back(new ValueCAN4_1(neodevice));
}
return found;
}
// USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(ValueCAN4_1, DeviceType::VCAN4_1, "V1");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
@ -35,25 +22,22 @@ public:
}
protected:
ValueCAN4_1(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
initialize<ValueCAN4_1Settings>(makeDriver);
}
void setupEncoder(Encoder& encoder) override {
ValueCAN4::setupEncoder(encoder);
encoder.supportCANFD = false; // VCAN 4-1 does not support CAN FD
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
private:
ValueCAN4_1(neodevice_t neodevice) : ValueCAN4(neodevice) {
initialize<CDCACM, ValueCAN4_1Settings>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = USB_PRODUCT_ID;
}
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
};
}

View File

@ -5,33 +5,20 @@
#include "icsneo/device/tree/valuecan4/valuecan4.h"
#include "icsneo/device/tree/valuecan4/settings/valuecan4-2settings.h"
#include "icsneo/platform/cdcacm.h"
#include <string>
namespace icsneo {
class ValueCAN4_2 : public ValueCAN4 {
public:
// Serial numbers start with V2 for 4-2
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_2;
static constexpr const char* SERIAL_START = "V2";
// USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(ValueCAN4_2, DeviceType::VCAN4_2, "V2");
enum class SKU {
Standard,
AP0200A, // USB A and Keysight Branding
};
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(USB_PRODUCT_ID)) {
if(std::string(neodevice.serial).substr(0, 2) == SERIAL_START)
found.emplace_back(new ValueCAN4_2(neodevice));
}
return found;
}
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN,
@ -60,20 +47,17 @@ public:
}
protected:
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
ValueCAN4_2(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
initialize<ValueCAN4_2Settings>(makeDriver);
}
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
private:
ValueCAN4_2(neodevice_t neodevice) : ValueCAN4(neodevice) {
initialize<CDCACM, ValueCAN4_2Settings>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = USB_PRODUCT_ID;
}
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
};
}

View File

@ -5,15 +5,15 @@
#include "icsneo/device/tree/valuecan4/valuecan4.h"
#include "icsneo/device/tree/valuecan4/settings/valuecan4-2elsettings.h"
#include <string>
namespace icsneo {
class ValueCAN4_2EL : public ValueCAN4 {
public:
// Serial numbers start with VE for 4-2EL
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_2EL;
static constexpr const char* SERIAL_START = "VE";
// USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
// Ethernet MAC allocation is 0x0B, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(ValueCAN4_2EL, DeviceType::VCAN4_2EL, "VE");
enum class SKU {
Standard,
@ -53,14 +53,16 @@ public:
Network::NetID::HSCAN,
Network::NetID::HSCAN2,
Network::NetID::Ethernet
Network::NetID::Ethernet,
Network::NetID::LIN
};
return supportedNetworks;
}
protected:
ValueCAN4_2EL(neodevice_t neodevice) : ValueCAN4(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
ValueCAN4_2EL(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
initialize<ValueCAN4_2ELSettings>(makeDriver);
}
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
@ -80,6 +82,13 @@ protected:
const valuecan4_2el_status_t* status = reinterpret_cast<const valuecan4_2el_status_t*>(message->data.data());
ethActivationStatus = status->ethernetActivationLineEnabled;
}
bool currentDriverSupportsDFU() const override { return com->driver->isEthernet(); }
void setupPacketizer(Packetizer& packetizer) override {
ValueCAN4::setupPacketizer(packetizer);
packetizer.align16bit = !com->driver->isEthernet();
}
};
}

View File

@ -1,68 +0,0 @@
#ifndef __VALUECAN4_2EL_ETH_H_
#define __VALUECAN4_2EL_ETH_H_
#ifdef __cplusplus
#include "icsneo/device/tree/valuecan4/valuecan4-2el.h"
#include "icsneo/platform/pcap.h"
#include <string>
namespace icsneo {
class ValueCAN4_2EL_ETH : public ValueCAN4_2EL {
public:
static constexpr const uint16_t ETH_PRODUCT_ID = 0x000B;
static std::vector<std::shared_ptr<Device>> Find(const std::vector<PCAP::PCAPFoundDevice>& pcapDevices) {
std::vector<std::shared_ptr<Device>> found;
for(auto& foundDev : pcapDevices) {
auto fakedev = std::shared_ptr<ValueCAN4_2EL_ETH>(new ValueCAN4_2EL_ETH({}));
for (auto& payload : foundDev.discoveryPackets)
fakedev->com->packetizer->input(payload);
for (auto& packet : fakedev->com->packetizer->output()) {
std::shared_ptr<Message> msg;
if (!fakedev->com->decoder->decode(msg, packet))
continue; // We failed to decode this packet
if(!msg || msg->type != Message::Type::Main51)
continue; // Not a message we care about
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
if(!sn)
continue; // Not a serial number message
if(sn->deviceSerial.length() < 2)
continue;
if(sn->deviceSerial.substr(0, 2) != SERIAL_START)
continue; // Not a ValueCAN4-2EL
auto device = foundDev.device;
device.serial[sn->deviceSerial.copy(device.serial, sizeof(device.serial))] = '\0';
found.push_back(std::shared_ptr<ValueCAN4_2EL_ETH>(new ValueCAN4_2EL_ETH(std::move(device))));
break;
}
}
return found;
}
bool currentDriverSupportsDFU() const override { return false; }
protected:
void setupPacketizer(Packetizer& packetizer) override {
ValueCAN4_2EL::setupPacketizer(packetizer);
packetizer.align16bit = false;
}
private:
ValueCAN4_2EL_ETH(neodevice_t neodevice) : ValueCAN4_2EL(neodevice) {
initialize<PCAP, ValueCAN4_2ELSettings>();
productId = ETH_PRODUCT_ID;
}
};
}
#endif // __cplusplus
#endif

View File

@ -1,36 +0,0 @@
#ifndef __VALUECAN4_2EL_USB_H_
#define __VALUECAN4_2EL_USB_H_
#ifdef __cplusplus
#include "icsneo/device/tree/valuecan4/valuecan4-2el.h"
#include "icsneo/platform/cdcacm.h"
#include <string>
namespace icsneo {
class ValueCAN4_2EL_USB : public ValueCAN4_2EL {
public:
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(USB_PRODUCT_ID)) {
if(std::string(neodevice.serial).substr(0, 2) == SERIAL_START)
found.emplace_back(new ValueCAN4_2EL_USB(neodevice));
}
return found;
}
private:
ValueCAN4_2EL_USB(neodevice_t neodevice) : ValueCAN4_2EL(neodevice) {
initialize<CDCACM, ValueCAN4_2ELSettings>();
productId = USB_PRODUCT_ID;
}
};
}
#endif // __cplusplus
#endif

View File

@ -5,16 +5,14 @@
#include "icsneo/device/tree/valuecan4/valuecan4.h"
#include "icsneo/device/tree/valuecan4/settings/valuecan4-4settings.h"
#include "icsneo/platform/cdcacm.h"
#include <string>
namespace icsneo {
class ValueCAN4_4 : public ValueCAN4 {
public:
// Serial numbers start with V4 for 4-4
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_4;
static constexpr const char* SERIAL_START = "V4";
// USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(ValueCAN4_4, DeviceType::VCAN4_4, "V4");
enum class SKU {
Standard,
@ -23,17 +21,6 @@ public:
AP0400A_OBD, // OBD, USB A, and Keysight Branding
};
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(USB_PRODUCT_ID)) {
if(std::string(neodevice.serial).substr(0, 2) == SERIAL_START)
found.emplace_back(new ValueCAN4_4(neodevice));
}
return found;
}
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN,
@ -71,20 +58,17 @@ public:
}
protected:
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
ValueCAN4_4(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
initialize<ValueCAN4_4Settings>(makeDriver);
}
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
private:
ValueCAN4_4(neodevice_t neodevice) : ValueCAN4(neodevice) {
initialize<CDCACM, ValueCAN4_4Settings>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = USB_PRODUCT_ID;
}
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
};
}

View File

@ -10,17 +10,16 @@ namespace icsneo {
class ValueCAN4 : public Device {
public:
// All ValueCAN 4 devices share a USB PID
static constexpr const uint16_t USB_PRODUCT_ID = 0x1101;
// All ValueCAN 4 devices share a USB PID of 0x1101
protected:
using Device::Device;
virtual void setupEncoder(Encoder& encoder) override {
Device::setupEncoder(encoder);
encoder.supportCANFD = true;
}
ValueCAN4(neodevice_t neodevice) : Device(neodevice) {}
bool requiresVehiclePower() const override { return false; }
};

View File

@ -11,12 +11,40 @@ namespace icsneo {
class ValueCAN4Industrial : public ValueCAN4 {
public:
// Serial numbers start with IV for Industrial
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_IND;
static constexpr const char* SERIAL_START = "IV";
// USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
// Ethernet MAC allocation is 0x12, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(ValueCAN4Industrial, DeviceType::VCAN4_IND, "IV");
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN,
Network::NetID::HSCAN2,
Network::NetID::Ethernet,
Network::NetID::LIN
};
return supportedNetworks;
}
protected:
ValueCAN4Industrial(neodevice_t neodevice) : ValueCAN4(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
ValueCAN4Industrial(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
initialize<ValueCAN4IndustrialSettings>(makeDriver);
}
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
bool currentDriverSupportsDFU() const override { return com->driver->isEthernet(); }
void setupPacketizer(Packetizer& packetizer) override {
ValueCAN4::setupPacketizer(packetizer);
packetizer.align16bit = !com->driver->isEthernet();
}
};

View File

@ -1,85 +0,0 @@
#ifndef __VALUECAN4INDUSTRIAL_ETH_H_
#define __VALUECAN4INDUSTRIAL_ETH_H_
#ifdef __cplusplus
#include "icsneo/device/tree/valuecan4/valuecan4industrial.h"
#include "icsneo/platform/pcap.h"
#include <string>
namespace icsneo {
class ValueCAN4IndustrialETH : public ValueCAN4Industrial {
public:
static constexpr const uint16_t ETH_PRODUCT_ID = 0x0012;
static std::vector<std::shared_ptr<Device>> Find(const std::vector<PCAP::PCAPFoundDevice>& pcapDevices) {
std::vector<std::shared_ptr<Device>> found;
for(auto& foundDev : pcapDevices) {
auto fakedev = std::shared_ptr<ValueCAN4IndustrialETH>(new ValueCAN4IndustrialETH({}));
for (auto& payload : foundDev.discoveryPackets)
fakedev->com->packetizer->input(payload);
for (auto& packet : fakedev->com->packetizer->output()) {
std::shared_ptr<Message> msg;
if (!fakedev->com->decoder->decode(msg, packet))
continue; // We failed to decode this packet
if(!msg || msg->type != Message::Type::Main51)
continue; // Not a message we care about
auto sn = std::dynamic_pointer_cast<SerialNumberMessage>(msg);
if(!sn)
continue; // Not a serial number message
if(sn->deviceSerial.length() < 2)
continue;
if(sn->deviceSerial.substr(0, 2) != SERIAL_START)
continue; // Not a ValueCAN 4 Industrial
auto device = foundDev.device;
device.serial[sn->deviceSerial.copy(device.serial, sizeof(device.serial))] = '\0';
found.push_back(std::shared_ptr<ValueCAN4IndustrialETH>(new ValueCAN4IndustrialETH(std::move(device))));
break;
}
}
return found;
}
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN,
Network::NetID::HSCAN2,
// No Network::NetID::Ethernet, since we're communicating over it instead
};
return supportedNetworks;
}
bool currentDriverSupportsDFU() const override { return false; }
protected:
void setupPacketizer(Packetizer& packetizer) override {
ValueCAN4Industrial::setupPacketizer(packetizer);
packetizer.align16bit = false;
}
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
private:
ValueCAN4IndustrialETH(neodevice_t neodevice) : ValueCAN4Industrial(neodevice) {
initialize<PCAP, ValueCAN4IndustrialSettings>();
}
};
}
#endif // __cplusplus
#endif

View File

@ -1,54 +0,0 @@
#ifndef __VALUECAN4INDUSTRIAL_USB_H_
#define __VALUECAN4INDUSTRIAL_USB_H_
#ifdef __cplusplus
#include "icsneo/device/tree/valuecan4/valuecan4industrial.h"
#include "icsneo/platform/cdcacm.h"
#include <string>
namespace icsneo {
class ValueCAN4IndustrialUSB : public ValueCAN4Industrial {
public:
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(USB_PRODUCT_ID)) {
if(std::string(neodevice.serial).substr(0, 2) == SERIAL_START)
found.emplace_back(new ValueCAN4IndustrialUSB(neodevice));
}
return found;
}
static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN,
Network::NetID::HSCAN2,
Network::NetID::Ethernet
};
return supportedNetworks;
}
protected:
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid);
}
// The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
private:
ValueCAN4IndustrialUSB(neodevice_t neodevice) : ValueCAN4Industrial(neodevice) {
initialize<CDCACM, ValueCAN4IndustrialSettings>();
}
};
}
#endif // __cplusplus
#endif

View File

@ -13,16 +13,8 @@ namespace icsneo {
class VividCAN : public Device {
public:
// Serial numbers start with VV
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VividCAN;
static constexpr const uint16_t PRODUCT_ID = 0x1102;
static std::vector<std::shared_ptr<Device>> Find() {
std::vector<std::shared_ptr<Device>> found;
for(auto neodevice : CDCACM::FindByProduct(PRODUCT_ID))
found.emplace_back(new VividCAN(neodevice));
return found;
}
// USB PID is 0x1102, standard driver is CDCACM
ICSNEO_FINDABLE_DEVICE(VividCAN, DeviceType::VividCAN, "VV");
// VividCAN does not go online, you can only set settings
bool goOnline() override {
@ -36,14 +28,11 @@ public:
}
protected:
bool requiresVehiclePower() const override { return false; }
private:
VividCAN(neodevice_t neodevice) : Device(neodevice) {
initialize<CDCACM, VividCANSettings>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
VividCAN(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<VividCANSettings>(makeDriver);
}
bool requiresVehiclePower() const override { return false; }
};
}

View File

@ -1,14 +1,12 @@
#ifndef __PCAP_H_
#define __PCAP_H_
#if defined _WIN32
#ifdef _WIN32
#include "icsneo/platform/windows/pcap.h"
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include "icsneo/platform/posix/pcap.h"
#else
#warning "This platform is not supported by the PCAP driver"
#endif
#define LIBICSNEO_HAVE_PCAP 1
#endif

View File

@ -27,7 +27,7 @@ public:
*/
CDCACM(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice) {}
~CDCACM();
static std::vector<neodevice_t> FindByProduct(int product);
static void Find(std::vector<FoundDevice>& found);
bool open() override;
bool isOpen() override;

View File

@ -5,31 +5,25 @@
#include "icsneo/device/tree/neoobd2pro/neoobd2pro.h"
#include "icsneo/device/tree/neoobd2sim/neoobd2sim.h"
#include "icsneo/device/tree/neovifire/neovifire.h"
#include "icsneo/device/tree/neovifire2/neovifire2eth.h"
#include "icsneo/device/tree/neovifire2/neovifire2usb.h"
#include "icsneo/device/tree/neovifire2/neovifire2.h"
#include "icsneo/device/tree/neovired2/neovired2.h"
#include "icsneo/device/tree/plasion/neoviion.h"
#include "icsneo/device/tree/plasion/neoviplasma.h"
#include "icsneo/device/tree/radepsilon/radepsilon.h"
#include "icsneo/device/tree/radgalaxy/radgalaxy.h"
#include "icsneo/device/tree/radgigastar/radgigastareth.h"
#include "icsneo/device/tree/radgigastar/radgigastarusb.h"
#include "icsneo/device/tree/radmars/radmarseth.h"
#include "icsneo/device/tree/radmars/radmarsusb.h"
#include "icsneo/device/tree/radgigastar/radgigastar.h"
#include "icsneo/device/tree/radmars/radmars.h"
#include "icsneo/device/tree/radmoon2/radmoon2.h"
#include "icsneo/device/tree/radmoonduo/radmoonduo.h"
#include "icsneo/device/tree/radpluto/radplutousb.h"
#include "icsneo/device/tree/radstar2/radstar2eth.h"
#include "icsneo/device/tree/radstar2/radstar2usb.h"
#include "icsneo/device/tree/radpluto/radpluto.h"
#include "icsneo/device/tree/radstar2/radstar2.h"
#include "icsneo/device/tree/radsupermoon/radsupermoon.h"
#include "icsneo/device/tree/valuecan3/valuecan3.h"
#include "icsneo/device/tree/valuecan4/valuecan4-1.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2eleth.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2elusb.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2el.h"
#include "icsneo/device/tree/valuecan4/valuecan4-4.h"
#include "icsneo/device/tree/valuecan4/valuecan4industrialeth.h"
#include "icsneo/device/tree/valuecan4/valuecan4industrialusb.h"
#include "icsneo/device/tree/valuecan4/valuecan4industrial.h"
#include "icsneo/device/tree/vividcan/vividcan.h"
#endif

View File

@ -16,7 +16,7 @@ namespace icsneo {
class FTDI : public Driver {
public:
static std::vector<neodevice_t> FindByProduct(int product);
static void Find(std::vector<FoundDevice>& found);
FTDI(const device_eventhandler_t& err, neodevice_t& forDevice);
~FTDI() { if(isOpen()) close(); }
@ -34,7 +34,9 @@ private:
context = nullptr;
}
std::pair<int, std::vector<std::string>> findDevices(int pid);
// A PID of 0 disables filtering by PID
std::pair<int, std::vector< std::pair<std::string, uint16_t> > > findDevices(int pid = 0);
int openDevice(int pid, const char* serial);
bool closeDevice();
bool isOpen() const { return deviceOpen; }
@ -52,7 +54,7 @@ private:
};
FTDIContext ftdi;
static std::vector<std::tuple<int, std::string>> handles;
static std::vector<std::string> handles;
static bool ErrorIsDisconnection(int errorCode);
void readTask();

View File

@ -4,6 +4,7 @@
#ifdef __cplusplus
#include "icsneo/device/neodevice.h"
#include "icsneo/device/founddevice.h"
#include "icsneo/communication/driver.h"
#include "icsneo/communication/ethernetpacketizer.h"
#include "icsneo/api/eventmanager.h"
@ -14,33 +15,28 @@ namespace icsneo {
class PCAP : public Driver {
public:
class PCAPFoundDevice {
public:
neodevice_t device;
std::vector<std::vector<uint8_t>> discoveryPackets;
};
static std::vector<PCAPFoundDevice> FindAll();
static void Find(std::vector<FoundDevice>& foundDevices);
static std::string GetEthDevSerialFromMacAddress(uint8_t product, uint16_t macSerial);
static bool IsHandleValid(neodevice_handle_t handle);
PCAP(device_eventhandler_t err, neodevice_t& forDevice);
bool open();
bool isOpen();
bool close();
bool open() override;
bool isOpen() override;
bool close() override;
bool isEthernet() const override { return true; }
private:
char errbuf[PCAP_ERRBUF_SIZE] = { 0 };
neodevice_t& device;
uint8_t deviceMAC[6];
bool openable = true;
EthernetPacketizer ethPacketizer;
void readTask();
void writeTask();
void readTask() override;
void writeTask() override;
class NetworkInterface {
public:
uint8_t uuid;
uint8_t macAddress[8];
uint8_t macAddress[6];
std::string nameFromPCAP;
std::string descriptionFromPCAP;
std::string fullName;

View File

@ -10,7 +10,7 @@ namespace icsneo {
class CDCACM : public VCP {
public:
CDCACM(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {}
static std::vector<neodevice_t> FindByProduct(int product) { return VCP::FindByProduct(product, { L"usbser" }); }
static void Find(std::vector<FoundDevice>& found) { return VCP::Find(found, { L"usbser" }); }
};
}

View File

@ -5,31 +5,25 @@
#include "icsneo/device/tree/neoobd2pro/neoobd2pro.h"
#include "icsneo/device/tree/neoobd2sim/neoobd2sim.h"
#include "icsneo/device/tree/neovifire/neovifire.h"
#include "icsneo/device/tree/neovifire2/neovifire2eth.h"
#include "icsneo/device/tree/neovifire2/neovifire2usb.h"
#include "icsneo/device/tree/neovifire2/neovifire2.h"
#include "icsneo/device/tree/neovired2/neovired2.h"
#include "icsneo/device/tree/plasion/neoviion.h"
#include "icsneo/device/tree/plasion/neoviplasma.h"
#include "icsneo/device/tree/radepsilon/radepsilon.h"
#include "icsneo/device/tree/radgalaxy/radgalaxy.h"
#include "icsneo/device/tree/radgigastar/radgigastareth.h"
#include "icsneo/device/tree/radgigastar/radgigastarusb.h"
#include "icsneo/device/tree/radmars/radmarseth.h"
#include "icsneo/device/tree/radmars/radmarsusb.h"
#include "icsneo/device/tree/radgigastar/radgigastar.h"
#include "icsneo/device/tree/radmars/radmars.h"
#include "icsneo/device/tree/radmoon2/radmoon2.h"
#include "icsneo/device/tree/radmoonduo/radmoonduo.h"
#include "icsneo/device/tree/radpluto/radplutousb.h"
#include "icsneo/device/tree/radstar2/radstar2eth.h"
#include "icsneo/device/tree/radstar2/radstar2usb.h"
#include "icsneo/device/tree/radpluto/radpluto.h"
#include "icsneo/device/tree/radstar2/radstar2.h"
#include "icsneo/device/tree/radsupermoon/radsupermoon.h"
#include "icsneo/device/tree/valuecan3/valuecan3.h"
#include "icsneo/device/tree/valuecan4/valuecan4-1.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2eleth.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2elusb.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2el.h"
#include "icsneo/device/tree/valuecan4/valuecan4-4.h"
#include "icsneo/device/tree/valuecan4/valuecan4industrialeth.h"
#include "icsneo/device/tree/valuecan4/valuecan4industrialusb.h"
#include "icsneo/device/tree/valuecan4/valuecan4industrial.h"
#include "icsneo/device/tree/vividcan/vividcan.h"
#endif

View File

@ -10,7 +10,7 @@ namespace icsneo {
class FTDI : public VCP {
public:
FTDI(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {}
static std::vector<neodevice_t> FindByProduct(int product) { return VCP::FindByProduct(product, { L"serenum" /*, L"ftdibus" */ }); }
static void Find(std::vector<FoundDevice>& found) { return VCP::Find(found, { L"serenum" /*, L"ftdibus" */ }); }
};
}

View File

@ -6,6 +6,7 @@
#include "icsneo/platform/windows/internal/pcapdll.h"
#include "icsneo/device/neodevice.h"
#include "icsneo/communication/driver.h"
#include "icsneo/device/founddevice.h"
#include "icsneo/api/eventmanager.h"
#include "icsneo/communication/ethernetpacketizer.h"
#include <string>
@ -14,20 +15,15 @@ namespace icsneo {
class PCAP : public Driver {
public:
class PCAPFoundDevice {
public:
neodevice_t device;
std::vector<std::vector<uint8_t>> discoveryPackets;
};
static std::vector<PCAPFoundDevice> FindAll();
static void Find(std::vector<FoundDevice>& foundDevices);
static std::string GetEthDevSerialFromMacAddress(uint8_t product, uint16_t macSerial);
static bool IsHandleValid(neodevice_handle_t handle);
PCAP(const device_eventhandler_t& err, neodevice_t& forDevice);
bool open();
bool isOpen();
bool close();
bool open() override;
bool isOpen() override;
bool close() override;
bool isEthernet() const override { return true; }
private:
const PCAPDLL& pcap;
char errbuf[PCAP_ERRBUF_SIZE] = { 0 };
@ -48,7 +44,7 @@ private:
class NetworkInterface {
public:
uint8_t uuid;
uint8_t macAddress[8];
uint8_t macAddress[6];
std::string nameFromWinPCAP;
std::string nameFromWin32API;
std::string descriptionFromWinPCAP;

View File

@ -17,7 +17,7 @@ namespace icsneo {
// Virtual COM Port Communication
class VCP : public Driver {
public:
static std::vector<neodevice_t> FindByProduct(int product, std::vector<std::wstring> driverName);
static void Find(std::vector<FoundDevice>& found, std::vector<std::wstring> driverName);
static bool IsHandleValid(neodevice_handle_t handle);
typedef void(*fn_boolCallback)(bool success);

View File

@ -1,4 +1,5 @@
#include "icsneo/platform/cdcacm.h"
#include "icsneo/device/founddevice.h"
#include <mutex>
#include <vector>
#include <CoreFoundation/CoreFoundation.h>
@ -79,22 +80,19 @@ private:
io_object_t toRelease;
};
std::vector<neodevice_t> CDCACM::FindByProduct(int product) {
std::vector<neodevice_t> found;
void CDCACM::Find(std::vector<FoundDevice>& found) {
CFMutableDictionaryRef ref = IOServiceMatching(kIOSerialBSDServiceValue);
if(ref == nullptr)
return found;
return;
io_iterator_t matchingServices = 0;
kern_return_t kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, ref, &matchingServices);
if(KERN_SUCCESS != kernResult || matchingServices == 0)
return found;
return;
IOReleaser matchingServicesReleaser(matchingServices);
io_object_t serialPort;
while((serialPort = IOIteratorNext(matchingServices))) {
IOReleaser serialPortReleaser(serialPort);
neodevice_t device;
// First get the parent device
// We want to check that it has the right VID/PID
@ -138,10 +136,10 @@ std::vector<neodevice_t> CDCACM::FindByProduct(int product) {
CFReleaser productPropReleaser(productProp);
if(CFGetTypeID(productProp) != CFNumberGetTypeID())
continue;
uint16_t pid = 0;
if(!CFNumberGetValue(static_cast<CFNumberRef>(productProp), kCFNumberSInt16Type, &pid))
continue;
if(pid != product)
// Read the PID directly into the FoundDevice structure
FoundDevice device;
if(!CFNumberGetValue(static_cast<CFNumberRef>(productProp), kCFNumberSInt16Type, &device.productId))
continue;
// Now, let's get the "call-out" device (/dev/cu.*)
@ -173,10 +171,13 @@ std::vector<neodevice_t> CDCACM::FindByProduct(int product) {
continue;
device.serial[serial.copy(device.serial, sizeof(device.serial)-1)] = '\0';
// Add a factory to make the driver
device.makeDriver = [](const device_eventhandler_t& report, neodevice_t& device) {
return std::unique_ptr<Driver>(new CDCACM(report, device));
};
found.push_back(device);
}
return found;
}
std::string CDCACM::HandleToTTY(neodevice_handle_t handle) {

View File

@ -1,4 +1,5 @@
#include "icsneo/platform/ftdi.h"
#include "icsneo/device/founddevice.h"
#include <iostream>
#include <stdio.h>
#include <cstring>
@ -9,22 +10,21 @@
using namespace icsneo;
std::vector<std::tuple<int, std::string>> FTDI::handles;
std::vector<std::string> FTDI::handles;
std::vector<neodevice_t> FTDI::FindByProduct(int product) {
void FTDI::Find(std::vector<FoundDevice>& found) {
constexpr size_t deviceSerialBufferLength = sizeof(device.serial);
std::vector<neodevice_t> found;
static FTDIContext context;
std::pair<int, std::vector<std::string>> result = context.findDevices(product);
const auto result = context.findDevices();
if(result.first < 0)
return found; // TODO Flag an error for the client application, there was an issue with FTDI
return; // TODO Flag an error for the client application, there was an issue with FTDI
for(auto& serial : result.second) {
neodevice_t d;
for(const auto& [serial, pid] : result.second) {
FoundDevice d;
strncpy(d.serial, serial.c_str(), deviceSerialBufferLength - 1);
d.serial[deviceSerialBufferLength - 1] = '\0'; // strncpy does not write a null terminator if serial is too long
std::tuple<int, std::string> devHandle = std::make_tuple(product, serial);
std::string devHandle = serial;
auto it = std::find(handles.begin(), handles.end(), devHandle);
size_t foundHandle = SIZE_MAX;
if(it != handles.end()) {
@ -34,10 +34,14 @@ std::vector<neodevice_t> FTDI::FindByProduct(int product) {
handles.push_back(devHandle);
}
d.handle = foundHandle;
d.productId = pid;
d.makeDriver = [](const device_eventhandler_t& report, neodevice_t& device) {
return std::unique_ptr<Driver>(new FTDI(report, device));
};
found.push_back(d);
}
return found;
}
FTDI::FTDI(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice) {
@ -56,8 +60,8 @@ bool FTDI::open() {
}
// At this point the handle has been checked to be within the bounds of the handles array
std::tuple<int, std::string>& handle = handles[device.handle];
const int openError = ftdi.openDevice(std::get<0>(handle), std::get<1>(handle).c_str());
auto& handle = handles[device.handle];
const int openError = ftdi.openDevice(0, handle.c_str());
if(openError == -5) { // Unable to claim device
report(APIEvent::Type::DeviceInUse, APIEvent::Severity::Error);
return false;
@ -112,17 +116,13 @@ bool FTDI::close() {
return ret;
}
std::pair<int, std::vector<std::string>> FTDI::FTDIContext::findDevices(int pid) {
std::pair<int, std::vector<std::string>> ret;
std::pair<int, std::vector< std::pair<std::string, uint16_t> > > FTDI::FTDIContext::findDevices(int pid) {
std::pair<int, std::vector< std::pair<std::string, uint16_t> > > ret;
if(context == nullptr) {
ret.first = -1;
return ret;
}
if(pid == 0) {
ret.first = -2;
return ret;
}
struct ftdi_device_list* devlist = nullptr;
ret.first = ftdi_usb_find_all(context, &devlist, INTREPID_USB_VENDOR_ID, pid);
@ -138,18 +138,23 @@ std::pair<int, std::vector<std::string>> FTDI::FTDIContext::findDevices(int pid)
return ret;
}
for (struct ftdi_device_list* curdev = devlist; curdev != NULL;) {
char serial[32];
memset(serial, 0, sizeof(serial));
int result = ftdi_usb_get_strings(context, curdev->dev, nullptr, 0, nullptr, 0, serial, 32);
size_t len = strlen(serial);
if(result >= 0 && len > 0)
ret.second.emplace_back(serial);
else if(ret.first > 0)
ret.first--; // We're discarding this device
curdev = curdev->next;
for(struct ftdi_device_list* curdev = devlist; curdev != nullptr; curdev = curdev->next) {
struct libusb_device_descriptor descriptor = {};
// Check against bDeviceClass here as it will be 0 for FTDI devices
// It will be 2 for CDC ACM devices, which we don't want to handle here
if(libusb_get_device_descriptor(curdev->dev, &descriptor) != 0 || descriptor.bDeviceClass != 0)
continue;
char serial[16] = {};
if(ftdi_usb_get_strings(context, curdev->dev, nullptr, 0, nullptr, 0, serial, sizeof(serial)) < 0)
continue;
const auto len = strnlen(serial, sizeof(serial));
if(len > 4 && len < 10)
ret.second.emplace_back(serial, descriptor.idProduct);
}
ret.first = static_cast<int>(ret.second.size());
ftdi_list_free(&devlist);
return ret;
}
@ -157,7 +162,7 @@ std::pair<int, std::vector<std::string>> FTDI::FTDIContext::findDevices(int pid)
int FTDI::FTDIContext::openDevice(int pid, const char* serial) {
if(context == nullptr)
return 1;
if(pid == 0 || serial == nullptr)
if(serial == nullptr)
return 2;
if(serial[0] == '\0')
return 3;

View File

@ -1,4 +1,5 @@
#include "icsneo/platform/cdcacm.h"
#include "icsneo/device/founddevice.h"
#include <dirent.h>
#include <cstring>
#include <iostream>
@ -80,12 +81,10 @@ private:
std::string serial;
};
std::vector<neodevice_t> CDCACM::FindByProduct(int product) {
std::vector<neodevice_t> found;
void CDCACM::Find(std::vector<FoundDevice>& found) {
Directory directory("/sys/bus/usb/drivers/cdc_acm"); // Query the CDCACM driver
if(!directory.openedSuccessfully())
return found;
return;
std::vector<std::string> foundusbs;
for(auto& entry : directory.ls()) {
@ -100,8 +99,9 @@ std::vector<neodevice_t> CDCACM::FindByProduct(int product) {
foundusbs.emplace_back(entry.getName());
}
// Pair the USB and TTY if found
std::map<std::string, std::string> foundttys;
// Map the USB directory to the TTY and PID if found
// The PID will be filled later
std::map< std::string, std::pair<std::string, uint16_t> > foundttys;
for(auto& usb : foundusbs) {
std::stringstream ss;
ss << "/sys/bus/usb/drivers/cdc_acm/" << usb << "/tty";
@ -113,15 +113,16 @@ std::vector<neodevice_t> CDCACM::FindByProduct(int product) {
if(listing.size() != 1) // We either got no serial ports or multiple, either way no good
continue;
foundttys.insert(std::make_pair(usb, listing[0].getName()));
foundttys.insert(std::make_pair(usb, std::make_pair(listing[0].getName(), 0)));
}
// We're going to remove from the map if this is not the product we're looking for
for(auto iter = foundttys.begin(); iter != foundttys.end(); ) {
const auto& dev = *iter;
auto& [_, pair] = *iter;
auto& [tty, ttyPid] = pair;
const std::string matchString = "PRODUCT=";
std::stringstream ss;
ss << "/sys/class/tty/" << dev.second << "/device/uevent"; // Read the uevent file, which contains should have a line like "PRODUCT=93c/1101/100"
ss << "/sys/class/tty/" << tty << "/device/uevent"; // Read the uevent file, which contains should have a line like "PRODUCT=93c/1101/100"
std::ifstream fs(ss.str());
std::string productLine;
size_t pos = std::string::npos;
@ -153,32 +154,34 @@ std::vector<neodevice_t> CDCACM::FindByProduct(int product) {
continue;
}
if(vid != INTREPID_USB_VENDOR_ID || pid != product) {
iter = foundttys.erase(iter); // Not the right VID or PID, remove
if(vid != INTREPID_USB_VENDOR_ID) {
iter = foundttys.erase(iter); // Not the right VID, remove
continue;
}
ttyPid = pid; // Set the PID for this TTY
iter++; // If the loop ends without erasing the iter from the map, the item is good
}
// At this point, foundttys contains the the devices we want
// Get the serial number, create the neodevice_t
for(auto& dev : foundttys) {
neodevice_t device;
for(auto& [usb, pair] : foundttys) {
auto& [tty, ttyPid] = pair;
FoundDevice device;
USBSerialGetter getter(dev.first);
USBSerialGetter getter(usb);
if(!getter.success())
continue; // Failure, could not get serial number
// In ttyACM0, we want the i to be the first character of the number
size_t i;
for(i = 0; i < dev.second.length(); i++) {
if(isdigit(dev.second[i]))
for(i = 0; i < tty.length(); i++) {
if(isdigit(tty[i]))
break;
}
// Now we try to parse the number so we have a handle for later
try {
device.handle = (neodevice_handle_t)std::stoul(dev.second.substr(i));
device.handle = (neodevice_handle_t)std::stoul(tty.substr(i));
/* The TTY numbering starts at zero, but we want to keep zero for an undefined
* handle, so add a constant, and we'll subtract that constant in the open function.
*/
@ -187,12 +190,16 @@ std::vector<neodevice_t> CDCACM::FindByProduct(int product) {
continue; // Somehow this failed, have to toss the device
}
device.productId = ttyPid;
device.serial[getter.getSerial().copy(device.serial, sizeof(device.serial)-1)] = '\0';
// Add a factory to make the driver
device.makeDriver = [](const device_eventhandler_t& report, neodevice_t& device) {
return std::unique_ptr<Driver>(new CDCACM(report, device));
};
found.push_back(device); // Finally, add device to search results
}
return found;
}
std::string CDCACM::HandleToTTY(neodevice_handle_t handle) {

View File

@ -1,7 +1,9 @@
#include "icsneo/platform/posix/pcap.h"
#include "icsneo/communication/network.h"
#include "icsneo/communication/communication.h"
#include "icsneo/communication/ethernetpacketizer.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/decoder.h"
#include <codecvt>
#include <chrono>
#include <cstring>
@ -15,14 +17,10 @@
using namespace icsneo;
static const uint8_t BROADCAST_MAC[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const uint8_t ICS_UNSET_MAC[6] = { 0x00, 0xFC, 0x70, 0xFF, 0xFF, 0xFF };
std::vector<PCAP::NetworkInterface> PCAP::knownInterfaces;
std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
void PCAP::Find(std::vector<FoundDevice>& found) {
static bool warned = false; // Only warn once for failure to open devices
std::vector<PCAPFoundDevice> foundDevices;
// First we ask PCAP to give us all of the devices
pcap_if_t* alldevs;
@ -39,7 +37,7 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
if(!success) {
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error);
return std::vector<PCAPFoundDevice>();
return;
}
std::vector<NetworkInterface> interfaces;
@ -138,7 +136,7 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
pcap_sendpacket(iface.fp, bs.data(), (int)bs.size());
auto timeout = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(50);
while(std::chrono::high_resolution_clock::now() <= timeout) { // Wait up to 5ms for the response
while(std::chrono::high_resolution_clock::now() <= timeout) { // Wait up to 50ms for the response
struct pcap_pkthdr* header;
const uint8_t* data;
auto res = pcap_next_ex(iface.fp, &header, &data);
@ -153,47 +151,48 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
if(res == 0)
continue; // Keep waiting for that packet
EthernetPacketizer::EthernetPacket packet(data, header->caplen);
// Is this an ICS response packet (0xCAB2) from an ICS MAC, either to broadcast or directly to us?
if(packet.etherType == 0xCAB2 && packet.srcMAC[0] == 0x00 && packet.srcMAC[1] == 0xFC && packet.srcMAC[2] == 0x70 && (
memcmp(packet.destMAC, iface.macAddress, sizeof(packet.destMAC)) == 0 ||
memcmp(packet.destMAC, BROADCAST_MAC, sizeof(packet.destMAC)) == 0 ||
memcmp(packet.destMAC, ICS_UNSET_MAC, sizeof(packet.destMAC)) == 0
)) {
/* We have received a packet from a device. We don't know if this is the device we're
* looking for, we don't know if it's actually a response to our RequestSerialNumber
* or not, we just know we got something.
*
* Unlike most transport layers, we can't get the serial number here as we actually
* need to parse this message that has been returned. Some devices parse messages
* differently, so we need to use their communication layer. We could technically
* create a communication layer to parse the packet we have in `payload` here, but
* we'd need to be given a packetizer and decoder for the device. I'm intentionally
* avoiding passing that information down here for code quality's sake. Instead, pass
* the packet we received back up so the device can handle it.
*/
neodevice_handle_t handle = (neodevice_handle_t)((i << 24) | (packet.srcMAC[3] << 16) | (packet.srcMAC[4] << 8) | (packet.srcMAC[5]));
PCAPFoundDevice* alreadyExists = nullptr;
for(auto& dev : foundDevices)
if(dev.device.handle == handle)
alreadyExists = &dev;
EthernetPacketizer ethPacketizer([](APIEvent::Type, APIEvent::Severity) {});
memcpy(ethPacketizer.hostMAC, iface.macAddress, sizeof(ethPacketizer.hostMAC));
ethPacketizer.allowInPacketsFromAnyMAC = true;
if(!ethPacketizer.inputUp({ data, data + header->caplen }))
continue; // This packet is not for us
if(alreadyExists == nullptr) {
PCAPFoundDevice foundDevice;
foundDevice.device.handle = handle;
foundDevice.discoveryPackets.push_back(std::move(packet.payload));
foundDevices.push_back(foundDevice);
} else {
alreadyExists->discoveryPackets.push_back(std::move(packet.payload));
}
Packetizer packetizer([](APIEvent::Type, APIEvent::Severity) {});
if(!packetizer.input(ethPacketizer.outputUp()))
continue; // This packet was not well formed
EthernetPacketizer::EthernetPacket decoded(data, header->caplen);
Decoder decoder([](APIEvent::Type, APIEvent::Severity) {});
for(const auto& packet : packetizer.output()) {
std::shared_ptr<Message> message;
if(!decoder.decode(message, packet))
continue;
const neodevice_handle_t handle = (neodevice_handle_t)((i << 24) | (decoded.srcMAC[3] << 16) | (decoded.srcMAC[4] << 8) | (decoded.srcMAC[5]));
if(std::any_of(found.begin(), found.end(), [&handle](const auto& found) { return handle == found.handle; }))
continue; // We already have this device on this interface
const auto serial = std::dynamic_pointer_cast<SerialNumberMessage>(message);
if(!serial || serial->deviceSerial.size() != 6)
continue;
FoundDevice foundDevice;
foundDevice.handle = handle;
foundDevice.productId = decoded.srcMAC[2];
memcpy(foundDevice.serial, serial->deviceSerial.c_str(), sizeof(foundDevice.serial) - 1);
foundDevice.serial[sizeof(foundDevice.serial) - 1] = '\0';
foundDevice.makeDriver = [](const device_eventhandler_t& report, neodevice_t& device) {
return std::unique_ptr<Driver>(new PCAP(report, device));
};
found.push_back(foundDevice);
}
}
pcap_close(iface.fp);
iface.fp = nullptr;
}
return foundDevices;
}
bool PCAP::IsHandleValid(neodevice_handle_t handle) {

View File

@ -4,8 +4,9 @@
#include "icsneo/platform/windows/pcap.h"
#include "icsneo/communication/network.h"
#include "icsneo/communication/communication.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/ethernetpacketizer.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/decoder.h"
#include <pcap.h>
#include <iphlpapi.h>
#pragma comment(lib, "IPHLPAPI.lib")
@ -17,17 +18,14 @@
using namespace icsneo;
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
static const uint8_t BROADCAST_MAC[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const uint8_t ICS_UNSET_MAC[6] = { 0x00, 0xFC, 0x70, 0xFF, 0xFF, 0xFF };
std::vector<PCAP::NetworkInterface> PCAP::knownInterfaces;
std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
std::vector<PCAPFoundDevice> foundDevices;
void PCAP::Find(std::vector<FoundDevice>& found) {
const PCAPDLL& pcap = PCAPDLL::getInstance();
if(!pcap.ok()) {
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotStart, APIEvent::Severity::Error);
return std::vector<PCAPFoundDevice>();
return;
}
// First we ask WinPCAP to give us all of the devices
@ -45,7 +43,7 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
if(!success) {
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error);
return std::vector<PCAPFoundDevice>();
return;
}
std::vector<NetworkInterface> interfaces;
@ -62,13 +60,13 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
ULONG size = 0;
if(GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &size) != ERROR_BUFFER_OVERFLOW) {
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error);
return std::vector<PCAPFoundDevice>();
return;
}
std::vector<uint8_t> adapterAddressBuffer;
adapterAddressBuffer.resize(size);
if(GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, (IP_ADAPTER_ADDRESSES*)adapterAddressBuffer.data(), &size) != ERROR_SUCCESS) {
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error);
return std::vector<PCAPFoundDevice>();
return;
}
// aa->AdapterName constains a unique name of the interface like "{3B1D2791-435A-456F-8A7B-9CB0EEE5DAB3}"
@ -137,46 +135,48 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
if(res == 0)
continue; // Keep waiting for that packet
EthernetPacketizer::EthernetPacket packet(data, header->caplen);
// Is this an ICS response packet (0xCAB2) from an ICS MAC, either to broadcast or directly to us?
if(packet.etherType == 0xCAB2 && packet.srcMAC[0] == 0x00 && packet.srcMAC[1] == 0xFC && packet.srcMAC[2] == 0x70 && (
memcmp(packet.destMAC, iface.macAddress, sizeof(packet.destMAC)) == 0 ||
memcmp(packet.destMAC, BROADCAST_MAC, sizeof(packet.destMAC)) == 0
)) {
/* We have received a packet from a device. We don't know if this is the device we're
* looking for, we don't know if it's actually a response to our RequestSerialNumber
* or not, we just know we got something.
*
* Unlike most transport layers, we can't get the serial number here as we actually
* need to parse this message that has been returned. Some devices parse messages
* differently, so we need to use their communication layer. We could technically
* create a communication layer to parse the packet we have in `payload` here, but
* we'd need to be given a packetizer and decoder for the device. I'm intentionally
* avoiding passing that information down here for code quality's sake. Instead, pass
* the packet we received back up so the device can handle it.
*/
neodevice_handle_t handle = (neodevice_handle_t)((i << 24) | (packet.srcMAC[3] << 16) | (packet.srcMAC[4] << 8) | (packet.srcMAC[5]));
PCAPFoundDevice* alreadyExists = nullptr;
for(auto& dev : foundDevices)
if(dev.device.handle == handle)
alreadyExists = &dev;
EthernetPacketizer ethPacketizer([](APIEvent::Type, APIEvent::Severity) {});
memcpy(ethPacketizer.hostMAC, iface.macAddress, sizeof(ethPacketizer.hostMAC));
ethPacketizer.allowInPacketsFromAnyMAC = true;
if(!ethPacketizer.inputUp({ data, data + header->caplen }))
continue; // This packet is not for us
if(alreadyExists == nullptr) {
PCAPFoundDevice foundDevice;
foundDevice.device.handle = handle;
foundDevice.discoveryPackets.push_back(std::move(packet.payload));
foundDevices.push_back(foundDevice);
} else {
alreadyExists->discoveryPackets.push_back(std::move(packet.payload));
}
Packetizer packetizer([](APIEvent::Type, APIEvent::Severity) {});
if(!packetizer.input(ethPacketizer.outputUp()))
continue; // This packet was not well formed
EthernetPacketizer::EthernetPacket decoded(data, header->caplen);
for(const auto& packet : packetizer.output()) {
Decoder decoder([](APIEvent::Type, APIEvent::Severity) {});
std::shared_ptr<Message> message;
if(!decoder.decode(message, packet))
continue;
const neodevice_handle_t handle = (neodevice_handle_t)((i << 24) | (decoded.srcMAC[3] << 16) | (decoded.srcMAC[4] << 8) | (decoded.srcMAC[5]));
if(std::any_of(found.begin(), found.end(), [&handle](const auto& found) { return handle == found.handle; }))
continue; // We already have this device on this interface
const auto serial = std::dynamic_pointer_cast<SerialNumberMessage>(message);
if(!serial || serial->deviceSerial.size() != 6)
continue;
FoundDevice foundDevice;
foundDevice.handle = handle;
foundDevice.productId = decoded.srcMAC[2];
memcpy(foundDevice.serial, serial->deviceSerial.c_str(), sizeof(foundDevice.serial) - 1);
foundDevice.serial[sizeof(foundDevice.serial) - 1] = '\0';
foundDevice.makeDriver = [](const device_eventhandler_t& reportFn, neodevice_t& device) {
return std::unique_ptr<Driver>(new PCAP(reportFn, device));
};
found.push_back(foundDevice);
}
}
pcap.close(iface.fp);
iface.fp = nullptr;
}
return foundDevices;
}
bool PCAP::IsHandleValid(neodevice_handle_t handle) {

View File

@ -1,6 +1,7 @@
#include "icsneo/platform/windows/ftdi.h"
#include "icsneo/platform/ftdi.h"
#include "icsneo/platform/registry.h"
#include "icsneo/device/founddevice.h"
#include <windows.h>
#include <iostream>
#include <iomanip>
@ -19,8 +20,7 @@ static const std::wstring ALL_ENUM_REG_KEY = L"SYSTEM\\CurrentControlSet\\Enum\\
static constexpr unsigned int RETRY_TIMES = 5;
static constexpr unsigned int RETRY_DELAY = 50;
struct VCP::Detail
{
struct VCP::Detail {
Detail() {
overlappedRead.hEvent = INVALID_HANDLE_VALUE;
overlappedWrite.hEvent = INVALID_HANDLE_VALUE;
@ -32,21 +32,22 @@ struct VCP::Detail
OVERLAPPED overlappedWait = {};
};
std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstring> driverNames) {
std::vector<neodevice_t> found;
void VCP::Find(std::vector<FoundDevice>& found, std::vector<std::wstring> driverNames) {
for(auto& driverName : driverNames) {
std::wstringstream regss;
regss << DRIVER_SERVICES_REG_KEY << driverName << L"\\Enum\\";
std::wstring driverEnumRegKey = regss.str();
uint32_t deviceCount = 0;
if(!Registry::Get(driverEnumRegKey, L"Count", deviceCount)) {
return found;
}
if(!Registry::Get(driverEnumRegKey, L"Count", deviceCount))
continue;
for(uint32_t i = 0; i < deviceCount; i++) {
neodevice_t device = {};
FoundDevice device;
device.makeDriver = [](const device_eventhandler_t& reportFn, neodevice_t& device) {
return std::unique_ptr<Driver>(new VCP(reportFn, device));
};
// 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"
@ -64,11 +65,10 @@ std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstrin
if(entry.find(vss.str()) == std::wstring::npos)
continue;
std::wstringstream pss;
pss << "PID_" << std::setfill(L'0') << std::setw(4) << std::uppercase << std::hex << product;
auto pidpos = entry.find(pss.str());
auto pidpos = entry.find(L"PID_");
if(pidpos == std::wstring::npos)
continue;
// We will later use this and startchar to parse the PID
// Okay, this is a device we want
// Get the serial number
@ -90,13 +90,18 @@ std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstrin
else
oss << sn;
device.productId = uint16_t(std::wcstol(entry.c_str() + pidpos + 4, nullptr, 16));
if(!device.productId)
continue;
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.
if(serial.find_first_of('\\') != std::string::npos) {
// 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
std::wstringstream uess;
uess << ALL_ENUM_REG_KEY << L"\\USB\\" << vss.str() << L'&' << pss.str() << L'\\';
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::wstringstream ciss;
ciss << ALL_ENUM_REG_KEY << entry;
std::wstring containerIDFromEntry, containerIDFromEnum;
@ -166,7 +171,7 @@ std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstrin
}
bool alreadyFound = false;
neodevice_t* shouldReplace = nullptr;
FoundDevice* shouldReplace = nullptr;
for(auto& foundDev : found) {
if((foundDev.handle == device.handle || foundDev.handle == 0 || device.handle == 0) && serial == foundDev.serial) {
alreadyFound = true;
@ -182,8 +187,6 @@ std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstrin
*shouldReplace = device;
}
}
return found;
}
VCP::VCP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice) {

View File

@ -328,8 +328,9 @@ int ftdi_usb_find_all(struct ftdi_context *ftdi, struct ftdi_device_list **devli
if (libusb_get_device_descriptor(dev, &desc) < 0)
ftdi_error_return_free_device_list(-6, "libusb_get_device_descriptor() failed", devs);
// Intrepid modification: PID 0 returns all devices with the correct VID
if (((vendor || product) &&
desc.idVendor == vendor && desc.idProduct == product) ||
desc.idVendor == vendor && (desc.idProduct == product || !product)) ||
(!(vendor || product) &&
(desc.idVendor == 0x403) && (desc.idProduct == 0x6001 || desc.idProduct == 0x6010
|| desc.idProduct == 0x6011 || desc.idProduct == 0x6014
@ -774,7 +775,8 @@ int ftdi_usb_open_desc_index(struct ftdi_context *ftdi, int vendor, int product,
if (libusb_get_device_descriptor(dev, &desc) < 0)
ftdi_error_return_free_device_list(-13, "libusb_get_device_descriptor() failed", devs);
if (desc.idVendor == vendor && desc.idProduct == product)
// Intrepid modification: PID 0 disables filtering by PID
if (desc.idVendor == vendor && (desc.idProduct == product || !product))
{
if (libusb_open(dev, &ftdi->usb_dev) < 0)
ftdi_error_return_free_device_list(-4, "usb_open() failed", devs);