Driver: D3XX: Refactor pipe logic

pull/64/merge
Kyle Schwarz 2025-04-15 17:44:58 -04:00
parent 70733b3d96
commit e88cd244c8
1 changed files with 50 additions and 48 deletions

View File

@ -65,6 +65,7 @@ bool FTD3XX::open() {
handle.emplace(tmpHandle); handle.emplace(tmpHandle);
setIsClosing(false); setIsClosing(false);
setIsDisconnected(false);
readThread = std::thread(&FTD3XX::readTask, this); readThread = std::thread(&FTD3XX::readTask, this);
writeThread = std::thread(&FTD3XX::writeTask, this); writeThread = std::thread(&FTD3XX::writeTask, this);
@ -82,7 +83,9 @@ bool FTD3XX::close() {
} }
setIsClosing(true); setIsClosing(true);
setIsDisconnected(false);
// unblock the read thread
FT_AbortPipe(*handle, READ_PIPE_ID);
if(readThread.joinable()) if(readThread.joinable())
readThread.join(); readThread.join();
@ -105,76 +108,75 @@ bool FTD3XX::close() {
void FTD3XX::readTask() { void FTD3XX::readTask() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread(); EventManager::GetInstance().downgradeErrorsOnCurrentThread();
static constexpr auto bufferSize = 2048; std::vector<uint8_t> buffer(2 * 1024 * 1024);
uint8_t buffer[bufferSize] = {};
FT_SetStreamPipe(*handle, false, false, READ_PIPE_ID, (ULONG)buffer.size());
// disable timeouts, we will interupt the read thread with AbortPipe
FT_SetPipeTimeout(*handle, READ_PIPE_ID, 0);
OVERLAPPED overlapped = {};
FT_InitializeOverlapped(*handle, &overlapped);
FT_STATUS status;
ULONG received = 0;
FT_SetStreamPipe(*handle, false, false, READ_PIPE_ID, bufferSize);
FT_SetPipeTimeout(*handle, READ_PIPE_ID, 1);
while(!isClosing() && !isDisconnected()) { while(!isClosing() && !isDisconnected()) {
ULONG received = 0; received = 0;
OVERLAPPED overlap = {};
FT_InitializeOverlapped(*handle, &overlap);
#ifdef _WIN32 #ifdef _WIN32
FT_ReadPipe(*handle, READ_PIPE_ID, buffer, bufferSize, &received, &overlap); status = FT_ReadPipe(*handle, READ_PIPE_ID, buffer.data(), (ULONG)buffer.size(), &received, &overlapped);
#else #else
FT_ReadPipeAsync(*handle, 0, buffer, bufferSize, &received, &overlap); status = FT_ReadPipeAsync(*handle, 0, buffer.data(), buffer.size(), &received, &overlapped);
#endif #endif
while(!isClosing()) { if(FT_FAILED(status)) {
const auto ret = FT_GetOverlappedResult(*handle, &overlap, &received, true); if(status != FT_IO_PENDING) {
if(ret == FT_IO_PENDING) addEvent(status, APIEvent::Severity::Error);
continue; setIsDisconnected(true);
if(ret != FT_OK) { break;
if(ret == FT_IO_ERROR) { }
setIsDisconnected(true); status = FT_GetOverlappedResult(*handle, &overlapped, &received, true);
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error); if(FT_FAILED(status)) {
} else { addEvent(status, APIEvent::Severity::Error);
addEvent(ret, APIEvent::Severity::Error); setIsDisconnected(true);
} break;
FT_AbortPipe(*handle, READ_PIPE_ID); }
if(received > 0) {
pushRx(buffer.data(), received);
} }
break;
}
FT_ReleaseOverlapped(*handle, &overlap);
if(received > 0) {
pushRx(buffer, received);
} }
} }
FT_ReleaseOverlapped(*handle, &overlapped);
} }
void FTD3XX::writeTask() { void FTD3XX::writeTask() {
EventManager::GetInstance().downgradeErrorsOnCurrentThread(); EventManager::GetInstance().downgradeErrorsOnCurrentThread();
FT_SetPipeTimeout(*handle, WRITE_PIPE_ID, 100); FT_SetPipeTimeout(*handle, WRITE_PIPE_ID, 0);
WriteOperation writeOp; WriteOperation writeOp;
ULONG sent;
FT_STATUS status;
while(!isClosing() && !isDisconnected()) { while(!isClosing() && !isDisconnected()) {
if(!writeQueue.wait_dequeue_timed(writeOp, std::chrono::milliseconds(100))) if(!writeQueue.wait_dequeue_timed(writeOp, std::chrono::milliseconds(100)))
continue; continue;
const auto size = static_cast<ULONG>(writeOp.bytes.size()); const auto size = static_cast<ULONG>(writeOp.bytes.size());
ULONG sent = 0; sent = 0;
OVERLAPPED overlap = {};
FT_InitializeOverlapped(*handle, &overlap);
FT_SetStreamPipe(*handle, false, false, WRITE_PIPE_ID, size);
#ifdef _WIN32 #ifdef _WIN32
FT_WritePipe(*handle, WRITE_PIPE_ID, writeOp.bytes.data(), size, &sent, &overlap); status = FT_WritePipe(*handle, WRITE_PIPE_ID, writeOp.bytes.data(), size, &sent, nullptr);
#else #else
FT_WritePipeAsync(*handle, 0, writeOp.bytes.data(), size, &sent, &overlap); status = FT_WritePipe(*handle, WRITE_PIPE_ID, writeOp.bytes.data(), size, &sent, 100);
#endif #endif
while(!isClosing()) { if(FT_FAILED(status)) {
const auto ret = FT_GetOverlappedResult(*handle, &overlap, &sent, true); addEvent(status, APIEvent::Severity::Error);
if(ret == FT_IO_PENDING) setIsDisconnected(true);
continue; break;
if(ret != FT_OK) { }
if(ret == FT_IO_ERROR) { if(sent != size) {
setIsDisconnected(true); report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error);
report(APIEvent::Type::DeviceDisconnected, APIEvent::Severity::Error); setIsDisconnected(true);
} else {
addEvent(ret, APIEvent::Severity::Error);
}
FT_AbortPipe(*handle, WRITE_PIPE_ID);
}
break; break;
} }
FT_ReleaseOverlapped(*handle, &overlap);
} }
} }