0

Does anyone have suggestions for using the WinUSB API to do overlapped read/write? The code that I wrote is always timing out - I suspect that I am using the API incorrectly to do overlapped read/write. Does anyone have any suggestions?

void MultiBlockTransfer(
    PrintParameters& parameters, 
    HANDLE hFile, 
    LARGE_INTEGER fileSize)
{
    const size_t BlockSize = parameters.PipeOutPacketSize * 8;

    LocalBuffer localBuffer(::LocalAlloc(LPTR, BlockSize));

    UCHAR* fileBuffer = (UCHAR*) localBuffer.GetBuffer();

    DWORD bytesRead = 0;

    DWORD totalBytesWritten = 0;

    do
    {
            if (!::ReadFile(hFile, fileBuffer, (DWORD) BlockSize, &bytesRead, NULL))
    {
        return;
    }

    if (bytesRead == 0)
    {
        break;
    }

    ULONG lengthTransferred = 0;

    OVERLAPPED overlappedWrite;
    OVERLAPPED overlappedRead;
    ZeroMemory(&overlappedWrite, sizeof(OVERLAPPED));
    ZeroMemory(&overlappedRead, sizeof(OVERLAPPED));

    Handle writeEvent(::CreateEvent(NULL, TRUE, FALSE, L"WriteUSBPipe"));
    Handle readEvent(::CreateEvent(NULL, TRUE, FALSE, L"ReadUsbPipe"));

    overlappedWrite.hEvent = writeEvent.GetHandle();
    overlappedWrite.Internal = STATUS_PENDING;
    overlappedRead.hEvent = readEvent.GetHandle();
    overlappedRead.Internal = STATUS_PENDING;

    ULONG readBlockSize = parameters.PipeOutPacketSize * 16;

    LocalBuffer localReadBuffer(::LocalAlloc(LPTR, readBlockSize));

    UCHAR* readBuffer = (UCHAR*) localReadBuffer.GetBuffer();
    ULONG lengthWritten = 0;
    ULONG lengthRead = 0;

    if (!::WinUsb_WritePipe(parameters.usbHandle, parameters.PipeOutId, fileBuffer, bytesRead, &lengthWritten, &overlappedWrite))
    {
        DWORD error = ::GetLastError();

        if (error != ERROR_IO_PENDING)
        {
            stringstream stream;
            stream << "Error writing to USB: " << LastErrorString;

            throw exception(stream.str().c_str());
        }
    }

    if (!::WinUsb_ReadPipe(parameters.usbHandle, parameters.PipeInId, readBuffer, readBlockSize, &lengthRead, &overlappedRead))
    {
        DWORD error = ::GetLastError();

        if (error != ERROR_IO_PENDING)
        {
            stringstream stream;
            stream << "Error reading from USB: " << LastErrorString;

            throw exception(stream.str().c_str());
        }
    }

    HANDLE events [] =
    {
        overlappedWrite.hEvent,
        overlappedRead.hEvent
    };

    DWORD waitResult = ::WaitForMultipleObjects(2, events, TRUE, 10000);

    switch (waitResult)
    {
    case WAIT_OBJECT_0:
        ::WinUsb_GetOverlappedResult(parameters.usbHandle, &overlappedWrite, &lengthWritten, TRUE);
        ::WinUsb_GetOverlappedResult(parameters.usbHandle, &overlappedRead, &lengthRead, TRUE);
        break;

    case WAIT_ABANDONED:
        throw exception("Wait for USB write/read abandoned");

    case WAIT_TIMEOUT:
        throw exception("Wait for USB write/read timed out.");

    case WAIT_FAILED:
        {
            stringstream stream;
            stream << "Wait for USB write/read failed: " << LastErrorString;
            throw exception(stream.str().c_str());
        }
    default:
        {
            stringstream stream;
            stream << "Wait for USB write/read failed with: " << waitResult;
            throw exception(stream.str().c_str());
        }
    }

    string readResult((char*) readBuffer);

    basic_stringstream<TCHAR> statusStream;

    totalBytesWritten += lengthTransferred;
    } while (bytesRead == BlockSize);
}
Michael S. Scherotter
  • 10,715
  • 3
  • 34
  • 57
  • Harry, The WaitForMultipleObjects() returns WAIT_OBJECT_0 if the third parameter is TRUE since it waits for all objects to be signaled. – Michael S. Scherotter Jun 17 '15 at 14:17
  • You're quite right, my mistake. A few more thoughts. (1) Do you know which of the operations is timing out, or whether both are? (2) Have you checked whether either or both operations are completing synchronously, i.e., not reporting ERROR_IO_PENDING? I'm not sure what happens in that case. – Harry Johnston Jun 17 '15 at 21:16
  • the write operation is timing out. – Michael S. Scherotter Jul 04 '15 at 21:33

0 Answers0