1

My application uses a USB based FTDI chip and the D2XX driver. It uses OIO (Overlapped IO) to read and write to the USB. My requirements include a 30 second timeout, something I cannot reduce. The code appear quite robust and stable.

A new requirement is overcoming an inadvertent disconnect and reconnect of the USB cable (a nurse kicked the cable out).

Once receiving the device removed message from windows and determining that it is our FTDI device I found that I cannot receive new data on a reconnect from the OIO until the previous OIO calls timeout (the 30 second timeout from requirements).

Once I discover the disconnect, I loop on the following call until all queued up OIO are reaped:

bool CancelOIO()
{
    if (!FtdiRemaining)
        return false;

    FT_SetTimeouts(FtdiHandle, 1, 1);
    FT_W32_PurgeComm(FtdiHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

    while (FtdiRemaining)
    {
        DWORD nBytes = 0;
        if (!FT_W32_GetOverlappedResult(FtdiHandle, &FtdiOverLap[FtdiQindex], &nBytes, FALSE))
        {
            if (FT_W32_GetLastError(FtdiHandle) == ERROR_IO_INCOMPLETE)
                return true;

            if (FT_W32_GetLastError(FtdiHandle) != ERROR_OPERATION_ABORTED)
            {
                CString str;
                str.Format("FT_W32_GetOverlappedResult failed with %d\r\n", FT_W32_GetLastError(FtdiHandle));
                SM_WriteLog(str, RGB_LOG_NORMAL);
            }
        }

        FtdiRemaining--;
        FtdiTodo++;
        FtdiQindex++;
        if (FtdiQindex >= FtdiQueueSize)
            FtdiQindex = 0;
    }

    return !!FtdiRemaining;
}

I set the timeout period to 1ms. This does not appear to change the timeout for previously scheduled OIO.

I called FT_W32_PurgeComm to cancel everything. This also does not appear to cancel the OIO.

I tried calling CancelIo and this returned an error, the handle is not valid. My understanding is that it is up the driver code to respond to it. It might be due to the disconnect.

Anyway, I call the above code in a loop until all scheduled OIO are reaped. Nothing happens for 30 seconds. Then all of the OIO seem to end in less than 1ms.

As a test of this code, I called with the USB cable connected and it returns in 1ms.

So the problem appears to be when the cable is unplugged.

Questions: What am I missing? Is there another call I can make? Is this a bug?

Other things I tried: Closing the handle before calling FT_W32_GetOverlappedResult. This results in fast return. But my app can no longer receive data from the new handle. Weird. Anyone know why?

Not calling this code. The app is able to receive new data from the new handle, but only after these timeout. why?

CyclePort. This does not cause these OIO to return more quickly. It does not change the use of the OIO receiving data until these timeout.

user3097514
  • 319
  • 2
  • 6

1 Answers1

0

I found after repeated tests two distinct behaviors. The fastest one returns reasonably quickly, canceling OIO. The other used the full 30 second timeout.

Try reducing the timeout to reduce the delay in cancelling OIO.

user3097514
  • 319
  • 2
  • 6