Driver: Switch to libredxx

- no more libFTDI
- no more libusb on Linux and macOS
- no more FTDI repack
- no more binary libs
- faster D2XX on Windows (no longer uses COM)
This commit is contained in:
Kyle Schwarz
2025-08-25 11:24:03 -04:00
parent 17285389e3
commit 29dc7b345f
110 changed files with 633 additions and 15167 deletions
+8 -35
View File
@@ -53,6 +53,7 @@ public:
NotSupported = 0x1017,
FixedPointOverflow = 0x1018,
FixedPointPrecision = 0x1019,
SyscallError = 0x1020, // check errno/GetLastError() for details
// Device Events
PollingMessageOverflow = 0x2000,
@@ -134,41 +135,6 @@ public:
SendToError = 0x3109,
MDIOMessageExceedsMaxLength = 0x3110,
// FTD3XX
FTOK = 0x4000, // placeholder
FTInvalidHandle = FTOK + 1,
FTDeviceNotFound = FTOK + 2,
FTDeviceNotOpened = FTOK + 3,
FTIOError = FTOK + 4,
FTInsufficientResources = FTOK + 5,
FTInvalidParameter = FTOK + 6,
FTInvalidBaudRate = FTOK + 7,
FTDeviceNotOpenedForErase = FTOK + 8,
FTDeviceNotOpenedForWrite = FTOK + 9,
FTFailedToWriteDevice = FTOK + 10,
FTEEPROMReadFailed = FTOK + 11,
FTEEPROMWriteFailed = FTOK + 12,
FTEEPROMEraseFailed = FTOK + 13,
FTEEPROMNotPresent = FTOK + 14,
FTEEPROMNotProgrammed = FTOK + 15,
FTInvalidArgs = FTOK + 16,
FTNotSupported = FTOK + 17,
FTNoMoreItems = FTOK + 18,
FTTimeout = FTOK + 19,
FTOperationAborted = FTOK + 20,
FTReservedPipe = FTOK + 21,
FTInvalidControlRequestDirection = FTOK + 22,
FTInvalidControlRequestType = FTOK + 23,
FTIOPending = FTOK + 24,
FTIOIncomplete = FTOK + 25,
FTHandleEOF = FTOK + 26,
FTBusy = FTOK + 27,
FTNoSystemResources = FTOK + 28,
FTDeviceListNotReady = FTOK + 29,
FTDeviceNotConnected = FTOK + 30,
FTIncorrectDevicePath = FTOK + 31,
FTOtherError = FTOK + 32,
// VSA
VSABufferCorrupted = 0x5000,
VSATimestampNotFound = VSABufferCorrupted + 1,
@@ -191,6 +157,13 @@ public:
ServdNoDataError = ServdBindError + 9,
ServdJoinMulticastError = ServdBindError + 10,
// DXX
DXXErrorSys = 0x6100,
DXXErrorInt = 0x6101,
DXXErrorOverflow = 0x6102,
DXXErrorIO = 0x6103,
DXXErrorArg = 0x6104,
NoErrorFound = 0xFFFFFFFD,
TooManyEvents = 0xFFFFFFFE,
Unknown = 0xFFFFFFFF
+1 -1
View File
@@ -20,7 +20,7 @@ public:
EventCallback(std::shared_ptr<EventFilter> f, fn_eventCallback cb) : callback(cb), filter(f) {}
EventCallback(EventFilter f, fn_eventCallback cb) : callback(cb), filter(std::make_shared<EventFilter>(f)) {}
virtual bool callIfMatch(const std::shared_ptr<APIEvent>& event) const {
bool callIfMatch(const std::shared_ptr<APIEvent>& event) const {
bool ret = filter->match(*event);
if(ret)
callback(event);
@@ -11,7 +11,7 @@ namespace icsneo {
class NeoVIFIRE : public Device {
public:
// USB PID is 0x0701, standard driver is FTDI
// USB PID is 0x0701, standard driver is DXX
ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIFIRE, DeviceType::FIRE, 0x0701);
static const std::vector<Network>& GetSupportedNetworks() {
@@ -12,7 +12,7 @@ namespace icsneo {
class NeoVIFIRE2 : public Device {
public:
// Serial numbers start with CY
// USB PID is 0x1000, standard driver is FTDI
// USB PID is 0x1000, standard driver is DXX
// Ethernet MAC allocation is 0x04, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(NeoVIFIRE2, DeviceType::FIRE2, "CY");
@@ -12,7 +12,7 @@ namespace icsneo {
class NeoVIION : public Plasion {
public:
// USB PID is 0x0901, standard driver is FTDI
// USB PID is 0x0901, standard driver is DXX
ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIION, DeviceType::ION, 0x0901);
private:
@@ -10,7 +10,7 @@ namespace icsneo {
class NeoVIPLASMA : public Plasion {
public:
// USB PID is 0x0801, standard driver is FTDI
// USB PID is 0x0801, standard driver is DXX
ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIPLASMA, DeviceType::PLASMA, 0x0801);
private:
+1 -1
View File
@@ -15,7 +15,7 @@ namespace icsneo {
class RADA2B : public Device {
public:
// Serial numbers start with AB
// USB PID is 0x0006, standard driver is FTDI
// USB PID is 0x0006, standard driver is DXX
// Ethernet MAC allocation is 0x18, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADA2B, DeviceType::RAD_A2B, "AB");
@@ -12,7 +12,7 @@ class RADComet : public RADCometBase {
public:
// Serial numbers start with RC
// USB PID is 0x1207, standard driver is FTDI3
// USB PID is 0x1207, standard driver is DXX
// Ethernet MAC allocation is 0x1D, standard driver is Raw
ICSNEO_FINDABLE_DEVICE_BY_SERIAL_RANGE(RADComet, DeviceType::RADComet, "RC0000", "RC0299");
@@ -12,7 +12,7 @@ class RADComet2 : public RADCometBase {
public:
// Serial numbers start with RC, Comet2 starts at RC0300
// USB PID is 0x1207, standard driver is FTDI3
// USB PID is 0x1207, standard driver is DXX
// Ethernet MAC allocation is 0x1D, standard driver is Raw
ICSNEO_FINDABLE_DEVICE_BY_SERIAL_RANGE(RADComet2, DeviceType::RADComet, "RC0300", "RCZZZZ");
@@ -12,7 +12,7 @@ class RADComet3 : public Device {
public:
// Serial numbers start with C3
// USB PID is 0x1208, standard driver is FTDI3
// USB PID is 0x1208, standard driver is DXX
// Ethernet MAC allocation is 0x20, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADComet3, DeviceType::RADComet3, "C3");
@@ -14,7 +14,7 @@ namespace icsneo {
class RADGigastar : public Device {
public:
// Serial numbers start with GS
// USB PID is 0x1204, standard driver is FTDI3
// USB PID is 0x1204, standard driver is DXX
// Ethernet MAC allocation is 0x0F, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADGigastar, DeviceType::RADGigastar, "GS");
@@ -16,7 +16,7 @@ namespace icsneo
{
public:
// Serial numbers start with GT
// USB PID is 0x1210, standard driver is FTDI3
// USB PID is 0x1210, standard driver is DXX
// Ethernet MAC allocation is 0x22, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADGigastar2, DeviceType::RADGigastar2, "GT");
+1 -1
View File
@@ -14,7 +14,7 @@ namespace icsneo {
class RADMars : public Device {
public:
// Serial numbers start with GL (previously, RAD-Gigalog)
// USB PID is 0x1203, standard driver is FTDI3
// USB PID is 0x1203, standard driver is DXX
// Ethernet MAC allocation is 0x0A, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADMars, DeviceType::RADMars, "GL");
@@ -11,7 +11,7 @@ namespace icsneo {
class RADMoon2 : public RADMoon2Base {
public:
// Serial numbers start with RM
// USB PID is 0x1202, standard driver is FTDI3
// USB PID is 0x1202, standard driver is DXX
ICSNEO_FINDABLE_DEVICE(RADMoon2, DeviceType::RADMoon2, "RM");
uint8_t getPhyAddrOrPort() const override { return 6; };
@@ -12,7 +12,7 @@ class RADMoonT1S : public Device {
public:
// Serial numbers start with MS
// USB PID is 0x1209, standard driver is FTDI3
// USB PID is 0x1209, standard driver is DXX
// Ethernet MAC allocation is 0x21, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADMoonT1S, DeviceType::RADMoonT1S, "MS");
@@ -12,7 +12,7 @@ namespace icsneo {
class RADStar2 : public Device {
public:
// Serial numbers start with RS
// USB PID is 0x0005, standard driver is FTDI
// USB PID is 0x0005, standard driver is DXX
// Ethernet MAC allocation is 0x05, standard driver is Raw
ICSNEO_FINDABLE_DEVICE(RADStar2, DeviceType::RADStar2, "RS");
@@ -12,7 +12,7 @@ namespace icsneo {
class RADSupermoon : public Device {
public:
// Serial numbers start with SM
// USB PID is 0x1201, standard driver is FTDI3
// USB PID is 0x1201, standard driver is DXX
ICSNEO_FINDABLE_DEVICE(RADSupermoon, DeviceType::RADSupermoon, "SM");
enum class SKU {
@@ -11,7 +11,7 @@ namespace icsneo {
class ValueCAN3 : public Device {
public:
// USB PID is 0x0601, standard driver is FTDI
// USB PID is 0x0601, standard driver is DXX
ICSNEO_FINDABLE_DEVICE_BY_PID(ValueCAN3, DeviceType::VCAN3, 0x0601);
static const std::vector<Network>& GetSupportedNetworks() {
+39
View File
@@ -0,0 +1,39 @@
#ifndef __DXX_H_
#define __DXX_H_
#ifdef __cplusplus
#include "icsneo/communication/driver.h"
#include "icsneo/device/founddevice.h"
#include "libredxx/libredxx.h"
namespace icsneo {
class DXX : public Driver {
public:
static void Find(std::vector<FoundDevice>& found);
DXX(const device_eventhandler_t& err, neodevice_t& forDevice, uint16_t pid, libredxx_device_type type);
bool open() override;
bool isOpen() override;
bool close() override;
private:
void read();
void write();
neodevice_t neodevice;
uint16_t pid;
libredxx_device_type type;
libredxx_opened_device* device = nullptr;
std::thread readThread;
std::thread writeThread;
};
}
#endif // __cplusplus
#endif // __DXX_H_
-35
View File
@@ -1,35 +0,0 @@
#ifndef __FTD3XX_H_
#define __FTD3XX_H_
#ifdef __cplusplus
#include <optional>
#include "icsneo/communication/driver.h"
#include "icsneo/device/founddevice.h"
namespace icsneo {
class FTD3XX : public Driver {
public:
static void Find(std::vector<FoundDevice>& foundDevices);
FTD3XX(const device_eventhandler_t& err, neodevice_t& forDevice);
~FTD3XX() override { if(isOpen()) close(); }
bool open() override;
bool isOpen() override;
bool close() override;
bool isEthernet() const override { return false; }
private:
neodevice_t& device;
std::optional<void*> handle;
std::thread readThread, writeThread;
void readTask();
void writeTask();
};
}
#endif // __cplusplus
#endif
-14
View File
@@ -1,14 +0,0 @@
#ifndef __FTDI_H_
#define __FTDI_H_
#define INTREPID_USB_VENDOR_ID (0x093c)
#if defined _WIN32
#include "icsneo/platform/windows/ftdi.h"
#elif defined (__unix__) || (defined (__APPLE__) && defined (__MACH__))
#include "icsneo/platform/posix/ftdi.h"
#else
#warning "This platform is not supported by the FTDI driver"
#endif
#endif
-74
View File
@@ -1,74 +0,0 @@
#ifndef __FTDI_POSIX_H_
#define __FTDI_POSIX_H_
#ifdef __cplusplus
#include <vector>
#include <memory>
#include <string>
#include <ftdi.h>
#include "icsneo/device/neodevice.h"
#include "icsneo/communication/driver.h"
#include "icsneo/third-party/concurrentqueue/blockingconcurrentqueue.h"
#include "icsneo/api/eventmanager.h"
namespace icsneo {
class FTDI : public Driver {
public:
static void Find(std::vector<FoundDevice>& found);
FTDI(const device_eventhandler_t& err, neodevice_t& forDevice);
~FTDI() { if(isOpen()) close(); }
bool open();
bool close();
bool isOpen() { return ftdi.isOpen(); }
private:
class FTDIContext {
public:
FTDIContext() : context(ftdi_new()) {}
~FTDIContext() {
if(context)
ftdi_free(context); // calls ftdi_deinit and ftdi_close if required
context = nullptr;
}
// A PID of 0 disables filtering by PID
std::pair<int, std::vector< std::pair<std::string, uint16_t> > > findDevices(int pid = 0);
int openDevice(int pid, const char* serial);
bool closeDevice();
bool isOpen() const { return deviceOpen; }
int flush() { return ftdi_usb_purge_buffers(context); }
int reset() { return ftdi_usb_reset(context); }
int read(uint8_t* data, size_t size) { return ftdi_read_data(context, data, (int)size); }
int write(const uint8_t* data, size_t size) { return ftdi_write_data(context, data, (int)size); }
int setBaudrate(int baudrate) { return ftdi_set_baudrate(context, baudrate); }
int setLatencyTimer(uint8_t latency) { return ftdi_set_latency_timer(context, latency); }
bool setReadTimeout(int timeout) { if(context == nullptr) return false; context->usb_read_timeout = timeout; return true; }
bool setWriteTimeout(int timeout) { if(context == nullptr) return false; context->usb_write_timeout = timeout; return true; }
private:
struct ftdi_context* context;
bool deviceOpen = false;
};
FTDIContext ftdi;
static std::vector<std::string> handles;
static bool ErrorIsDisconnection(int errorCode);
std::thread readThread, writeThread;
void readTask();
void writeTask();
bool openable; // Set to false in the constructor if the object has not been found in searchResultDevices
neodevice_t& device;
};
}
#endif // __cplusplus
#endif
+2
View File
@@ -4,6 +4,8 @@
#ifdef __cplusplus
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
+24 -4
View File
@@ -3,14 +3,34 @@
#ifdef __cplusplus
#include "icsneo/platform/windows/vcp.h"
#include "icsneo/communication/driver.h"
#include "icsneo/device/founddevice.h"
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include <string>
namespace icsneo {
class CDCACM : public VCP {
class CDCACM : public Driver {
public:
CDCACM(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {}
static void Find(std::vector<FoundDevice>& found) { return VCP::Find(found, { L"usbser" }); }
CDCACM(const device_eventhandler_t& err, const std::wstring& path);
static void Find(std::vector<FoundDevice>& found);
bool open() override;
bool isOpen() override;
bool close() override;
private:
void read();
void write();
std::wstring path;
HANDLE handle = INVALID_HANDLE_VALUE;
std::thread readThread;
std::thread writeThread;
OVERLAPPED readOverlapped = {};
OVERLAPPED writeOverlapped = {};
};
}
@@ -1,6 +1,8 @@
#ifndef __DYNAMICLIB_WINDOWS_H_
#define __DYNAMICLIB_WINDOWS_H_
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#ifndef ICSNEOC_BUILD_STATIC
-20
View File
@@ -1,20 +0,0 @@
#ifndef __FTDI_WINDOWS_H_
#define __FTDI_WINDOWS_H_
#ifdef __cplusplus
#include "icsneo/platform/windows/vcp.h"
namespace icsneo {
class FTDI : public VCP {
public:
FTDI(const device_eventhandler_t& err, neodevice_t& forDevice) : VCP(err, forDevice) {}
static void Find(std::vector<FoundDevice>& found) { return VCP::Find(found, { L"serenum" /*, L"ftdibus" */ }); }
};
}
#endif // __cplusplus
#endif
@@ -3,6 +3,8 @@
#ifdef __cplusplus
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <windows.h>
#include <pcap.h>
#include <memory>
-49
View File
@@ -1,49 +0,0 @@
#ifndef __VCP_WINDOWS_H_
#define __VCP_WINDOWS_H_
#ifdef __cplusplus
#include <vector>
#include <string>
#include <thread>
#include <atomic>
#include <chrono>
#include "icsneo/device/neodevice.h"
#include "icsneo/communication/driver.h"
#include "icsneo/api/eventmanager.h"
namespace icsneo {
// Virtual COM Port Communication
class VCP : public Driver {
public:
static void Find(std::vector<FoundDevice>& found, std::vector<std::wstring> driverName);
static bool IsHandleValid(neodevice_handle_t handle);
typedef void(*fn_boolCallback)(bool success);
VCP(const device_eventhandler_t& err, neodevice_t& forDevice);
virtual ~VCP();
bool open() { return open(false); }
void openAsync(fn_boolCallback callback);
bool close();
bool isOpen();
private:
bool open(bool fromAsync);
bool opening = false;
neodevice_t& device;
struct Detail;
std::shared_ptr<Detail> detail;
std::vector<std::shared_ptr<std::thread>> threads;
std::thread readThread, writeThread;
void readTask();
void writeTask();
};
}
#endif // __cplusplus
#endif