From 6d22b1e00179577433aed975f30f2cb3cae3d2e3 Mon Sep 17 00:00:00 2001 From: Paul Hollinsky Date: Tue, 4 May 2021 22:22:30 -0400 Subject: [PATCH] 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 --- include/icsneo/platform/posix/stm32.h | 3 +++ platform/posix/stm32.cpp | 32 ++++++++++++++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/include/icsneo/platform/posix/stm32.h b/include/icsneo/platform/posix/stm32.h index 45f7517..c20bf04 100644 --- a/include/icsneo/platform/posix/stm32.h +++ b/include/icsneo/platform/posix/stm32.h @@ -6,7 +6,9 @@ #include "icsneo/communication/driver.h" #include "icsneo/device/neodevice.h" #include "icsneo/api/eventmanager.h" +#include "icsneo/platform/optional.h" #include +#include #include namespace icsneo { @@ -37,6 +39,7 @@ public: private: neodevice_t& device; int fd = -1; + optional disallowedInode; std::atomic modeChanging{false}; std::thread modeChangeThread; std::mutex modeChangeMutex; diff --git a/platform/posix/stm32.cpp b/platform/posix/stm32.cpp index f56945a..46e0f4b 100644 --- a/platform/posix/stm32.cpp +++ b/platform/posix/stm32.cpp @@ -35,10 +35,28 @@ bool STM32::open() { // Some devices can take a while to boot for(int i = 0; i != 50; ++i) { 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)); } + disallowedInode.reset(); if(!isOpen()) { //std::cout << "Open of " << ttyPath.c_str() << " failed with " << strerror(errno) << ' '; report(APIEvent::Type::DriverFailedToOpen, APIEvent::Severity::Error); @@ -110,6 +128,15 @@ bool STM32::close() { closing = 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); fd = -1; @@ -120,7 +147,6 @@ bool STM32::close() { if(modeChanging) { modeChanging = false; - std::this_thread::sleep_for(std::chrono::milliseconds(2000)); return open(); // Reopen the reenumerated device }