Pregunta

Tengo una conexión para un 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;
}

Tengo un hilo que siempre se lee esta manija para los nuevos mensajes:

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);
        }
    }
}

Mi función de escritura:

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);

salida de la consola:

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 siempre imprime los datos recibidos en formato hexadecimal. A veces me da los datos correctos, pero a veces la matriz sólo se carga con 00 00 00 00 00 00 00 00 00 00 00 ...

he experimentado que, cuando hago una escritura, siempre vuelva un informe, que contiene sólo 00 de esta y aparece antes de mi función de escritura hacer la escritura en la salida de la consola.

Yo estaba desesperado, así que probó esto:

do 
            {
                waitError = WaitForSingleObject(readReportEvent, timeout);
                Sleep(500);
            } while (waitError == WAIT_TIMEOUT && opened && readThreadNextStatus);

No sé por qué, pero ahora funciona (no muy bien, ya que cuenta con 500 ms de retardo).

¿Qué opinas? Tal vez ReadFile y WriteFile no funcionan al mismo tiempo?

¿Cuál es la causa? ¿Me he perdido algo?

¿Fue útil?

Solución

Hay algunos problemas adicionales:

  • Crear evento de rearme manual (CreateEvent (NULL, TRUE, FALSE, NULL)) en lugar de eventos auto-reset (CreateEvent (NULL, FALSO, FALSO, NULL)).

  • Comprobar si ReadFile devuelve FALSO y el valor de GetLastError es ERROR_IO_PENDING, y en este caso espera para el evento (WaitForSingleObject).

  • Si WaitForSingleObject devuelve WAIT_OBJECT_0 continuación, se llama a GetOverlappedResult.

    Pass lpNumberOfBytesRead no es necesario si se utiliza GetOverlappedResult porque esta función devuelve un valor demasiado.

Otros consejos

No se supone que ReadFile repetir después de tiempo de espera, pero a WaitForSingleObject nuevo. Todavía tengo pendiente leer. lazo del hombre pobre (probablemente debería refinarlo, por lo que el usuario puede abortar):

DWORD waitError;
do
{
    waitError = WaitForSingleObject(ReportEvent, timeout);
}
while (waitError == WAIT_TIMEOUT);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top