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