Purge read and write queues after a close succeeds
parent
82adbcaba6
commit
8a147e2c3f
|
|
@ -99,10 +99,16 @@ bool FTDI::close() {
|
||||||
|
|
||||||
closing = false;
|
closing = false;
|
||||||
|
|
||||||
|
bool ret = true;
|
||||||
if(ftdiDevice.close())
|
if(ftdiDevice.close())
|
||||||
return false;
|
ret = false;
|
||||||
|
|
||||||
return true;
|
uint8_t flush;
|
||||||
|
WriteOperation flushop;
|
||||||
|
while(readQueue.try_dequeue(flush)) {}
|
||||||
|
while(writeQueue.try_dequeue(flushop)) {}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FTDI::readTask() {
|
void FTDI::readTask() {
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,11 @@ bool STM32::close() {
|
||||||
|
|
||||||
int ret = ::close(fd);
|
int ret = ::close(fd);
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
|
||||||
|
uint8_t flush;
|
||||||
|
WriteOperation flushop;
|
||||||
|
while (readQueue.try_dequeue(flush)) {}
|
||||||
|
while (writeQueue.try_dequeue(flushop)) {}
|
||||||
|
|
||||||
return ret == 0;
|
return ret == 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,11 @@ bool PCAP::close() {
|
||||||
pcap.close(interface.fp);
|
pcap.close(interface.fp);
|
||||||
interface.fp = nullptr;
|
interface.fp = nullptr;
|
||||||
|
|
||||||
|
uint8_t flush;
|
||||||
|
WriteOperation flushop;
|
||||||
|
while(readQueue.try_dequeue(flush)) {}
|
||||||
|
while(writeQueue.try_dequeue(flushop)) {}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,82 +18,99 @@ 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;
|
||||||
|
|
||||||
std::vector<neodevice_t> VCP::FindByProduct(int product, wchar_t* driverName) {
|
std::vector<neodevice_t> VCP::FindByProduct(int product, std::vector<std::wstring> driverNames) {
|
||||||
std::vector<neodevice_t> found;
|
std::vector<neodevice_t> found;
|
||||||
|
|
||||||
std::wstringstream regss;
|
for(auto& driverName : driverNames) {
|
||||||
regss << DRIVER_SERVICES_REG_KEY << driverName << L"\\Enum\\";
|
std::wstringstream regss;
|
||||||
std::wstring driverEnumRegKey = regss.str();
|
regss << DRIVER_SERVICES_REG_KEY << driverName << L"\\Enum\\";
|
||||||
|
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;
|
return found;
|
||||||
}
|
|
||||||
|
|
||||||
for(uint32_t i = 0; i < deviceCount; i++) {
|
|
||||||
neodevice_t device = {};
|
|
||||||
|
|
||||||
// First we want to look at what devices FTDI is enumerating (inside driverEnumRegKey)
|
|
||||||
// The entry for a ValueCAN 3 with SN 138635 looks like "FTDIBUS\VID_093C+PID_0601+138635A\0000"
|
|
||||||
// The entry for a ValueCAN 4 with SN V20227 looks like "USB\VID_093C&PID_1101\V20227"
|
|
||||||
std::wstringstream ss;
|
|
||||||
ss << i;
|
|
||||||
std::wstring entry;
|
|
||||||
if(!Registry::Get(driverEnumRegKey, ss.str(), entry))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::transform(entry.begin(), entry.end(), entry.begin(), std::towupper);
|
|
||||||
|
|
||||||
std::wstringstream vss;
|
|
||||||
vss << "VID_" << std::setfill(L'0') << std::setw(4) << std::uppercase << std::hex << INTREPID_USB_VENDOR_ID; // Intrepid Vendor ID
|
|
||||||
if(entry.find(vss.str()) == std::wstring::npos)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::wstringstream pss;
|
|
||||||
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)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Okay, this is a device we want
|
|
||||||
// Get the serial number
|
|
||||||
auto startchar = entry.find(L"+", pidpos + 1);
|
|
||||||
if(startchar == std::wstring::npos)
|
|
||||||
startchar = entry.find(L"\\", pidpos + 1);
|
|
||||||
bool conversionError = false;
|
|
||||||
int sn = 0;
|
|
||||||
try {
|
|
||||||
sn = std::stoi(entry.substr(startchar + 1));
|
|
||||||
} catch(...) {
|
|
||||||
conversionError = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::wstringstream oss;
|
for(uint32_t i = 0; i < deviceCount; i++) {
|
||||||
if(!sn || conversionError) {
|
neodevice_t device = {};
|
||||||
// This is a device with characters in the serial number
|
|
||||||
oss << entry.substr(startchar + 1, 6);
|
|
||||||
} else {
|
|
||||||
oss << sn;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy_s(device.serial, sizeof(device.serial), converter.to_bytes(oss.str()).c_str());
|
// 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 4 with SN V20227 looks like "USB\VID_093C&PID_1101\V20227"
|
||||||
|
std::wstringstream ss;
|
||||||
|
ss << i;
|
||||||
|
std::wstring entry;
|
||||||
|
if(!Registry::Get(driverEnumRegKey, ss.str(), entry))
|
||||||
|
continue;
|
||||||
|
|
||||||
// Serial number is saved, we want the COM port number now
|
std::transform(entry.begin(), entry.end(), entry.begin(), std::towupper);
|
||||||
// This will be stored under ALL_ENUM_REG_KEY\entry\Device Parameters\PortName (entry from the FTDI_ENUM)
|
|
||||||
std::wstringstream dpss;
|
std::wstringstream vss;
|
||||||
dpss << ALL_ENUM_REG_KEY << entry << L"\\Device Parameters";
|
vss << "VID_" << std::setfill(L'0') << std::setw(4) << std::uppercase << std::hex << INTREPID_USB_VENDOR_ID; // Intrepid Vendor ID
|
||||||
std::wstring port;
|
if(entry.find(vss.str()) == std::wstring::npos)
|
||||||
Registry::Get(dpss.str(), L"PortName", port); // TODO If error do something else (Plasma maybe?)
|
continue;
|
||||||
std::transform(port.begin(), port.end(), port.begin(), std::towupper);
|
|
||||||
auto compos = port.find(L"COM");
|
std::wstringstream pss;
|
||||||
device.handle = 0;
|
pss << "PID_" << std::setfill(L'0') << std::setw(4) << std::uppercase << std::hex << product;
|
||||||
if(compos != std::wstring::npos) {
|
auto pidpos = entry.find(pss.str());
|
||||||
|
if(pidpos == std::wstring::npos)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Okay, this is a device we want
|
||||||
|
// Get the serial number
|
||||||
|
auto startchar = entry.find(L"+", pidpos + 1);
|
||||||
|
if(startchar == std::wstring::npos)
|
||||||
|
startchar = entry.find(L"\\", pidpos + 1);
|
||||||
|
bool conversionError = false;
|
||||||
|
int sn = 0;
|
||||||
try {
|
try {
|
||||||
device.handle = std::stoi(port.substr(compos + 3));
|
sn = std::stoi(entry.substr(startchar + 1));
|
||||||
} catch(...) {} // In case of this, or any other error, handle has already been initialized to 0
|
}
|
||||||
}
|
catch(...) {
|
||||||
|
conversionError = true;
|
||||||
|
}
|
||||||
|
|
||||||
found.push_back(device);
|
std::wstringstream oss;
|
||||||
|
if(!sn || conversionError) {
|
||||||
|
// This is a device with characters in the serial number
|
||||||
|
oss << entry.substr(startchar + 1, 6);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
oss << sn;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string serial = converter.to_bytes(oss.str());
|
||||||
|
if(serial.find_first_of('\\') != std::string::npos)
|
||||||
|
continue; // Not sure how this happened but a slash is not valid in the serial
|
||||||
|
strcpy_s(device.serial, sizeof(device.serial), serial.c_str());
|
||||||
|
|
||||||
|
// Serial number is saved, we want the COM port number now
|
||||||
|
// This will be stored under ALL_ENUM_REG_KEY\entry\Device Parameters\PortName (entry from the FTDI_ENUM)
|
||||||
|
std::wstringstream dpss;
|
||||||
|
dpss << ALL_ENUM_REG_KEY << entry << L"\\Device Parameters";
|
||||||
|
std::wstring port;
|
||||||
|
Registry::Get(dpss.str(), L"PortName", port); // TODO If error do something else (Plasma maybe?)
|
||||||
|
std::transform(port.begin(), port.end(), port.begin(), std::towupper);
|
||||||
|
auto compos = port.find(L"COM");
|
||||||
|
device.handle = 0;
|
||||||
|
if(compos != std::wstring::npos) {
|
||||||
|
try {
|
||||||
|
device.handle = std::stoi(port.substr(compos + 3));
|
||||||
|
}
|
||||||
|
catch(...) {} // In case of this, or any other error, handle has already been initialized to 0
|
||||||
|
}
|
||||||
|
|
||||||
|
bool alreadyFound = false;
|
||||||
|
for(auto& foundDev : found) {
|
||||||
|
if(foundDev.handle == device.handle && serial == foundDev.serial) {
|
||||||
|
alreadyFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!alreadyFound)
|
||||||
|
found.push_back(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return found;
|
return found;
|
||||||
|
|
@ -113,8 +130,10 @@ bool VCP::open(bool fromAsync) {
|
||||||
if(isOpen() || (!fromAsync && opening))
|
if(isOpen() || (!fromAsync && opening))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!IsHandleValid(device.handle))
|
if(!IsHandleValid(device.handle)) {
|
||||||
|
err(APIError::DriverFailedToOpen);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
opening = true;
|
opening = true;
|
||||||
|
|
||||||
|
|
@ -132,8 +151,10 @@ bool VCP::open(bool fromAsync) {
|
||||||
|
|
||||||
opening = false;
|
opening = false;
|
||||||
|
|
||||||
if(!isOpen())
|
if(!isOpen()) {
|
||||||
|
err(APIError::DriverFailedToOpen);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Set the timeouts
|
// Set the timeouts
|
||||||
COMMTIMEOUTS timeouts;
|
COMMTIMEOUTS timeouts;
|
||||||
|
|
@ -151,6 +172,7 @@ bool VCP::open(bool fromAsync) {
|
||||||
|
|
||||||
if(!SetCommTimeouts(handle, &timeouts)) {
|
if(!SetCommTimeouts(handle, &timeouts)) {
|
||||||
close();
|
close();
|
||||||
|
err(APIError::DriverFailedToOpen);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,6 +180,7 @@ bool VCP::open(bool fromAsync) {
|
||||||
DCB comstate;
|
DCB comstate;
|
||||||
if(!GetCommState(handle, &comstate)) {
|
if(!GetCommState(handle, &comstate)) {
|
||||||
close();
|
close();
|
||||||
|
err(APIError::DriverFailedToOpen);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,6 +193,7 @@ bool VCP::open(bool fromAsync) {
|
||||||
|
|
||||||
if(!SetCommState(handle, &comstate)) {
|
if(!SetCommState(handle, &comstate)) {
|
||||||
close();
|
close();
|
||||||
|
err(APIError::DriverFailedToOpen);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,12 +205,14 @@ bool VCP::open(bool fromAsync) {
|
||||||
overlappedWait.hEvent = CreateEvent(nullptr, true, false, nullptr);
|
overlappedWait.hEvent = CreateEvent(nullptr, true, false, nullptr);
|
||||||
if (overlappedRead.hEvent == nullptr || overlappedWrite.hEvent == nullptr || overlappedWait.hEvent == nullptr) {
|
if (overlappedRead.hEvent == nullptr || overlappedWrite.hEvent == nullptr || overlappedWait.hEvent == nullptr) {
|
||||||
close();
|
close();
|
||||||
|
err(APIError::DriverFailedToOpen);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up event so that we will satisfy overlappedWait when a character comes in
|
// Set up event so that we will satisfy overlappedWait when a character comes in
|
||||||
if(!SetCommMask(handle, EV_RXCHAR)) {
|
if(!SetCommMask(handle, EV_RXCHAR)) {
|
||||||
close();
|
close();
|
||||||
|
err(APIError::DriverFailedToOpen);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -238,6 +264,11 @@ bool VCP::close() {
|
||||||
overlappedWait.hEvent = INVALID_HANDLE_VALUE;
|
overlappedWait.hEvent = INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t flush;
|
||||||
|
WriteOperation flushop;
|
||||||
|
while(readQueue.try_dequeue(flush)) {}
|
||||||
|
while(writeQueue.try_dequeue(flushop)) {}
|
||||||
|
|
||||||
// TODO Set up some sort of shared memory, free which COM port we had open so we can try to open it again
|
// TODO Set up some sort of shared memory, free which COM port we had open so we can try to open it again
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue