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_ICSNEOC_STATIC "Build static C library" ON)
option(LIBICSNEO_BUILD_ICSNEOLEGACY "Build icsnVC40 compatibility 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") 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) if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
@ -86,17 +89,41 @@ endif()
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
set(PLATFORM_SRC set(PLATFORM_SRC
platform/windows/pcap.cpp
platform/windows/registry.cpp platform/windows/registry.cpp
platform/windows/vcp.cpp )
if(LIBICSNEO_ENABLE_RAW_ETHERNET)
list(APPEND PLATFORM_SRC
platform/windows/pcap.cpp
platform/windows/internal/pcapdll.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 else() # Darwin or Linux
set(PLATFORM_SRC set(PLATFORM_SRC)
platform/posix/ftdi.cpp
if(LIBICSNEO_ENABLE_RAW_ETHERNET)
list(APPEND PLATFORM_SRC
platform/posix/pcap.cpp platform/posix/pcap.cpp
)
endif()
if(LIBICSNEO_ENABLE_FTDI)
list(APPEND PLATFORM_SRC
platform/posix/ftdi.cpp
)
endif()
if(LIBICSNEO_ENABLE_CDCACM)
list(APPEND PLATFORM_SRC
platform/posix/cdcacm.cpp platform/posix/cdcacm.cpp
) )
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin") if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
list(APPEND PLATFORM_SRC list(APPEND PLATFORM_SRC
platform/posix/darwin/cdcacmdarwin.cpp platform/posix/darwin/cdcacmdarwin.cpp
@ -107,11 +134,12 @@ else() # Darwin or Linux
) )
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
message(WARNING message(WARNING
"There is no platform port defined for ${CMAKE_SYSTEM_NAME}!\n" "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." "The Linux platform code will be used, as it will generally allow building, but some devices may not enumerate properly."
) )
endif() endif()
endif() endif()
endif()
endif() endif()
if(LIBICSNEO_BUILD_EXAMPLES) if(LIBICSNEO_BUILD_EXAMPLES)
@ -149,6 +177,7 @@ set(SRC_FILES
device/idevicesettings.cpp device/idevicesettings.cpp
device/devicefinder.cpp device/devicefinder.cpp
device/device.cpp device/device.cpp
device/neodevice.cpp
disk/diskreaddriver.cpp disk/diskreaddriver.cpp
disk/diskwritedriver.cpp disk/diskwritedriver.cpp
disk/nulldiskdriver.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) 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}) message("Loaded extensions: " ${LIBICSNEO_EXTENSION_TARGETS})
target_link_libraries(icsneocpp PUBLIC ${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 # fatfs
add_subdirectory(third-party/fatfs) add_subdirectory(third-party/fatfs)

View File

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

View File

@ -1,11 +1,166 @@
#include "icsneo/device/devicefinder.h" #include "icsneo/device/devicefinder.h"
#include "icsneo/platform/devices.h" #include "icsneo/platform/devices.h"
#include "icsneo/device/founddevice.h"
#include "generated/extensions/builtin.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; using namespace icsneo;
static bool supportedDevicesCached = false; template<typename T>
static std::vector<DeviceType> supportedDevices = { 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));
}
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;
// Offer found devices to each of the subclasses
for (const FoundDevice& dev : driverFoundDevices) {
#ifdef __ETHERBADGE_H_
makeIfSerialMatches<EtherBADGE>(dev, foundDevices);
#endif
#ifdef __NEOOBD2PRO_H_
makeIfSerialMatches<NeoOBD2PRO>(dev, foundDevices);
#endif
#ifdef __NEOOBD2SIM_H_
makeIfSerialMatches<NeoOBD2SIM>(dev, foundDevices);
#endif
#ifdef __NEOVIFIRE_H_
makeIfPIDMatches<NeoVIFIRE>(dev, foundDevices);
#endif
#ifdef __NEOVIFIRE2_H_
makeIfSerialMatches<NeoVIFIRE2>(dev, foundDevices);
#endif
#ifdef __NEOVIRED2_H_
makeIfSerialMatches<NeoVIRED2>(dev, foundDevices);
#endif
#ifdef __NEOVIION_H_
makeIfPIDMatches<NeoVIION>(dev, foundDevices);
#endif
#ifdef __NEOVIPLASMA_H_
makeIfPIDMatches<NeoVIPLASMA>(dev, foundDevices);
#endif
#ifdef __RADEPSILON_H_
makeIfSerialMatches<RADEpsilon>(dev, foundDevices);
#endif
#ifdef __RADGALAXY_H_
makeIfSerialMatches<RADGalaxy>(dev, foundDevices);
#endif
#ifdef __RADMARS_H_
makeIfSerialMatches<RADMars>(dev, foundDevices);
#endif
#ifdef __RADGIGASTAR_H_
makeIfSerialMatches<RADGigastar>(dev, foundDevices);
#endif
#ifdef __RADMOON2_H_
makeIfSerialMatches<RADMoon2>(dev, foundDevices);
#endif
#ifdef __RADMOONDUO_H_
makeIfSerialMatches<RADMoonDuo>(dev, foundDevices);
#endif
#ifdef __RADPLUTO_H_
makeIfSerialMatches<RADPluto>(dev, foundDevices);
#endif
#ifdef __RADSTAR2_H_
makeIfSerialMatches<RADStar2>(dev, foundDevices);
#endif
#ifdef __RADSUPERMOON_H_
makeIfSerialMatches<RADSupermoon>(dev, foundDevices);
#endif
#ifdef __VALUECAN3_H_
makeIfPIDMatches<ValueCAN3>(dev, foundDevices);
#endif
#ifdef __VALUECAN4_1_H_
makeIfSerialMatches<ValueCAN4_1>(dev, foundDevices);
#endif
#ifdef __VALUECAN4_2_H_
makeIfSerialMatches<ValueCAN4_2>(dev, foundDevices);
#endif
#ifdef __VALUECAN4_2EL_H_
makeIfSerialMatches<ValueCAN4_2EL>(dev, foundDevices);
#endif
#ifdef __VALUECAN4_4_H_
makeIfSerialMatches<ValueCAN4_4>(dev, foundDevices);
#endif
#ifdef __VALUECAN4INDUSTRIAL_H_
makeIfSerialMatches<ValueCAN4Industrial>(dev, foundDevices);
#endif
#ifdef __VIVIDCAN_H_
makeIfSerialMatches<VividCAN>(dev, foundDevices);
#endif
}
for(auto& device : foundDevices) {
AddBuiltInExtensionsTo(device);
}
return foundDevices;
}
const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
static std::vector<DeviceType> supportedDevices = {
#ifdef __ETHERBADGE_H_ #ifdef __ETHERBADGE_H_
EtherBADGE::DEVICE_TYPE, EtherBADGE::DEVICE_TYPE,
@ -27,12 +182,8 @@ static std::vector<DeviceType> supportedDevices = {
NeoVIFIRE::DEVICE_TYPE, NeoVIFIRE::DEVICE_TYPE,
#endif #endif
#ifdef __NEOVIFIRE2ETH_H_ #ifdef __NEOVIFIRE2_H_
NeoVIFIRE2ETH::DEVICE_TYPE, NeoVIFIRE2::DEVICE_TYPE,
#endif
#ifdef __NEOVIFIRE2USB_H_
NeoVIFIRE2USB::DEVICE_TYPE,
#endif #endif
#ifdef __NEOVIION_H_ #ifdef __NEOVIION_H_
@ -51,20 +202,12 @@ static std::vector<DeviceType> supportedDevices = {
RADGalaxy::DEVICE_TYPE, RADGalaxy::DEVICE_TYPE,
#endif #endif
#ifdef __RADMARS_ETH_H_ #ifdef __RADMARS_H_
RADMarsETH::DEVICE_TYPE, RADMars::DEVICE_TYPE,
#endif #endif
#ifdef __RADMARS_USB_H_ #ifdef __RADGIGASTAR_H_
RADMarsUSB::DEVICE_TYPE, RADGigastar::DEVICE_TYPE,
#endif
#ifdef __RADGIGASTAR_ETH_H_
RADGigastarETH::DEVICE_TYPE,
#endif
#ifdef __RADGIGASTAR_USB_H_
RADGigastarUSB::DEVICE_TYPE,
#endif #endif
#ifdef __RADMOON2_H_ #ifdef __RADMOON2_H_
@ -75,16 +218,12 @@ static std::vector<DeviceType> supportedDevices = {
RADMoonDuo::DEVICE_TYPE, RADMoonDuo::DEVICE_TYPE,
#endif #endif
#ifdef __RADPLUTOUSB_H_ #ifdef __RADPLUTO_H_
RADPlutoUSB::DEVICE_TYPE, RADPluto::DEVICE_TYPE,
#endif #endif
#ifdef __RADSTAR2ETH_H_ #ifdef __RADSTAR2_H_
RADStar2ETH::DEVICE_TYPE, RADStar2::DEVICE_TYPE,
#endif
#ifdef __RADSTAR2USB_H_
RADStar2USB::DEVICE_TYPE,
#endif #endif
#ifdef __RADSUPERMOON_H_ #ifdef __RADSUPERMOON_H_
@ -103,176 +242,23 @@ static std::vector<DeviceType> supportedDevices = {
ValueCAN4_2::DEVICE_TYPE, ValueCAN4_2::DEVICE_TYPE,
#endif #endif
#ifdef __VALUECAN4_2EL_ETH_H_ #ifdef __VALUECAN4_2EL_H_
ValueCAN4_2EL_ETH::DEVICE_TYPE, ValueCAN4_2EL::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4_2EL_USB_H_
ValueCAN4_2EL_USB::DEVICE_TYPE,
#endif #endif
#ifdef __VALUECAN4_4_H_ #ifdef __VALUECAN4_4_H_
ValueCAN4_4::DEVICE_TYPE, ValueCAN4_4::DEVICE_TYPE,
#endif #endif
#ifdef __VALUECAN4INDUSTRIAL_ETH_H_ #ifdef __VALUECAN4INDUSTRIAL_H_
ValueCAN4IndustrialETH::DEVICE_TYPE, ValueCAN4Industrial::DEVICE_TYPE,
#endif
#ifdef __VALUECAN4INDUSTRIAL_USB_H_
ValueCAN4IndustrialUSB::DEVICE_TYPE,
#endif #endif
#ifdef __VIVIDCAN_H_ #ifdef __VIVIDCAN_H_
VividCAN::DEVICE_TYPE, VividCAN::DEVICE_TYPE,
#endif #endif
}; };
std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
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
#ifdef __ETHERBADGE_H_
findResults.push_back(EtherBADGE::Find());
#endif
#ifdef __NEOOBD2PRO_H_
findResults.push_back(NeoOBD2PRO::Find());
#endif
#ifdef __NEOOBD2SIM_H_
findResults.push_back(NeoOBD2SIM::Find());
#endif
#ifdef __NEOVIFIRE_H_
findResults.push_back(NeoVIFIRE::Find());
#endif
#ifdef __NEOVIFIRE2ETH_H_
findResults.push_back(NeoVIFIRE2ETH::Find(pcapDevices));
#endif
#ifdef __NEOVIFIRE2USB_H_
findResults.push_back(NeoVIFIRE2USB::Find());
#endif
#ifdef __NEOVIRED2_H_
findResults.push_back(NeoVIRED2::Find(pcapDevices));
#endif
#ifdef __NEOVIION_H_
findResults.push_back(NeoVIION::Find());
#endif
#ifdef __NEOVIPLASMA_H_
findResults.push_back(NeoVIPLASMA::Find());
#endif
#ifdef __RADEPSILON_H_
findResults.push_back(RADEpsilon::Find());
#endif
#ifdef __RADGALAXY_H_
findResults.push_back(RADGalaxy::Find(pcapDevices));
#endif
#ifdef __RADMARS_ETH_H_
findResults.push_back(RADMarsETH::Find(pcapDevices));
#endif
#ifdef __RADMARS_USB_H_
findResults.push_back(RADMarsUSB::Find());
#endif
#ifdef __RADGIGASTAR_ETH_H_
findResults.push_back(RADGigastarETH::Find(pcapDevices));
#endif
#ifdef __RADGIGASTAR_USB_H_
findResults.push_back(RADGigastarUSB::Find());
#endif
#ifdef __RADMOON2_H_
findResults.push_back(RADMoon2::Find());
#endif
#ifdef __RADMOONDUO_H_
findResults.push_back(RADMoonDuo::Find());
#endif
#ifdef __RADPLUTOUSB_H_
findResults.push_back(RADPlutoUSB::Find());
#endif
#ifdef __RADSTAR2ETH_H_
findResults.push_back(RADStar2ETH::Find(pcapDevices));
#endif
#ifdef __RADSTAR2USB_H_
findResults.push_back(RADStar2USB::Find());
#endif
#ifdef __RADSUPERMOON_H_
findResults.push_back(RADSupermoon::Find());
#endif
#ifdef __VALUECAN3_H_
findResults.push_back(ValueCAN3::Find());
#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()));
}
for(auto& device : foundDevices) {
AddBuiltInExtensionsTo(device);
}
return foundDevices;
}
const std::vector<DeviceType>& DeviceFinder::GetSupportedDevices() {
if(!supportedDevicesCached) {
supportedDevices.erase(std::unique(supportedDevices.begin(), supportedDevices.end()), supportedDevices.end());
supportedDevicesCached = true;
}
return supportedDevices; 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 { class Communication {
public: public:
// Note that the Packetizer is not created by the constructor,
// and should be done once the Communication module is in place.
Communication( Communication(
device_eventhandler_t report, device_eventhandler_t report,
std::unique_ptr<Driver>&& driver, std::unique_ptr<Driver>&& driver,
std::function<std::unique_ptr<Packetizer>()> makeConfiguredPacketizer, std::function<std::unique_ptr<Packetizer>()> makeConfiguredPacketizer,
std::unique_ptr<Encoder>&& e, 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)) { std::unique_ptr<Decoder>&& md) : makeConfiguredPacketizer(makeConfiguredPacketizer), encoder(std::move(e)), decoder(std::move(md)), driver(std::move(driver)), report(report) {}
packetizer = makeConfiguredPacketizer();
}
virtual ~Communication(); virtual ~Communication();
bool open(); bool open();
@ -77,10 +77,10 @@ public:
std::unique_ptr<Packetizer> packetizer; std::unique_ptr<Packetizer> packetizer;
std::unique_ptr<Encoder> encoder; std::unique_ptr<Encoder> encoder;
std::unique_ptr<Decoder> decoder; std::unique_ptr<Decoder> decoder;
std::unique_ptr<Driver> driver;
device_eventhandler_t report; device_eventhandler_t report;
protected: protected:
std::unique_ptr<Driver> driver;
static int messageCallbackIDCounter; static int messageCallbackIDCounter;
std::mutex messageCallbacksLock; std::mutex messageCallbacksLock;
std::map<int, MessageCallback> messageCallbacks; 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 read(std::vector<uint8_t>& bytes, size_t limit = 0);
virtual bool readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds(100), size_t limit = 0); virtual bool readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds(100), size_t limit = 0);
virtual bool write(const std::vector<uint8_t>& bytes); virtual bool write(const std::vector<uint8_t>& bytes);
virtual bool isEthernet() const { return false; }
device_eventhandler_t report; device_eventhandler_t report;

View File

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

View File

@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include <utility> #include <utility>
#include <cstring> #include <cstring>
#include <cstdint>
#include <atomic> #include <atomic>
#include <type_traits> #include <type_traits>
#include "icsneo/api/eventmanager.h" #include "icsneo/api/eventmanager.h"
@ -16,6 +17,7 @@
#include "icsneo/device/nullsettings.h" #include "icsneo/device/nullsettings.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/device/deviceversion.h" #include "icsneo/device/deviceversion.h"
#include "icsneo/device/founddevice.h"
#include "icsneo/disk/diskreaddriver.h" #include "icsneo/disk/diskreaddriver.h"
#include "icsneo/disk/diskwritedriver.h" #include "icsneo/disk/diskwritedriver.h"
#include "icsneo/disk/nulldiskdriver.h" #include "icsneo/disk/nulldiskdriver.h"
@ -32,6 +34,20 @@
#include "icsneo/platform/optional.h" #include "icsneo/platform/optional.h"
#include "icsneo/platform/nodiscard.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 { namespace icsneo {
class DeviceExtension; class DeviceExtension;
@ -46,7 +62,6 @@ public:
uint16_t getTimestampResolution() const; uint16_t getTimestampResolution() const;
DeviceType getType() const { return DeviceType(data.type); } DeviceType getType() const { return DeviceType(data.type); }
uint16_t getProductId() const { return productId; }
std::string getSerial() const { return data.serial; } std::string getSerial() const { return data.serial; }
uint32_t getSerialNumber() const { return Device::SerialStringToNum(getSerial()); } uint32_t getSerialNumber() const { return Device::SerialStringToNum(getSerial()); }
const neodevice_t& getNeoDevice() const { return data; } const neodevice_t& getNeoDevice() const { return data; }
@ -308,7 +323,6 @@ public:
std::unique_ptr<IDeviceSettings> settings; std::unique_ptr<IDeviceSettings> settings;
protected: protected:
uint16_t productId = 0;
bool online = false; bool online = false;
int messagePollingCallbackID = 0; int messagePollingCallbackID = 0;
int internalHandlerCallbackID = 0; int internalHandlerCallbackID = 0;
@ -323,21 +337,23 @@ protected:
std::array<optional<double>, 2> miscAnalog; std::array<optional<double>, 2> miscAnalog;
// START Initialization Functions // START Initialization Functions
Device(neodevice_t neodevice = { 0 }) { Device(neodevice_t neodevice) : data(neodevice) {
data = neodevice;
data.device = this; data.device = this;
} }
template<typename Driver, typename Settings = NullSettings, typename DiskRead = Disk::NullDriver, typename DiskWrite = Disk::NullDriver> template<typename Settings = NullSettings, typename DiskRead = Disk::NullDriver, typename DiskWrite = Disk::NullDriver>
void initialize() { void initialize(const driver_factory_t& makeDriver) {
report = makeEventHandler(); report = makeEventHandler();
auto driver = makeDriver<Driver>();
setupDriver(*driver);
auto encoder = makeEncoder(); auto encoder = makeEncoder();
setupEncoder(*encoder); setupEncoder(*encoder);
auto decoder = makeDecoder(); auto decoder = makeDecoder();
setupDecoder(*decoder); 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); setupCommunication(*com);
settings = makeSettings<Settings>(com); settings = makeSettings<Settings>(com);
setupSettings(*settings); 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 std::unique_ptr<Packetizer> makePacketizer() { return std::unique_ptr<Packetizer>(new Packetizer(report)); }
virtual void setupPacketizer(Packetizer&) {} virtual void setupPacketizer(Packetizer&) {}
std::unique_ptr<Packetizer> makeConfiguredPacketizer() { std::unique_ptr<Packetizer> makeConfiguredPacketizer() {
@ -377,7 +389,9 @@ protected:
std::function<std::unique_ptr<Packetizer>()> makeConfiguredPacketizer, std::function<std::unique_ptr<Packetizer>()> makeConfiguredPacketizer,
std::unique_ptr<Encoder> e, 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)); } 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> template<typename Settings>
std::unique_ptr<IDeviceSettings> makeSettings(std::shared_ptr<Communication> com) { 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 { namespace icsneo {
class Device; class Device;
class FoundDevice;
} }
typedef icsneo::Device* devicehandle_t; typedef icsneo::Device* devicehandle_t;
@ -20,7 +21,13 @@ typedef int32_t neodevice_handle_t;
#pragma pack(push, 1) #pragma pack(push, 1)
#ifdef __cplusplus
typedef struct neodevice_t {
neodevice_t();
neodevice_t(const icsneo::FoundDevice& found, devicetype_t inType);
#else
typedef struct { typedef struct {
#endif
devicehandle_t device; // Pointer back to the C++ device object devicehandle_t device; // Pointer back to the C++ device object
neodevice_handle_t handle; // Handle for use by the underlying driver neodevice_handle_t handle; // Handle for use by the underlying driver
devicetype_t type; devicetype_t type;

View File

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

View File

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

View File

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

View File

@ -5,23 +5,14 @@
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
#include "icsneo/device/tree/neovifire/neovifiresettings.h" #include "icsneo/device/tree/neovifire/neovifiresettings.h"
namespace icsneo { namespace icsneo {
class NeoVIFIRE : public Device { class NeoVIFIRE : public Device {
public: public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::FIRE; // USB PID is 0x0701, standard driver is FTDI
static constexpr const uint16_t PRODUCT_ID = 0x0701; ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIFIRE, DeviceType::FIRE, 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;
}
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
@ -67,19 +58,17 @@ public:
} }
private: private:
NeoVIFIRE(neodevice_t neodevice) : Device(neodevice) { NeoVIFIRE(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<FTDI, NeoVIFIRESettings>(); initialize<NeoVIFIRESettings>(makeDriver);
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
} }
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
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/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
#include "icsneo/device/tree/neovifire2/neovifire2settings.h" #include "icsneo/device/tree/neovifire2/neovifire2settings.h"
namespace icsneo { namespace icsneo {
class NeoVIFIRE2 : public Device { class NeoVIFIRE2 : public Device {
public: public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::FIRE2; // Serial numbers start with CY
static constexpr const char* SERIAL_START = "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 { enum class SKU {
Standard, Standard,
@ -87,8 +88,22 @@ public:
} }
protected: protected:
NeoVIFIRE2(neodevice_t neodevice) : Device(neodevice) { NeoVIFIRE2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE; 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 { virtual void setupEncoder(Encoder& encoder) override {
@ -96,13 +111,13 @@ protected:
encoder.supportCANFD = true; encoder.supportCANFD = true;
} }
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
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 { void handleDeviceStatus(const std::shared_ptr<RawMessage>& message) override {
if(message->data.size() < sizeof(neovifire2_status_t)) 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/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/platform/pcap.h"
#include "icsneo/disk/extextractordiskreaddriver.h" #include "icsneo/disk/extextractordiskreaddriver.h"
#include "icsneo/disk/neomemorydiskdriver.h" #include "icsneo/disk/neomemorydiskdriver.h"
#include "icsneo/device/tree/neovired2/neovired2settings.h" #include "icsneo/device/tree/neovired2/neovired2settings.h"
@ -12,41 +11,9 @@ namespace icsneo {
class NeoVIRED2 : public Device { class NeoVIRED2 : public Device {
public: public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RED2; // Serial numbers start with D2
static constexpr const char* SERIAL_START = "D2"; // Ethernet MAC allocation is 0x0E, standard driver is Raw
static constexpr const uint16_t PRODUCT_ID = 0x000E; ICSNEO_FINDABLE_DEVICE(NeoVIRED2, DeviceType::RED2, "D2");
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;
}
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
@ -68,10 +35,8 @@ public:
} }
protected: protected:
NeoVIRED2(neodevice_t neodevice) : Device(neodevice) { NeoVIRED2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<PCAP, NeoVIRED2Settings, Disk::ExtExtractorDiskReadDriver, Disk::NeoMemoryDiskDriver>(); initialize<NeoVIRED2Settings, Disk::ExtExtractorDiskReadDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
} }
virtual void setupEncoder(Encoder& encoder) override { virtual void setupEncoder(Encoder& encoder) override {
@ -84,13 +49,13 @@ protected:
packetizer.align16bit = false; packetizer.align16bit = false;
} }
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
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/tree/plasion/plasion.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/platform/ftdi.h"
#include "icsneo/disk/plasiondiskreaddriver.h" #include "icsneo/disk/plasiondiskreaddriver.h"
#include "icsneo/disk/neomemorydiskdriver.h" #include "icsneo/disk/neomemorydiskdriver.h"
@ -13,22 +12,12 @@ namespace icsneo {
class NeoVIION : public Plasion { class NeoVIION : public Plasion {
public: public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::ION; // USB PID is 0x0901, standard driver is FTDI
static constexpr const uint16_t PRODUCT_ID = 0x0901; ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIION, DeviceType::ION, 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;
}
private: private:
NeoVIION(neodevice_t neodevice) : Plasion(neodevice) { NeoVIION(neodevice_t neodevice, const driver_factory_t& makeDriver) : Plasion(neodevice) {
initialize<FTDI, NullSettings, Disk::PlasionDiskReadDriver, Disk::NeoMemoryDiskDriver>(); initialize<NullSettings, Disk::PlasionDiskReadDriver, Disk::NeoMemoryDiskDriver>(makeDriver);
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
} }
virtual std::shared_ptr<Communication> makeCommunication( virtual std::shared_ptr<Communication> makeCommunication(

View File

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

View File

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

View File

@ -3,23 +3,14 @@
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/platform/cdcacm.h"
namespace icsneo { namespace icsneo {
class RADEpsilon : public Device { class RADEpsilon : public Device {
public: public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADEpsilon; // Serial numbers start with RE
static constexpr const char* SERIAL_START = "RE"; // USB PID is 0x1109, standard driver is CDCACM
static constexpr const uint16_t PRODUCT_ID = 0x1109; ICSNEO_FINDABLE_DEVICE(RADEpsilon, DeviceType::RADEpsilon, "RE");
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;
}
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
@ -34,10 +25,8 @@ public:
} }
protected: protected:
RADEpsilon(neodevice_t neodevice) : Device(neodevice) { RADEpsilon(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<CDCACM>(); initialize(makeDriver);
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
} }
virtual void setupEncoder(Encoder& encoder) override { virtual void setupEncoder(Encoder& encoder) override {
@ -45,13 +34,13 @@ protected:
encoder.supportCANFD = true; encoder.supportCANFD = true;
} }
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
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/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/platform/pcap.h"
#include "icsneo/communication/packetizer.h" #include "icsneo/communication/packetizer.h"
#include "icsneo/communication/decoder.h" #include "icsneo/communication/decoder.h"
#include "icsneo/device/tree/radgalaxy/radgalaxysettings.h" #include "icsneo/device/tree/radgalaxy/radgalaxysettings.h"
@ -15,41 +14,8 @@ namespace icsneo {
class RADGalaxy : public Device { class RADGalaxy : public Device {
public: public:
// Serial numbers start with RG // Serial numbers start with RG
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADGalaxy; // Ethernet MAC allocation is 0x03, standard driver is Raw
static constexpr const uint16_t PRODUCT_ID = 0x0003; ICSNEO_FINDABLE_DEVICE(RADGalaxy, DeviceType::RADGalaxy, "RG");
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;
}
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
@ -85,15 +51,13 @@ public:
return supportedNetworks; 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; } size_t getEthernetActivationLineCount() const override { return 1; }
protected: protected:
RADGalaxy(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADGalaxySettings>(makeDriver);
}
void setupPacketizer(Packetizer& packetizer) override { void setupPacketizer(Packetizer& packetizer) override {
Device::setupPacketizer(packetizer); Device::setupPacketizer(packetizer);
packetizer.disableChecksum = true; packetizer.disableChecksum = true;

View File

@ -11,16 +11,18 @@ namespace icsneo {
class RADGigastar : public Device { class RADGigastar : public Device {
public: public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADGigastar; // Serial numbers start with GS
static constexpr const char* SERIAL_START = "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; } size_t getEthernetActivationLineCount() const override { return 1; }
bool getEthPhyRegControlSupported() const override { return true; } bool getEthPhyRegControlSupported() const override { return true; }
protected: protected:
RADGigastar(neodevice_t neodevice) : Device(neodevice) { RADGigastar(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE; initialize<RADGigastarSettings>(makeDriver);
} }
void setupPacketizer(Packetizer& packetizer) override { 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 { class RADMars : public Device {
public: public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADMars; // Serial numbers start with GL (previously, RAD-Gigalog)
static constexpr const char* SERIAL_START = "GL"; // 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; } size_t getEthernetActivationLineCount() const override { return 1; }
protected: protected:
RADMars(neodevice_t neodevice) : Device(neodevice) { RADMars(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE; initialize<RADMarsSettings>(makeDriver);
} }
void setupPacketizer(Packetizer& packetizer) override { 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/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/device/tree/radmoon2/radmoon2settings.h" #include "icsneo/device/tree/radmoon2/radmoon2settings.h"
#include "icsneo/platform/ftdi3.h"
namespace icsneo { namespace icsneo {
class RADMoon2 : public Device { class RADMoon2 : public Device {
public: public:
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADMoon2; // Serial numbers start with RM
static constexpr const uint16_t PRODUCT_ID = 0x1202; // USB PID is 0x1202, standard driver is FTDI3
static constexpr const char* SERIAL_START = "RM"; ICSNEO_FINDABLE_DEVICE(RADMoon2, DeviceType::RADMoon2, "RM");
enum class SKU { enum class SKU {
Standard, Standard,
@ -22,15 +21,6 @@ public:
APM1000E_CLK, // Clock Option and Keysight Branding 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 { SKU getSKU() const {
switch(getSerial().back()) { switch(getSerial().back()) {
case 'A': case 'A':
@ -70,10 +60,8 @@ public:
bool getEthPhyRegControlSupported() const override { return true; } bool getEthPhyRegControlSupported() const override { return true; }
protected: protected:
RADMoon2(neodevice_t neodevice) : Device(neodevice) { RADMoon2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<FTDI3, RADMoon2Settings>(); initialize<RADMoon2Settings>(makeDriver);
productId = PRODUCT_ID;
getWritableNeoDevice().type = DEVICE_TYPE;
} }
void setupPacketizer(Packetizer& packetizer) override { void setupPacketizer(Packetizer& packetizer) override {

View File

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

View File

@ -5,8 +5,6 @@
#include "icsneo/device/device.h" #include "icsneo/device/device.h"
#include "icsneo/device/devicetype.h" #include "icsneo/device/devicetype.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/decoder.h"
#include "icsneo/device/tree/radpluto/radplutosettings.h" #include "icsneo/device/tree/radpluto/radplutosettings.h"
namespace icsneo { namespace icsneo {
@ -14,9 +12,8 @@ namespace icsneo {
class RADPluto : public Device { class RADPluto : public Device {
public: public:
// Serial numbers start with PL // Serial numbers start with PL
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADPluto; // USB PID is 1104, standard driver is CDCACM
static constexpr const uint16_t PRODUCT_ID = 0x1104; ICSNEO_FINDABLE_DEVICE(RADPluto, DeviceType::RADPluto, "PL");
static constexpr const char* SERIAL_START = "PL";
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
@ -35,27 +32,26 @@ public:
return supportedNetworks; return supportedNetworks;
} }
RADPluto(neodevice_t neodevice) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
bool getEthPhyRegControlSupported() const override { return true; } bool getEthPhyRegControlSupported() const override { return true; }
protected: protected:
RADPluto(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADPlutoSettings>(makeDriver);
}
virtual void setupEncoder(Encoder& encoder) override { virtual void setupEncoder(Encoder& encoder) override {
Device::setupEncoder(encoder); Device::setupEncoder(encoder);
encoder.supportCANFD = true; encoder.supportCANFD = true;
encoder.supportEthPhy = true; encoder.supportEthPhy = true;
} }
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
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; } 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 { class RADStar2 : public Device {
public: public:
// Serial numbers start with RS // Serial numbers start with RS
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::RADStar2; // USB PID is 0x0005, standard driver is FTDI
static constexpr const uint16_t PRODUCT_ID = 0x0005; // Ethernet MAC allocation is 0x05, standard driver is Raw
static constexpr const char* SERIAL_START = "RS"; ICSNEO_FINDABLE_DEVICE(RADStar2, DeviceType::RADStar2, "RS");
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
@ -30,6 +30,10 @@ public:
} }
protected: protected:
RADStar2(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<RADStar2Settings>(makeDriver);
}
virtual void setupPacketizer(Packetizer& packetizer) override { virtual void setupPacketizer(Packetizer& packetizer) override {
Device::setupPacketizer(packetizer); Device::setupPacketizer(packetizer);
packetizer.disableChecksum = true; packetizer.disableChecksum = true;
@ -46,18 +50,13 @@ protected:
decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns decoder.timestampResolution = 10; // Timestamps are in 10ns increments instead of the usual 25ns
} }
virtual void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override {
for(auto& netid : GetSupportedNetworks()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); } void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); }
RADStar2(neodevice_t neodevice) : Device(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
}
}; };
} }

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

View File

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

View File

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

View File

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

View File

@ -5,15 +5,15 @@
#include "icsneo/device/tree/valuecan4/valuecan4.h" #include "icsneo/device/tree/valuecan4/valuecan4.h"
#include "icsneo/device/tree/valuecan4/settings/valuecan4-2elsettings.h" #include "icsneo/device/tree/valuecan4/settings/valuecan4-2elsettings.h"
#include <string>
namespace icsneo { namespace icsneo {
class ValueCAN4_2EL : public ValueCAN4 { class ValueCAN4_2EL : public ValueCAN4 {
public: public:
// Serial numbers start with VE for 4-2EL // Serial numbers start with VE for 4-2EL
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_2EL; // USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
static constexpr const char* SERIAL_START = "VE"; // Ethernet MAC allocation is 0x0B, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(ValueCAN4_2EL, DeviceType::VCAN4_2EL, "VE");
enum class SKU { enum class SKU {
Standard, Standard,
@ -53,14 +53,16 @@ public:
Network::NetID::HSCAN, Network::NetID::HSCAN,
Network::NetID::HSCAN2, Network::NetID::HSCAN2,
Network::NetID::Ethernet Network::NetID::Ethernet,
Network::NetID::LIN
}; };
return supportedNetworks; return supportedNetworks;
} }
protected: protected:
ValueCAN4_2EL(neodevice_t neodevice) : ValueCAN4(neodevice) { ValueCAN4_2EL(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE; initialize<ValueCAN4_2ELSettings>(makeDriver);
} }
void setupSupportedRXNetworks(std::vector<Network>& rxNetworks) override { 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()); const valuecan4_2el_status_t* status = reinterpret_cast<const valuecan4_2el_status_t*>(message->data.data());
ethActivationStatus = status->ethernetActivationLineEnabled; ethActivationStatus = status->ethernetActivationLineEnabled;
} }
bool currentDriverSupportsDFU() const override { return com->driver->isEthernet(); }
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/valuecan4.h"
#include "icsneo/device/tree/valuecan4/settings/valuecan4-4settings.h" #include "icsneo/device/tree/valuecan4/settings/valuecan4-4settings.h"
#include "icsneo/platform/cdcacm.h"
#include <string>
namespace icsneo { namespace icsneo {
class ValueCAN4_4 : public ValueCAN4 { class ValueCAN4_4 : public ValueCAN4 {
public: public:
// Serial numbers start with V4 for 4-4 // Serial numbers start with V4 for 4-4
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_4; // USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
static constexpr const char* SERIAL_START = "V4"; ICSNEO_FINDABLE_DEVICE(ValueCAN4_4, DeviceType::VCAN4_4, "V4");
enum class SKU { enum class SKU {
Standard, Standard,
@ -23,17 +21,6 @@ public:
AP0400A_OBD, // OBD, USB A, and Keysight Branding 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 const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {
Network::NetID::HSCAN, Network::NetID::HSCAN,
@ -71,20 +58,17 @@ public:
} }
protected: 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()) for(auto& netid : GetSupportedNetworks())
rxNetworks.emplace_back(netid); rxNetworks.emplace_back(netid);
} }
// The supported TX networks are the same as the supported RX networks for this device // The supported TX networks are the same as the supported RX networks for this device
virtual void setupSupportedTXNetworks(std::vector<Network>& txNetworks) override { setupSupportedRXNetworks(txNetworks); } 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;
}
}; };
} }

View File

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

View File

@ -11,12 +11,40 @@ namespace icsneo {
class ValueCAN4Industrial : public ValueCAN4 { class ValueCAN4Industrial : public ValueCAN4 {
public: public:
// Serial numbers start with IV for Industrial // Serial numbers start with IV for Industrial
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VCAN4_IND; // USB PID is 0x1101 (shared by all ValueCAN 4s), standard driver is CDCACM
static constexpr const char* SERIAL_START = "IV"; // 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: protected:
ValueCAN4Industrial(neodevice_t neodevice) : ValueCAN4(neodevice) { ValueCAN4Industrial(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
getWritableNeoDevice().type = DEVICE_TYPE; 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 { class VividCAN : public Device {
public: public:
// Serial numbers start with VV // Serial numbers start with VV
static constexpr DeviceType::Enum DEVICE_TYPE = DeviceType::VividCAN; // USB PID is 0x1102, standard driver is CDCACM
static constexpr const uint16_t PRODUCT_ID = 0x1102; ICSNEO_FINDABLE_DEVICE(VividCAN, DeviceType::VividCAN, "VV");
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;
}
// VividCAN does not go online, you can only set settings // VividCAN does not go online, you can only set settings
bool goOnline() override { bool goOnline() override {
@ -36,14 +28,11 @@ public:
} }
protected: protected:
bool requiresVehiclePower() const override { return false; } VividCAN(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
initialize<VividCANSettings>(makeDriver);
private:
VividCAN(neodevice_t neodevice) : Device(neodevice) {
initialize<CDCACM, VividCANSettings>();
getWritableNeoDevice().type = DEVICE_TYPE;
productId = PRODUCT_ID;
} }
bool requiresVehiclePower() const override { return false; }
}; };
} }

View File

@ -1,14 +1,12 @@
#ifndef __PCAP_H_ #ifndef __PCAP_H_
#define __PCAP_H_ #define __PCAP_H_
#if defined _WIN32 #ifdef _WIN32
#include "icsneo/platform/windows/pcap.h" #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" #include "icsneo/platform/posix/pcap.h"
#else #else
#warning "This platform is not supported by the PCAP driver" #warning "This platform is not supported by the PCAP driver"
#endif #endif
#define LIBICSNEO_HAVE_PCAP 1
#endif #endif

View File

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

View File

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

View File

@ -16,7 +16,7 @@ namespace icsneo {
class FTDI : public Driver { class FTDI : public Driver {
public: 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(const device_eventhandler_t& err, neodevice_t& forDevice);
~FTDI() { if(isOpen()) close(); } ~FTDI() { if(isOpen()) close(); }
@ -34,7 +34,9 @@ private:
context = nullptr; 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); int openDevice(int pid, const char* serial);
bool closeDevice(); bool closeDevice();
bool isOpen() const { return deviceOpen; } bool isOpen() const { return deviceOpen; }
@ -52,7 +54,7 @@ private:
}; };
FTDIContext ftdi; FTDIContext ftdi;
static std::vector<std::tuple<int, std::string>> handles; static std::vector<std::string> handles;
static bool ErrorIsDisconnection(int errorCode); static bool ErrorIsDisconnection(int errorCode);
void readTask(); void readTask();

View File

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

View File

@ -10,7 +10,7 @@ namespace icsneo {
class CDCACM : public VCP { class CDCACM : public VCP {
public: public:
CDCACM(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {} CDCACM(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {}
static 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/neoobd2pro/neoobd2pro.h"
#include "icsneo/device/tree/neoobd2sim/neoobd2sim.h" #include "icsneo/device/tree/neoobd2sim/neoobd2sim.h"
#include "icsneo/device/tree/neovifire/neovifire.h" #include "icsneo/device/tree/neovifire/neovifire.h"
#include "icsneo/device/tree/neovifire2/neovifire2eth.h" #include "icsneo/device/tree/neovifire2/neovifire2.h"
#include "icsneo/device/tree/neovifire2/neovifire2usb.h"
#include "icsneo/device/tree/neovired2/neovired2.h" #include "icsneo/device/tree/neovired2/neovired2.h"
#include "icsneo/device/tree/plasion/neoviion.h" #include "icsneo/device/tree/plasion/neoviion.h"
#include "icsneo/device/tree/plasion/neoviplasma.h" #include "icsneo/device/tree/plasion/neoviplasma.h"
#include "icsneo/device/tree/radepsilon/radepsilon.h" #include "icsneo/device/tree/radepsilon/radepsilon.h"
#include "icsneo/device/tree/radgalaxy/radgalaxy.h" #include "icsneo/device/tree/radgalaxy/radgalaxy.h"
#include "icsneo/device/tree/radgigastar/radgigastareth.h" #include "icsneo/device/tree/radgigastar/radgigastar.h"
#include "icsneo/device/tree/radgigastar/radgigastarusb.h" #include "icsneo/device/tree/radmars/radmars.h"
#include "icsneo/device/tree/radmars/radmarseth.h"
#include "icsneo/device/tree/radmars/radmarsusb.h"
#include "icsneo/device/tree/radmoon2/radmoon2.h" #include "icsneo/device/tree/radmoon2/radmoon2.h"
#include "icsneo/device/tree/radmoonduo/radmoonduo.h" #include "icsneo/device/tree/radmoonduo/radmoonduo.h"
#include "icsneo/device/tree/radpluto/radplutousb.h" #include "icsneo/device/tree/radpluto/radpluto.h"
#include "icsneo/device/tree/radstar2/radstar2eth.h" #include "icsneo/device/tree/radstar2/radstar2.h"
#include "icsneo/device/tree/radstar2/radstar2usb.h"
#include "icsneo/device/tree/radsupermoon/radsupermoon.h" #include "icsneo/device/tree/radsupermoon/radsupermoon.h"
#include "icsneo/device/tree/valuecan3/valuecan3.h" #include "icsneo/device/tree/valuecan3/valuecan3.h"
#include "icsneo/device/tree/valuecan4/valuecan4-1.h" #include "icsneo/device/tree/valuecan4/valuecan4-1.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2.h" #include "icsneo/device/tree/valuecan4/valuecan4-2.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2eleth.h" #include "icsneo/device/tree/valuecan4/valuecan4-2el.h"
#include "icsneo/device/tree/valuecan4/valuecan4-2elusb.h"
#include "icsneo/device/tree/valuecan4/valuecan4-4.h" #include "icsneo/device/tree/valuecan4/valuecan4-4.h"
#include "icsneo/device/tree/valuecan4/valuecan4industrialeth.h" #include "icsneo/device/tree/valuecan4/valuecan4industrial.h"
#include "icsneo/device/tree/valuecan4/valuecan4industrialusb.h"
#include "icsneo/device/tree/vividcan/vividcan.h" #include "icsneo/device/tree/vividcan/vividcan.h"
#endif #endif

View File

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

View File

@ -17,7 +17,7 @@ namespace icsneo {
// Virtual COM Port Communication // Virtual COM Port Communication
class VCP : public Driver { class VCP : public Driver {
public: 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); static bool IsHandleValid(neodevice_handle_t handle);
typedef void(*fn_boolCallback)(bool success); typedef void(*fn_boolCallback)(bool success);

View File

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

View File

@ -1,4 +1,5 @@
#include "icsneo/platform/ftdi.h" #include "icsneo/platform/ftdi.h"
#include "icsneo/device/founddevice.h"
#include <iostream> #include <iostream>
#include <stdio.h> #include <stdio.h>
#include <cstring> #include <cstring>
@ -9,22 +10,21 @@
using namespace icsneo; 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); constexpr size_t deviceSerialBufferLength = sizeof(device.serial);
std::vector<neodevice_t> found;
static FTDIContext context; static FTDIContext context;
std::pair<int, std::vector<std::string>> result = context.findDevices(product); const auto result = context.findDevices();
if(result.first < 0) 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) { for(const auto& [serial, pid] : result.second) {
neodevice_t d; FoundDevice d;
strncpy(d.serial, serial.c_str(), deviceSerialBufferLength - 1); 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 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); auto it = std::find(handles.begin(), handles.end(), devHandle);
size_t foundHandle = SIZE_MAX; size_t foundHandle = SIZE_MAX;
if(it != handles.end()) { if(it != handles.end()) {
@ -34,10 +34,14 @@ std::vector<neodevice_t> FTDI::FindByProduct(int product) {
handles.push_back(devHandle); handles.push_back(devHandle);
} }
d.handle = foundHandle; 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); found.push_back(d);
} }
return found;
} }
FTDI::FTDI(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice) { FTDI::FTDI(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), 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 // 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]; auto& handle = handles[device.handle];
const int openError = ftdi.openDevice(std::get<0>(handle), std::get<1>(handle).c_str()); const int openError = ftdi.openDevice(0, handle.c_str());
if(openError == -5) { // Unable to claim device if(openError == -5) { // Unable to claim device
report(APIEvent::Type::DeviceInUse, APIEvent::Severity::Error); report(APIEvent::Type::DeviceInUse, APIEvent::Severity::Error);
return false; return false;
@ -112,17 +116,13 @@ bool FTDI::close() {
return ret; return ret;
} }
std::pair<int, std::vector<std::string>> FTDI::FTDIContext::findDevices(int pid) { std::pair<int, std::vector< std::pair<std::string, uint16_t> > > FTDI::FTDIContext::findDevices(int pid) {
std::pair<int, std::vector<std::string>> ret; std::pair<int, std::vector< std::pair<std::string, uint16_t> > > ret;
if(context == nullptr) { if(context == nullptr) {
ret.first = -1; ret.first = -1;
return ret; return ret;
} }
if(pid == 0) {
ret.first = -2;
return ret;
}
struct ftdi_device_list* devlist = nullptr; struct ftdi_device_list* devlist = nullptr;
ret.first = ftdi_usb_find_all(context, &devlist, INTREPID_USB_VENDOR_ID, pid); 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; return ret;
} }
for (struct ftdi_device_list* curdev = devlist; curdev != NULL;) { for(struct ftdi_device_list* curdev = devlist; curdev != nullptr; curdev = curdev->next) {
char serial[32]; struct libusb_device_descriptor descriptor = {};
memset(serial, 0, sizeof(serial)); // Check against bDeviceClass here as it will be 0 for FTDI devices
int result = ftdi_usb_get_strings(context, curdev->dev, nullptr, 0, nullptr, 0, serial, 32); // It will be 2 for CDC ACM devices, which we don't want to handle here
size_t len = strlen(serial); if(libusb_get_device_descriptor(curdev->dev, &descriptor) != 0 || descriptor.bDeviceClass != 0)
if(result >= 0 && len > 0) continue;
ret.second.emplace_back(serial);
else if(ret.first > 0) char serial[16] = {};
ret.first--; // We're discarding this device if(ftdi_usb_get_strings(context, curdev->dev, nullptr, 0, nullptr, 0, serial, sizeof(serial)) < 0)
curdev = curdev->next; 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); ftdi_list_free(&devlist);
return ret; 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) { int FTDI::FTDIContext::openDevice(int pid, const char* serial) {
if(context == nullptr) if(context == nullptr)
return 1; return 1;
if(pid == 0 || serial == nullptr) if(serial == nullptr)
return 2; return 2;
if(serial[0] == '\0') if(serial[0] == '\0')
return 3; return 3;

View File

@ -1,4 +1,5 @@
#include "icsneo/platform/cdcacm.h" #include "icsneo/platform/cdcacm.h"
#include "icsneo/device/founddevice.h"
#include <dirent.h> #include <dirent.h>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
@ -80,12 +81,10 @@ private:
std::string serial; std::string serial;
}; };
std::vector<neodevice_t> CDCACM::FindByProduct(int product) { void CDCACM::Find(std::vector<FoundDevice>& found) {
std::vector<neodevice_t> found;
Directory directory("/sys/bus/usb/drivers/cdc_acm"); // Query the CDCACM driver Directory directory("/sys/bus/usb/drivers/cdc_acm"); // Query the CDCACM driver
if(!directory.openedSuccessfully()) if(!directory.openedSuccessfully())
return found; return;
std::vector<std::string> foundusbs; std::vector<std::string> foundusbs;
for(auto& entry : directory.ls()) { for(auto& entry : directory.ls()) {
@ -100,8 +99,9 @@ std::vector<neodevice_t> CDCACM::FindByProduct(int product) {
foundusbs.emplace_back(entry.getName()); foundusbs.emplace_back(entry.getName());
} }
// Pair the USB and TTY if found // Map the USB directory to the TTY and PID if found
std::map<std::string, std::string> foundttys; // The PID will be filled later
std::map< std::string, std::pair<std::string, uint16_t> > foundttys;
for(auto& usb : foundusbs) { for(auto& usb : foundusbs) {
std::stringstream ss; std::stringstream ss;
ss << "/sys/bus/usb/drivers/cdc_acm/" << usb << "/tty"; 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 if(listing.size() != 1) // We either got no serial ports or multiple, either way no good
continue; 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 // 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(); ) { for(auto iter = foundttys.begin(); iter != foundttys.end(); ) {
const auto& dev = *iter; auto& [_, pair] = *iter;
auto& [tty, ttyPid] = pair;
const std::string matchString = "PRODUCT="; const std::string matchString = "PRODUCT=";
std::stringstream ss; 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::ifstream fs(ss.str());
std::string productLine; std::string productLine;
size_t pos = std::string::npos; size_t pos = std::string::npos;
@ -153,32 +154,34 @@ std::vector<neodevice_t> CDCACM::FindByProduct(int product) {
continue; continue;
} }
if(vid != INTREPID_USB_VENDOR_ID || pid != product) { if(vid != INTREPID_USB_VENDOR_ID) {
iter = foundttys.erase(iter); // Not the right VID or PID, remove iter = foundttys.erase(iter); // Not the right VID, remove
continue; 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 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 // At this point, foundttys contains the the devices we want
// Get the serial number, create the neodevice_t // Get the serial number, create the neodevice_t
for(auto& dev : foundttys) { for(auto& [usb, pair] : foundttys) {
neodevice_t device; auto& [tty, ttyPid] = pair;
FoundDevice device;
USBSerialGetter getter(dev.first); USBSerialGetter getter(usb);
if(!getter.success()) if(!getter.success())
continue; // Failure, could not get serial number continue; // Failure, could not get serial number
// In ttyACM0, we want the i to be the first character of the number // In ttyACM0, we want the i to be the first character of the number
size_t i; size_t i;
for(i = 0; i < dev.second.length(); i++) { for(i = 0; i < tty.length(); i++) {
if(isdigit(dev.second[i])) if(isdigit(tty[i]))
break; break;
} }
// Now we try to parse the number so we have a handle for later // Now we try to parse the number so we have a handle for later
try { 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 /* 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. * 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 continue; // Somehow this failed, have to toss the device
} }
device.productId = ttyPid;
device.serial[getter.getSerial().copy(device.serial, sizeof(device.serial)-1)] = '\0'; 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 found.push_back(device); // Finally, add device to search results
} }
return found;
} }
std::string CDCACM::HandleToTTY(neodevice_handle_t handle) { std::string CDCACM::HandleToTTY(neodevice_handle_t handle) {

View File

@ -1,7 +1,9 @@
#include "icsneo/platform/posix/pcap.h" #include "icsneo/platform/posix/pcap.h"
#include "icsneo/communication/network.h" #include "icsneo/communication/network.h"
#include "icsneo/communication/communication.h" #include "icsneo/communication/communication.h"
#include "icsneo/communication/ethernetpacketizer.h"
#include "icsneo/communication/packetizer.h" #include "icsneo/communication/packetizer.h"
#include "icsneo/communication/decoder.h"
#include <codecvt> #include <codecvt>
#include <chrono> #include <chrono>
#include <cstring> #include <cstring>
@ -15,14 +17,10 @@
using namespace icsneo; 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::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 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 // First we ask PCAP to give us all of the devices
pcap_if_t* alldevs; pcap_if_t* alldevs;
@ -39,7 +37,7 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
if(!success) { if(!success) {
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error);
return std::vector<PCAPFoundDevice>(); return;
} }
std::vector<NetworkInterface> interfaces; std::vector<NetworkInterface> interfaces;
@ -138,7 +136,7 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
pcap_sendpacket(iface.fp, bs.data(), (int)bs.size()); pcap_sendpacket(iface.fp, bs.data(), (int)bs.size());
auto timeout = std::chrono::high_resolution_clock::now() + std::chrono::milliseconds(50); 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; struct pcap_pkthdr* header;
const uint8_t* data; const uint8_t* data;
auto res = pcap_next_ex(iface.fp, &header, &data); auto res = pcap_next_ex(iface.fp, &header, &data);
@ -153,47 +151,48 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
if(res == 0) if(res == 0)
continue; // Keep waiting for that packet continue; // Keep waiting for that packet
EthernetPacketizer::EthernetPacket packet(data, header->caplen); EthernetPacketizer ethPacketizer([](APIEvent::Type, APIEvent::Severity) {});
// Is this an ICS response packet (0xCAB2) from an ICS MAC, either to broadcast or directly to us? memcpy(ethPacketizer.hostMAC, iface.macAddress, sizeof(ethPacketizer.hostMAC));
if(packet.etherType == 0xCAB2 && packet.srcMAC[0] == 0x00 && packet.srcMAC[1] == 0xFC && packet.srcMAC[2] == 0x70 && ( ethPacketizer.allowInPacketsFromAnyMAC = true;
memcmp(packet.destMAC, iface.macAddress, sizeof(packet.destMAC)) == 0 || if(!ethPacketizer.inputUp({ data, data + header->caplen }))
memcmp(packet.destMAC, BROADCAST_MAC, sizeof(packet.destMAC)) == 0 || continue; // This packet is not for us
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;
if(alreadyExists == nullptr) { Packetizer packetizer([](APIEvent::Type, APIEvent::Severity) {});
PCAPFoundDevice foundDevice; if(!packetizer.input(ethPacketizer.outputUp()))
foundDevice.device.handle = handle; continue; // This packet was not well formed
foundDevice.discoveryPackets.push_back(std::move(packet.payload));
foundDevices.push_back(foundDevice); EthernetPacketizer::EthernetPacket decoded(data, header->caplen);
} else { Decoder decoder([](APIEvent::Type, APIEvent::Severity) {});
alreadyExists->discoveryPackets.push_back(std::move(packet.payload)); 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); pcap_close(iface.fp);
iface.fp = nullptr; iface.fp = nullptr;
} }
return foundDevices;
} }
bool PCAP::IsHandleValid(neodevice_handle_t handle) { bool PCAP::IsHandleValid(neodevice_handle_t handle) {

View File

@ -4,8 +4,9 @@
#include "icsneo/platform/windows/pcap.h" #include "icsneo/platform/windows/pcap.h"
#include "icsneo/communication/network.h" #include "icsneo/communication/network.h"
#include "icsneo/communication/communication.h" #include "icsneo/communication/communication.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/ethernetpacketizer.h" #include "icsneo/communication/ethernetpacketizer.h"
#include "icsneo/communication/packetizer.h"
#include "icsneo/communication/decoder.h"
#include <pcap.h> #include <pcap.h>
#include <iphlpapi.h> #include <iphlpapi.h>
#pragma comment(lib, "IPHLPAPI.lib") #pragma comment(lib, "IPHLPAPI.lib")
@ -17,17 +18,14 @@
using namespace icsneo; using namespace icsneo;
static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; static std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
static const 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::NetworkInterface> PCAP::knownInterfaces;
std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() { void PCAP::Find(std::vector<FoundDevice>& found) {
std::vector<PCAPFoundDevice> foundDevices;
const PCAPDLL& pcap = PCAPDLL::getInstance(); const PCAPDLL& pcap = PCAPDLL::getInstance();
if(!pcap.ok()) { if(!pcap.ok()) {
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotStart, APIEvent::Severity::Error); 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 // First we ask WinPCAP to give us all of the devices
@ -45,7 +43,7 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
if(!success) { if(!success) {
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error);
return std::vector<PCAPFoundDevice>(); return;
} }
std::vector<NetworkInterface> interfaces; std::vector<NetworkInterface> interfaces;
@ -62,13 +60,13 @@ std::vector<PCAP::PCAPFoundDevice> PCAP::FindAll() {
ULONG size = 0; ULONG size = 0;
if(GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &size) != ERROR_BUFFER_OVERFLOW) { if(GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, nullptr, &size) != ERROR_BUFFER_OVERFLOW) {
EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::PCAPCouldNotFindDevices, APIEvent::Severity::Error);
return std::vector<PCAPFoundDevice>(); return;
} }
std::vector<uint8_t> adapterAddressBuffer; std::vector<uint8_t> adapterAddressBuffer;
adapterAddressBuffer.resize(size); adapterAddressBuffer.resize(size);
if(GetAdaptersAddresses(AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, nullptr, (IP_ADAPTER_ADDRESSES*)adapterAddressBuffer.data(), &size) != ERROR_SUCCESS) { 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); 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}" // 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) if(res == 0)
continue; // Keep waiting for that packet continue; // Keep waiting for that packet
EthernetPacketizer::EthernetPacket packet(data, header->caplen); EthernetPacketizer ethPacketizer([](APIEvent::Type, APIEvent::Severity) {});
// Is this an ICS response packet (0xCAB2) from an ICS MAC, either to broadcast or directly to us? memcpy(ethPacketizer.hostMAC, iface.macAddress, sizeof(ethPacketizer.hostMAC));
if(packet.etherType == 0xCAB2 && packet.srcMAC[0] == 0x00 && packet.srcMAC[1] == 0xFC && packet.srcMAC[2] == 0x70 && ( ethPacketizer.allowInPacketsFromAnyMAC = true;
memcmp(packet.destMAC, iface.macAddress, sizeof(packet.destMAC)) == 0 || if(!ethPacketizer.inputUp({ data, data + header->caplen }))
memcmp(packet.destMAC, BROADCAST_MAC, sizeof(packet.destMAC)) == 0 continue; // This packet is not for us
)) {
/* 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;
if(alreadyExists == nullptr) { Packetizer packetizer([](APIEvent::Type, APIEvent::Severity) {});
PCAPFoundDevice foundDevice; if(!packetizer.input(ethPacketizer.outputUp()))
foundDevice.device.handle = handle; continue; // This packet was not well formed
foundDevice.discoveryPackets.push_back(std::move(packet.payload));
foundDevices.push_back(foundDevice); EthernetPacketizer::EthernetPacket decoded(data, header->caplen);
} else { for(const auto& packet : packetizer.output()) {
alreadyExists->discoveryPackets.push_back(std::move(packet.payload)); 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); pcap.close(iface.fp);
iface.fp = nullptr; iface.fp = nullptr;
} }
return foundDevices;
} }
bool PCAP::IsHandleValid(neodevice_handle_t handle) { bool PCAP::IsHandleValid(neodevice_handle_t handle) {

View File

@ -1,6 +1,7 @@
#include "icsneo/platform/windows/ftdi.h" #include "icsneo/platform/windows/ftdi.h"
#include "icsneo/platform/ftdi.h" #include "icsneo/platform/ftdi.h"
#include "icsneo/platform/registry.h" #include "icsneo/platform/registry.h"
#include "icsneo/device/founddevice.h"
#include <windows.h> #include <windows.h>
#include <iostream> #include <iostream>
#include <iomanip> #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_TIMES = 5;
static constexpr unsigned int RETRY_DELAY = 50; static constexpr unsigned int RETRY_DELAY = 50;
struct VCP::Detail struct VCP::Detail {
{
Detail() { Detail() {
overlappedRead.hEvent = INVALID_HANDLE_VALUE; overlappedRead.hEvent = INVALID_HANDLE_VALUE;
overlappedWrite.hEvent = INVALID_HANDLE_VALUE; overlappedWrite.hEvent = INVALID_HANDLE_VALUE;
@ -32,21 +32,22 @@ struct VCP::Detail
OVERLAPPED overlappedWait = {}; OVERLAPPED overlappedWait = {};
}; };
std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstring> driverNames) { void VCP::Find(std::vector<FoundDevice>& found, std::vector<std::wstring> driverNames) {
std::vector<neodevice_t> found;
for(auto& driverName : driverNames) { for(auto& driverName : driverNames) {
std::wstringstream regss; std::wstringstream regss;
regss << DRIVER_SERVICES_REG_KEY << driverName << L"\\Enum\\"; regss << DRIVER_SERVICES_REG_KEY << driverName << L"\\Enum\\";
std::wstring driverEnumRegKey = regss.str(); std::wstring driverEnumRegKey = regss.str();
uint32_t deviceCount = 0; uint32_t deviceCount = 0;
if(!Registry::Get(driverEnumRegKey, L"Count", deviceCount)) { if(!Registry::Get(driverEnumRegKey, L"Count", deviceCount))
return found; continue;
}
for(uint32_t i = 0; i < deviceCount; i++) { 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) // First we want to look at what devices FTDI is enumerating (inside driverEnumRegKey)
// The entry for a ValueCAN 3 with SN 138635 looks like "FTDIBUS\VID_093C+PID_0601+138635A\0000" // The entry for a ValueCAN 3 with SN 138635 looks like "FTDIBUS\VID_093C+PID_0601+138635A\0000"
@ -64,11 +65,10 @@ std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstrin
if(entry.find(vss.str()) == std::wstring::npos) if(entry.find(vss.str()) == std::wstring::npos)
continue; continue;
std::wstringstream pss; auto pidpos = entry.find(L"PID_");
pss << "PID_" << std::setfill(L'0') << std::setw(4) << std::uppercase << std::hex << product;
auto pidpos = entry.find(pss.str());
if(pidpos == std::wstring::npos) if(pidpos == std::wstring::npos)
continue; continue;
// We will later use this and startchar to parse the PID
// Okay, this is a device we want // Okay, this is a device we want
// Get the serial number // Get the serial number
@ -90,13 +90,18 @@ std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstrin
else else
oss << sn; 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()); std::string serial = converter.to_bytes(oss.str());
// The serial number should not have a path slash in it. If it does, that means we don't have the real serial. // The serial number should not have a path slash in it. If it does, that means we don't have the real serial.
if(serial.find_first_of('\\') != std::string::npos) { if(serial.find_first_of('\\') != std::string::npos) {
// The serial number was not in the first serenum key where we expected it. // The serial number was not in the first serenum key where we expected it.
// We can try to match the ContainerID with the one in ALL_ENUM\USB and get a serial that way // We can try to match the ContainerID with the one in ALL_ENUM\USB and get a serial that way
std::wstringstream uess; std::wstringstream uess;
uess << ALL_ENUM_REG_KEY << L"\\USB\\" << vss.str() << L'&' << 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; std::wstringstream ciss;
ciss << ALL_ENUM_REG_KEY << entry; ciss << ALL_ENUM_REG_KEY << entry;
std::wstring containerIDFromEntry, containerIDFromEnum; std::wstring containerIDFromEntry, containerIDFromEnum;
@ -166,7 +171,7 @@ std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstrin
} }
bool alreadyFound = false; bool alreadyFound = false;
neodevice_t* shouldReplace = nullptr; FoundDevice* shouldReplace = nullptr;
for(auto& foundDev : found) { for(auto& foundDev : found) {
if((foundDev.handle == device.handle || foundDev.handle == 0 || device.handle == 0) && serial == foundDev.serial) { if((foundDev.handle == device.handle || foundDev.handle == 0 || device.handle == 0) && serial == foundDev.serial) {
alreadyFound = true; alreadyFound = true;
@ -182,8 +187,6 @@ std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstrin
*shouldReplace = device; *shouldReplace = device;
} }
} }
return found;
} }
VCP::VCP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice) { VCP::VCP(const device_eventhandler_t& err, neodevice_t& forDevice) : Driver(err), device(forDevice) {

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) if (libusb_get_device_descriptor(dev, &desc) < 0)
ftdi_error_return_free_device_list(-6, "libusb_get_device_descriptor() failed", devs); 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) && if (((vendor || product) &&
desc.idVendor == vendor && desc.idProduct == product) || desc.idVendor == vendor && (desc.idProduct == product || !product)) ||
(!(vendor || product) && (!(vendor || product) &&
(desc.idVendor == 0x403) && (desc.idProduct == 0x6001 || desc.idProduct == 0x6010 (desc.idVendor == 0x403) && (desc.idProduct == 0x6001 || desc.idProduct == 0x6010
|| desc.idProduct == 0x6011 || desc.idProduct == 0x6014 || 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) if (libusb_get_device_descriptor(dev, &desc) < 0)
ftdi_error_return_free_device_list(-13, "libusb_get_device_descriptor() failed", devs); 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) if (libusb_open(dev, &ftdi->usb_dev) < 0)
ftdi_error_return_free_device_list(-4, "usb_open() failed", devs); ftdi_error_return_free_device_list(-4, "usb_open() failed", devs);