Driver: DXX: Fix ION, FIRE, ValueCAN3, & VividCAN

pull/76/merge
Kyle Schwarz 2025-09-10 10:11:08 -04:00
parent fbdab1e998
commit 8b7e2556a0
12 changed files with 42 additions and 36 deletions

View File

@ -355,7 +355,7 @@ if(LIBICSNEO_ENABLE_DXX)
include(FetchContent) include(FetchContent)
FetchContent_Declare(libredxx FetchContent_Declare(libredxx
GIT_REPOSITORY https://github.com/Zeranoe/libredxx.git GIT_REPOSITORY https://github.com/Zeranoe/libredxx.git
GIT_TAG 3acc754d0af4fe529f05dbc2488b2da77ad9729c GIT_TAG 070402e425fa6e1a9da08967bbadee00fb7b5e68
) )
set(LIBREDXX_DISABLE_INSTALL ON) set(LIBREDXX_DISABLE_INSTALL ON)
FetchContent_MakeAvailable(libredxx) FetchContent_MakeAvailable(libredxx)

View File

@ -38,18 +38,10 @@ bool Driver::waitForRx(std::function<bool()> predicate, std::chrono::millisecond
} }
bool Driver::readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout, size_t limit) { bool Driver::readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout, size_t limit) {
// A limit of zero indicates no limit // wait until we have enough data, or the timeout occurs
if(limit == 0)
limit = (size_t)-1;
if(limit > (readBuffer.size() + 4))
limit = (readBuffer.size() + 4);
// wait until we have enough data, or the timout occurs
waitForRx(limit, timeout); waitForRx(limit, timeout);
size_t actuallyRead = std::min(readBuffer.size(), limit); size_t actuallyRead = readBuffer.size();
bytes.resize(actuallyRead); bytes.resize(actuallyRead);
readBuffer.read(bytes.data(), 0, actuallyRead); readBuffer.read(bytes.data(), 0, actuallyRead);

View File

@ -24,6 +24,7 @@ void MultiChannelCommunication::spawnThreads() {
void MultiChannelCommunication::joinThreads() { void MultiChannelCommunication::joinThreads() {
closing = true; closing = true;
ringBufCV.notify_all();
if(hidReadThread.joinable()) if(hidReadThread.joinable())
hidReadThread.join(); hidReadThread.join();
for(auto& thread : vnetThreads) { for(auto& thread : vnetThreads) {
@ -179,6 +180,9 @@ void MultiChannelCommunication::vnetReadTask(size_t vnetIndex) {
while(!closing) { while(!closing) {
std::unique_lock lk(ringBufMutex); std::unique_lock lk(ringBufMutex);
ringBufCV.wait(lk); ringBufCV.wait(lk);
if(closing) {
break;
}
if(vnetPacketizer->input(packetRB)) { if(vnetPacketizer->input(packetRB)) {
for(const auto& packet : vnetPacketizer->output()) { for(const auto& packet : vnetPacketizer->output()) {
std::shared_ptr<Message> msg; std::shared_ptr<Message> msg;

View File

@ -35,15 +35,6 @@ static void makeIfSerialMatches(const FoundDevice& dev, std::vector<std::shared_
into.push_back(std::make_shared<T>(dev)); 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));
}
template<typename T> template<typename T>
static void makeIfSerialRangeMatches(const FoundDevice& dev, std::vector<std::shared_ptr<Device>>& into) { static void makeIfSerialRangeMatches(const FoundDevice& dev, std::vector<std::shared_ptr<Device>>& into) {
// Relies on the subclass to have // Relies on the subclass to have
@ -139,7 +130,7 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
#endif #endif
#ifdef __NEOVIFIRE_H_ #ifdef __NEOVIFIRE_H_
makeIfPIDMatches<NeoVIFIRE>(dev, newFoundDevices); makeIfSerialRangeMatches<NeoVIFIRE>(dev, newFoundDevices);
#endif #endif
#ifdef __NEOVIFIRE2_H_ #ifdef __NEOVIFIRE2_H_
@ -159,11 +150,11 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
#endif #endif
#ifdef __NEOVIION_H_ #ifdef __NEOVIION_H_
makeIfPIDMatches<NeoVIION>(dev, newFoundDevices); makeIfSerialMatches<NeoVIION>(dev, newFoundDevices);
#endif #endif
#ifdef __NEOVIPLASMA_H_ #ifdef __NEOVIPLASMA_H_
makeIfPIDMatches<NeoVIPLASMA>(dev, newFoundDevices); makeIfSerialMatches<NeoVIPLASMA>(dev, newFoundDevices);
#endif #endif
#ifdef __RADA2B_H_ #ifdef __RADA2B_H_
@ -247,7 +238,7 @@ std::vector<std::shared_ptr<Device>> DeviceFinder::FindAll() {
#endif #endif
#ifdef __VALUECAN3_H_ #ifdef __VALUECAN3_H_
makeIfPIDMatches<ValueCAN3>(dev, newFoundDevices); makeIfSerialRangeMatches<ValueCAN3>(dev, newFoundDevices);
#endif #endif
#ifdef __VALUECAN4_1_H_ #ifdef __VALUECAN4_1_H_

View File

@ -31,7 +31,7 @@ public:
bool waitForRx(size_t limit, std::chrono::milliseconds timeout); bool waitForRx(size_t limit, std::chrono::milliseconds timeout);
bool waitForRx(std::function<bool()> predicate, std::chrono::milliseconds timeout); bool waitForRx(std::function<bool()> predicate, std::chrono::milliseconds timeout);
bool readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds(100), size_t limit = 0); bool readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds(100), size_t limit = 1);
bool write(const std::vector<uint8_t>& bytes); bool write(const std::vector<uint8_t>& bytes);
virtual bool isEthernet() const { return false; } virtual bool isEthernet() const { return false; }
bool readAvailable() { return readBuffer.size() > 0; } bool readAvailable() { return readBuffer.size() > 0; }

View File

@ -12,7 +12,7 @@ namespace icsneo {
class NeoVIFIRE : public Device { class NeoVIFIRE : public Device {
public: public:
// USB PID is 0x0701, standard driver is DXX // USB PID is 0x0701, standard driver is DXX
ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIFIRE, DeviceType::FIRE, 0x0701); ICSNEO_FINDABLE_DEVICE_BY_SERIAL_RANGE(NeoVIFIRE, DeviceType::FIRE, "50000", "79999");
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {

View File

@ -13,7 +13,7 @@ namespace icsneo {
class NeoVIION : public Plasion { class NeoVIION : public Plasion {
public: public:
// USB PID is 0x0901, standard driver is DXX // USB PID is 0x0901, standard driver is DXX
ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIION, DeviceType::ION, 0x0901); ICSNEO_FINDABLE_DEVICE(NeoVIION, DeviceType::ION, "40");
private: private:
NeoVIION(neodevice_t neodevice, const driver_factory_t& makeDriver) : Plasion(neodevice) { NeoVIION(neodevice_t neodevice, const driver_factory_t& makeDriver) : Plasion(neodevice) {

View File

@ -11,7 +11,7 @@ namespace icsneo {
class NeoVIPLASMA : public Plasion { class NeoVIPLASMA : public Plasion {
public: public:
// USB PID is 0x0801, standard driver is DXX // USB PID is 0x0801, standard driver is DXX
ICSNEO_FINDABLE_DEVICE_BY_PID(NeoVIPLASMA, DeviceType::PLASMA, 0x0801); ICSNEO_FINDABLE_DEVICE(NeoVIPLASMA, DeviceType::PLASMA, "30");
private: private:
NeoVIPLASMA(neodevice_t neodevice, const driver_factory_t& makeDriver) : Plasion(neodevice) { NeoVIPLASMA(neodevice_t neodevice, const driver_factory_t& makeDriver) : Plasion(neodevice) {

View File

@ -43,6 +43,8 @@ public:
// Until VNET support is added, assume we have one FIRE 2 VNET or FlexRay VNETZ as the main // Until VNET support is added, assume we have one FIRE 2 VNET or FlexRay VNETZ as the main
size_t getEthernetActivationLineCount() const override { return 1; } size_t getEthernetActivationLineCount() const override { return 1; }
bool supportsComponentVersions() const override { return true; }
protected: protected:
using Device::Device; using Device::Device;

View File

@ -12,7 +12,7 @@ namespace icsneo {
class ValueCAN3 : public Device { class ValueCAN3 : public Device {
public: public:
// USB PID is 0x0601, standard driver is DXX // USB PID is 0x0601, standard driver is DXX
ICSNEO_FINDABLE_DEVICE_BY_PID(ValueCAN3, DeviceType::VCAN3, 0x0601); ICSNEO_FINDABLE_DEVICE_BY_SERIAL_RANGE(ValueCAN3, DeviceType::VCAN3, "80000", "139999");
static const std::vector<Network>& GetSupportedNetworks() { static const std::vector<Network>& GetSupportedNetworks() {
static std::vector<Network> supportedNetworks = { static std::vector<Network> supportedNetworks = {

View File

@ -20,9 +20,13 @@ void DXX::Find(std::vector<FoundDevice>& found) {
static libredxx_find_filter filters[] = { static libredxx_find_filter filters[] = {
{ LIBREDXX_DEVICE_TYPE_D2XX, { ICS_USB_VID, 0x0005 } }, // RAD-Star 2 { LIBREDXX_DEVICE_TYPE_D2XX, { ICS_USB_VID, 0x0005 } }, // RAD-Star 2
{ LIBREDXX_DEVICE_TYPE_D2XX, { ICS_USB_VID, 0x0006 } }, // RAD-A2B Rev A { LIBREDXX_DEVICE_TYPE_D2XX, { ICS_USB_VID, 0x0006 } }, // RAD-A2B Rev A
{ LIBREDXX_DEVICE_TYPE_D2XX, { ICS_USB_VID, 0x0601 } }, // ValueCAN 3
{ LIBREDXX_DEVICE_TYPE_D2XX, { ICS_USB_VID, 0x0701 } }, // FIRE
{ LIBREDXX_DEVICE_TYPE_D2XX, { ICS_USB_VID, 0x0901 } }, // neoVI ION
{ LIBREDXX_DEVICE_TYPE_D2XX, { ICS_USB_VID, 0x1000 } }, // neoVI FIRE2 { LIBREDXX_DEVICE_TYPE_D2XX, { ICS_USB_VID, 0x1000 } }, // neoVI FIRE2
{ LIBREDXX_DEVICE_TYPE_D3XX, { ICS_USB_VID, 0x1201 } }, // RAD-SuperMoon { LIBREDXX_DEVICE_TYPE_D3XX, { ICS_USB_VID, 0x1201 } }, // RAD-SuperMoon
{ LIBREDXX_DEVICE_TYPE_D3XX, { ICS_USB_VID, 0x1202 } }, // RAD-Moon2 { LIBREDXX_DEVICE_TYPE_D3XX, { ICS_USB_VID, 0x1202 } }, // RAD-Moon2
{ LIBREDXX_DEVICE_TYPE_D3XX, { ICS_USB_VID, 0x1205 } }, // RAD-Moon2
{ LIBREDXX_DEVICE_TYPE_D3XX, { ICS_USB_VID, 0x1203 } }, // RAD-Gigalog { LIBREDXX_DEVICE_TYPE_D3XX, { ICS_USB_VID, 0x1203 } }, // RAD-Gigalog
{ LIBREDXX_DEVICE_TYPE_D3XX, { ICS_USB_VID, 0x1204 } }, // RAD-Gigastar { LIBREDXX_DEVICE_TYPE_D3XX, { ICS_USB_VID, 0x1204 } }, // RAD-Gigastar
{ LIBREDXX_DEVICE_TYPE_D3XX, { ICS_USB_VID, 0x1206 } }, // RAD-A2B Rev B { LIBREDXX_DEVICE_TYPE_D3XX, { ICS_USB_VID, 0x1206 } }, // RAD-A2B Rev B
@ -67,7 +71,8 @@ void DXX::Find(std::vector<FoundDevice>& found) {
} }
auto& device = found.emplace_back(); auto& device = found.emplace_back();
std::copy(serial.serial, serial.serial + sizeof(device.serial), device.serial); // -1 to make sure serial has a trailing '\0'
std::copy(serial.serial, serial.serial + (sizeof(device.serial) - 1), device.serial);
device.makeDriver = [id, type](device_eventhandler_t err, neodevice_t& forDevice) { device.makeDriver = [id, type](device_eventhandler_t err, neodevice_t& forDevice) {
return std::make_unique<DXX>(err, forDevice, id.pid, type); return std::make_unique<DXX>(err, forDevice, id.pid, type);
}; };
@ -104,7 +109,8 @@ bool DXX::open() {
EventManager::GetInstance().add(eventError(status), APIEvent::Severity::EventWarning); EventManager::GetInstance().add(eventError(status), APIEvent::Severity::EventWarning);
continue; continue;
} }
if(strcmp(serial.serial, neodevice.serial) == 0) {
if(strncmp(serial.serial, neodevice.serial, sizeof(neodevice.serial) - 1) == 0) {
foundDevice = foundDevices[i]; foundDevice = foundDevices[i];
break; break;
} }

View File

@ -7,6 +7,8 @@
using namespace icsneo; using namespace icsneo;
#define SERIAL_SIZE 6
CDCACM::CDCACM(const device_eventhandler_t& err, const std::wstring& path) : Driver(err), path(path) { CDCACM::CDCACM(const device_eventhandler_t& err, const std::wstring& path) : Driver(err), path(path) {
} }
@ -205,14 +207,23 @@ void CDCACM::Find(std::vector<FoundDevice>& found) {
continue; continue;
} }
std::wstring wserial; auto serialOffset = deviceInstanceId.find_last_of('\\');
while(!SetupDiGetDevicePropertyW(deviceInfoSet, deviceInfoData, &DEVPKEY_Device_BusReportedDeviceDesc, &DataT, reinterpret_cast<PBYTE>(wserial.data()), static_cast<DWORD>((wserial.size() + 1) * WSTRING_ELEMENT_SIZE), &buffersize, 0)) {
wserial.resize((buffersize - 1) / WSTRING_ELEMENT_SIZE); if(serialOffset == std::string::npos) {
continue;
} }
FoundDevice device; ++serialOffset; // move past '\'
if(WideCharToMultiByte(CP_ACP, 0, wserial.c_str(), (int)wserial.size(), device.serial, sizeof(device.serial), NULL, NULL) == 0) { if(deviceInstanceId.size() < serialOffset + SERIAL_SIZE) {
continue;
}
std::wstring wserial(deviceInstanceId.c_str() + serialOffset, SERIAL_SIZE);
FoundDevice device = {0};
if(WideCharToMultiByte(CP_ACP, 0, wserial.c_str(), (int)wserial.size(), device.serial, SERIAL_SIZE, NULL, NULL) == 0) {
EventManager::GetInstance().add(APIEvent::Type::SyscallError, APIEvent::Severity::Error); EventManager::GetInstance().add(APIEvent::Type::SyscallError, APIEvent::Severity::Error);
continue; continue;
} }