POSIX: STM32: Check re-enumeration by inode

This is much more stable than waiting for a set amount of time
We still timeout at 5s, if we see that being hit it can be increased
pull/35/head
Paul Hollinsky 2021-05-04 22:22:30 -04:00
parent b7c7d4349a
commit 6d22b1e001
2 changed files with 32 additions and 3 deletions

View File

@ -6,7 +6,9 @@
#include "icsneo/communication/driver.h" #include "icsneo/communication/driver.h"
#include "icsneo/device/neodevice.h" #include "icsneo/device/neodevice.h"
#include "icsneo/api/eventmanager.h" #include "icsneo/api/eventmanager.h"
#include "icsneo/platform/optional.h"
#include <chrono> #include <chrono>
#include <sys/stat.h>
#include <stdint.h> #include <stdint.h>
namespace icsneo { namespace icsneo {
@ -37,6 +39,7 @@ public:
private: private:
neodevice_t& device; neodevice_t& device;
int fd = -1; int fd = -1;
optional<ino_t> disallowedInode;
std::atomic<bool> modeChanging{false}; std::atomic<bool> modeChanging{false};
std::thread modeChangeThread; std::thread modeChangeThread;
std::mutex modeChangeMutex; std::mutex modeChangeMutex;

View File

@ -35,10 +35,28 @@ bool STM32::open() {
// Some devices can take a while to boot // Some devices can take a while to boot
for(int i = 0; i != 50; ++i) { for(int i = 0; i != 50; ++i) {
fd = ::open(ttyPath.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); fd = ::open(ttyPath.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
if(fd != -1)
break; if(fd != -1) {
// Opened successfully, check if it's the same inode as the disallowed one
// The inode is disallowed if we're expecting the device to re-enumerate (modeChanging)
if(disallowedInode.has_value()) {
struct stat fileStat = {};
if(fstat(fd, &fileStat) >= 0) {
if(fileStat.st_ino != *disallowedInode)
break;
}
} else {
break;
}
// This is still the old device, wait and try again
::close(fd);
fd = -1;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100)); std::this_thread::sleep_for(std::chrono::milliseconds(100));
} }
disallowedInode.reset();
if(!isOpen()) { if(!isOpen()) {
//std::cout << "Open of " << ttyPath.c_str() << " failed with " << strerror(errno) << ' '; //std::cout << "Open of " << ttyPath.c_str() << " failed with " << strerror(errno) << ' ';
report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error);
@ -110,6 +128,15 @@ bool STM32::close() {
closing = false; closing = false;
disconnected = false; disconnected = false;
if(modeChanging) {
// We're expecting this inode to go away after we close the device
// In order to block waiting for this to happen, we first need to
// get the inode.
struct stat fileStat = {};
if(fstat(fd, &fileStat) >= 0)
disallowedInode = fileStat.st_ino;
}
int ret = ::close(fd); int ret = ::close(fd);
fd = -1; fd = -1;
@ -120,7 +147,6 @@ bool STM32::close() {
if(modeChanging) { if(modeChanging) {
modeChanging = false; modeChanging = false;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
return open(); // Reopen the reenumerated device return open(); // Reopen the reenumerated device
} }