POSIX: STM32: Handle re-enumeration when changing modes

This commit is contained in:
Paul Hollinsky
2021-04-27 21:12:59 -04:00
parent 5733300de6
commit 622c5ee57a
4 changed files with 61 additions and 9 deletions
+44 -3
View File
@@ -14,6 +14,12 @@
using namespace icsneo;
STM32::~STM32() {
awaitModeChangeComplete();
if(isOpen())
close();
}
bool STM32::open() {
if(isOpen()) {
report(APIEvent::Type::DeviceCurrentlyOpen, APIEvent::Severity::Error);
@@ -111,6 +117,12 @@ bool STM32::close() {
WriteOperation flushop;
while (readQueue.try_dequeue(flush)) {}
while (writeQueue.try_dequeue(flushop)) {}
if(modeChanging) {
modeChanging = false;
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
return open(); // Reopen the reenumerated device
}
if(ret == 0) {
return true;
@@ -120,6 +132,18 @@ bool STM32::close() {
}
}
void STM32::modeChangeIncoming() {
modeChanging = true;
}
void STM32::awaitModeChangeComplete() {
std::unique_lock<std::mutex> lk(modeChangeMutex);
if(modeChanging && !modeChangeThread.joinable()) // Waiting for the thread to start
modeChangeCV.wait_for(lk, std::chrono::seconds(1), [this] { return modeChangeThread.joinable(); });
if(modeChangeThread.joinable())
modeChangeThread.join();
}
void STM32::readTask() {
constexpr size_t READ_BUFFER_SIZE = 2048;
uint8_t readbuf[READ_BUFFER_SIZE];
@@ -131,10 +155,27 @@ void STM32::readTask() {
tv.tv_usec = 50000; // 50ms
::select(fd + 1, &rfds, NULL, NULL, &tv);
auto bytesRead = ::read(fd, readbuf, READ_BUFFER_SIZE);
if(bytesRead > 0)
if(bytesRead > 0) {
#if 0 // Perhaps helpful for debugging :)
std::cout << "Read data: (" << bytesRead << ')' << std::hex << std::endl;
for(int i = 0; i < bytesRead; i += 16) {
for(int j = 0; j < std::min<int>(bytesRead - i, 16); j++)
std::cout << std::setw(2) << std::setfill('0') << uint32_t(readbuf[i+j]) << ' ';
std::cout << std::endl;
}
std::cout << std::dec << std::endl;
#endif
readQueue.enqueue_bulk(readbuf, bytesRead);
else {
if(!fdIsValid() && !isDisconnected()) {
} else {
if(modeChanging) {
// We were expecting a disconnect for reenumeration
modeChangeThread = std::thread([this] {
modeChangeCV.notify_all();
close(); // Which will trigger an open() due to modeChanging
});
break;
} else if(!closing && !fdIsValid() && !isDisconnected()) {
disconnected = true;
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
}