HIDのReadFileは、間違った値を与えることがあります
質問
Wiimoteの接続があります
handle = CreateFile(didetail->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if(handle != INVALID_HANDLE_VALUE) {
opened = true;
readReportEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
memset(&readOverlapped, 0, sizeof(readOverlapped));
readOverlapped.hEvent = readReportEvent;
readOverlapped.Offset = 0;
readOverlapped.OffsetHigh = 0;
writeReportEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
memset(&writeOverlapped, 0, sizeof(writeOverlapped));
writeOverlapped.hEvent = readReportEvent;
writeOverlapped.Offset = 0;
writeOverlapped.OffsetHigh = 0;
}
新しいメッセージのために常にこのハンドルを読むスレッドがあります:
while(opened && readThreadNextStatus){
memset (readBuff, 0, 22);
BYTE* ptrbuff = new BYTE[22];
int readfile = ReadFile(handle, readBuff, reportLength, NULL, &readOverlapped);
if(readfile == 0 && GetLastError() == ERROR_IO_PENDING){
DWORD waitError;
do
{
waitError = WaitForSingleObject(readReportEvent, timeout);
} while (waitError == WAIT_TIMEOUT && opened && readThreadNextStatus);
if(opened && readThreadNextStatus){
DWORD read = 0;
if(waitError == WAIT_OBJECT_0){
GetOverlappedResult(handle, &readOverlapped, &read, TRUE);
}
ResetEvent(readReportEvent);
memcpy(ptrbuff, readBuff, 22);
cout << "Read: ";
coutHex(ptrbuff);
}
}
}
私の書き込み関数:
if(opened){
if(!WriteFile(handle, buff, reportLength, NULL, &writeOverlapped)){
if(GetLastError() != ERROR_IO_PENDING){
close();
}
}
WaitForSingleObject(writeReportEvent, timeout);
DWORD write = 0;
GetOverlappedResult(handle, &writeOverlapped, &write, TRUE);
ResetEvent(writeReportEvent);
}
cout << "Write: ";
coutHex(buff);
コンソール出力:
Connection established
Write: 15- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0-
Read: 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0-
Read: 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0-
Write: 15- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0-
Read: 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0-
Write: 15- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0-
Read: 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0-
Read: 20- 0- 0-10- 0- 0-49-ff-ff-ff-ff-ff-ff-ff-ff-ff-ff-ff-ff-ff-ff-ff-
Write: 15- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0-
Read: 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0-
Write: 15- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0
Read: 0- 0-
0- 0-
- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0- 0-
Couthexは常に、受信したデータを16進形式で印刷します。時々私は正しいデータを取得しますが、アレイに00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00時々
書き込みをするとき、私は常にレポートを取り戻します。これにはわずか00が含まれており、これは私の書き込み関数がコンソール出力で書き込みを行う前に表示されます。
私は必死だったので、これを試しました:
do
{
waitError = WaitForSingleObject(readReportEvent, timeout);
Sleep(500);
} while (waitError == WAIT_TIMEOUT && opened && readThreadNextStatus);
理由はわかりませんが、今では機能します(500ms遅延があるため、うまくいきません)。
どう思いますか?たぶんReadFileとWriteFileは同時に動作しませんか?
何がこれを引き起こしますか?私は何か見落としてますか?
解決
いくつかの追加の問題があります:
マニュアルリセットイベント(CreateEvent(null、true、false、null))を作成します。
ReadFileがFALSEを返し、GetLasterRorの値がERROR_IO_PENDINGであるかどうかを確認し、この場合はイベントを待ちます(WaitForsIngleObject)。
waitforsingleobjectがwait_object_0を返した場合、getOverlaptResultを呼び出します。
この関数がこの値を返すため、getOverlappedResultを使用する場合、pass lpnumberofbytesReadは必要ありません。
他のヒント
あなたは繰り返されるべきではありません ReadFile
タイムアウト後、しかし WaitForSingleObject
また。あなたはまだ保留中の読みがあります。かわいそうな人のループ(おそらく、ユーザーがそれを中止できるように、おそらくそれを洗練する必要があります):
DWORD waitError;
do
{
waitError = WaitForSingleObject(ReportEvent, timeout);
}
while (waitError == WAIT_TIMEOUT);