Readfile на HID иногда дает неправильные значения - PullRequest
1 голос
/ 13 ноября 2010

У меня есть соединение для 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 всегда печатает полученные данные в шестнадцатеричном формате.Иногда я получаю правильные данные, но иногда массив загружается только с 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);

Я незнаю почему, но теперь это работает (не нормально, потому что имеет задержку 500 мс).

Что вы думаете?Может быть, ReadFile и WriteFile не работают одновременно?

Что вызывает это?Я что-то пропустил?

Ответы [ 2 ]

2 голосов
/ 14 ноября 2010

Есть несколько дополнительных проблем:

  • Создать событие ручного сброса (CreateEvent (NULL, TRUE, FALSE, NULL)) вместо события автоматического сброса (CreateEvent (NULL, FALSE, FALSE, NULL)).

  • Проверьте, вернул ли ReadFile значение FALSE и имеет ли значение GetLastError ERROR_IO_PENDING, и в этом случае дождитесь события (WaitForSingleObject).

  • Если WaitForSingleObject возвращает WAIT_OBJECT_0, тогда вы вызываете GetOverlappedResult.

    Передача lpNumberOfBytesRead не требуется, если вы используете GetOverlappedResult, потому что эта функция также возвращает это значение.

1 голос
/ 14 ноября 2010

Вы не должны повторять ReadFile после тайм-аута, но снова WaitForSingleObject. У вас еще есть ожидающие чтения. Цикл бедного человека (вы, вероятно, должны его уточнить, чтобы пользователь мог его прервать):

DWORD waitError;
do
{
    waitError = WaitForSingleObject(ReportEvent, timeout);
}
while (waitError == WAIT_TIMEOUT);
...