Still the issue is not resolved. I modified the read in my thread with WaitForSingleObject(); but still no improvement.
I guess the issue could be inside my driver as well. I have pasted the skeleton of my EvtIoRead().
The read is simple; I have configured the USBCOntinuousReader which is polling the USB BUS. In the read completion routine, data is copied to a ringbuffer with spinLock.
THE PROBLEM IS THAT most of times read completion gets empty data from device and ring buffer will be empty. The device sends around 40-100 bytes of data for 60-80usec.
I see that my readthread is calling ReadFile() with no delay and this is in turn invoking UsbDeviceEvtIoRead() continuously. Most of times ReadFile get 0 as bytes read as ringbuffer is empty.
VOID UsbDeviceEvtIoRead(IN WDFQUEUE Queue, IN WDFREQUEST Request, IN size_t Length) {
…
PUSBDEVICE_DEVICE_EXTENSION pDevExt = NULL;
WDFMEMORY requestBuffer;
…
status = WdfRequestRetrieveOutputMemory(Request, &requestBuffer);
//Acquire a spinlock on a ringBUffer…
//this Ringbuffer is filled by UsbdeviceEvtBulkInPipeReadComplete which is configured in WdfUsbTargetPipeConfigContinuousReader
WdfSpinLockAcquire(pDevExt->spinLockRxMsgList);
//copy data from ring buffer… ???
// if the ringBuff
ringBuffLength = RingBufferGetLength(pDevExt->pRingBuffer[iProcessCount]);//
if (ringBuffLength <= 0)
{
completionSz = 0;
}
else
{
status = WdfRequestRetrieveOutputMemory(Request, &requestBuffer);
if (Length < ringBuffLength)
{
ringBuffLength = Length;
}
status = RingBufferRemove(pDevExt->pRingBuffer[iProcessCount], requestBuffer, 0, ringBuffLength, FALSE);
completionSz = (ULONG)ringBuffLength;
}
WdfSpinLockRelease(pDevExt->spinLockRxMsgList); //release the lock
WdfRequestCompleteWithInformation(Request, status, completionSz);
}
How to make my UsbDeviceEvtIoRead() to block until there is some data in ringbuffer? Can I loop inside this function for few iterations or until data is available in ringbuffer?
Is there any event to fire to userspace? I am completely lost in this scenario?
Here is my latest readthread in user space application…
while(…)
{
if (ReadFile(mHandle, by_bIn, ReadLen, NULL, &m_ovRead) == 0)
{
derror = GetLastError();
if (derror != ERROR_IO_PENDING)
{
continue;////error case.
}
else
{
waitState = WaitForSingleObject(m_ovRead.hEvent, 100);
switch (waitState)
{
case WAIT_FAILED:
case WAIT_TIMEOUT:
case WAIT_ABANDONED:
derror = GetLastError();
break;
case WAIT_OBJECT_0:
if (GetOverlappedResult(mHandle, &m_ovRead, (PULONG)&nBytesRead, TRUE) != 0)
{
if (nBytesRead > 0) {
packet.bIsPacket = FALSE;
for (wIndex = 0; wIndex < nBytesRead; wIndex++)
{
fHandlerRx.ExtractFrame(by_bIn[wIndex], &packet);
if (packet.bIsPacket == TRUE)
{
packet.bIsPacket = FALSE;
ProcessPacket(&packet);;
}
}
}
}
break;
}
}
}