2010-11-13 4 views
1

У меня есть соединение для WiimoteReadFile на HID иногда дает неправильные значения

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

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

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

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

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

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

+0

Я редактировал свой оригинальный вопрос с вашими идеями, пожалуйста, проверьте код. Это не решает проблему. –

+1

Поместите ResetEvent (ReportEvent) после GetOverlappedResult, потому что, когда эта функция возвращает событие, установлено (вы используете TRUE как параметр bWait). Вам не нужно помещать ResetEvent (ReportEvent) перед GetOverlappedResul, потому что эта функция сбрасывает событие. –

+0

Спасибо, я изменил его, но такая же проблема существует: S –

1

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

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

Спасибо за ваш ответ, я добавил его в свой код в вопросе. Для первого запуска я решил, что он решил проблему, но после некоторого тестирования я снова испытал проблему. Я добавил консольный вывод о пакетах. –

+0

, если (waitError == WAIT_OBJECT_0) часть должна охватывать все четыре строки до конца блока. Если открыт && readThreadNextStatus является ложным из самого внутреннего цикла, вы не хотите печатать данные, которых у вас нет. – Dialecticus

+0

Это правда, спасибо, я изменил его. –

Смежные вопросы