私のアプリケーションは、USB ベースの FTDI チップと D2XX ドライバーを使用しています。OIO (Overlapped IO) を使用して、USB への読み取りと書き込みを行います。私の要件には 30 秒のタイムアウトが含まれており、これを減らすことはできません。コードは非常に堅牢で安定しているように見えます。
新しい要件は、USB ケーブルの不注意による切断と再接続 (看護師がケーブルを蹴り飛ばした) を克服することです。
Windows からデバイス削除メッセージを受信し、それが FTDI デバイスであると判断すると、以前の OIO 呼び出しタイムアウト (要件からの 30 秒のタイムアウト) まで、OIO からの再接続で新しいデータを受信できないことがわかりました。
切断を発見したら、キューに入れられたすべての OIO が取得されるまで、次の呼び出しをループします。
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;
}
タイムアウト期間を 1ms に設定しました。これは、以前にスケジュールされた OIO のタイムアウトを変更するようには見えません。
私はFT_W32_PurgeComm
すべてをキャンセルするために電話しました。これも、OIO をキャンセルするようには見えません。
呼び出しCancelIo
てみましたが、エラーが返されました。ハンドルが無効です。私の理解では、それに応答するのはドライバーコードです。切断が原因である可能性があります。
とにかく、スケジュールされたすべての OIO が取得されるまで、上記のコードをループで呼び出します。30秒間何も起こりません。その後、すべての OIO が 1 ミリ秒未満で終了するようです。
このコードのテストとして、USB ケーブルを接続して呼び出したところ、1ms で返ってきました。
したがって、問題はケーブルを抜いたときのようです。
質問: 何が欠けていますか? 他にかけられる電話はありますか?これはバグですか?
私が試した他のこと: を呼び出す前にハンドルを閉じFT_W32_GetOverlappedResult
ます。これにより、リターンが速くなります。しかし、私のアプリは新しいハンドルからデータを受信できなくなりました。変。理由を知っている人はいますか?
このコードを呼び出していません。アプリは新しいハンドルから新しいデータを受信できますが、これらのタイムアウト後にのみです。なぜ?
サイクルポート。これにより、これらの OIO がより迅速に戻ることはありません。これらのタイムアウトまで、OIO 受信データの使用は変更されません。