You have a race condition. What happens when WdfIoQueueRetrieveNextRequest fails and immediately right afterwards you receive a user mode request for bulk in data? Do you drop the data on the floor in the cont reader completion routine?
-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@alumni.tu-berlin.de
Sent: Wednesday, May 1, 2013 10:58 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] BulkInPipe Read Request -> 0xc0000001
Hi,
just for the case that someone is interested in code examples on how to get data from a continuous reader into the user space ? here are the relevant routines (attached). From my point of view my original question on the NTSTATUS 0xc0000001 message in case of a read request can be answered that if the microcontroller of the usb device sends continuously data into the bulkin pipe then the host has to offer a continues reader because otherwise it would generate the error message 0xc0000001.
Best Regards,
Matthias
//WDFQUEUE BulkinReadRequestsQueue;//must be included into the device context structure
// WDFUSBPIPE UsbInterruptPipe; //must be included into the device context structure
//EvtDevicePrepareHardware
WdfUsbTargetPipeSetNoMaximumPacketSizeCheck(devCtx->UsbBulkInPipe);
WDF_USB_CONTINUOUS_READER_CONFIG_INIT(&BulkinConfig,
&UsbPipeReadComplete,
devCtx,
1024*sizeof(BYTE)); // <- this has to be multiple times larger than the expected packet size ? I expected 200 bytes and got only in the case of 1024 bytes a call of the BulkInContireader completion routine
BulkinConfig.EvtUsbTargetPipeReadersFailed = (PFN_WDF_USB_READERS_FAILED) UsbPipeReadFailed;
BulkinConfig.NumPendingReads = 2; // this is by default = 0;
status = WdfUsbTargetPipeConfigContinuousReader(
devCtx->UsbBulkInPipe,
&BulkinConfig);
if(!NT_SUCCESS(status))
{
KdPrint((__DRIVER_NAME
“WdfUsbTargetPipeConfigContinuousReader failed with status 0x%08x\n”, status));
return status;
} else KdPrint((__DRIVER_NAME
“WdfUsbTargetPipeConfigContinuousReader ready \n”));
//CreateQueue
WDF_IO_QUEUE_CONFIG_INIT(&ioQConfig,
WdfIoQueueDispatchManual); // this is the ?manual queue? Tim was speaking about
status = WdfIoQueueCreate(Device,
&ioQConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&Context->BulkinReadRequestsQueue);
if(!NT_SUCCESS(status))
{
KdPrint((__DRIVER_NAME
“WdfIoQueueCreate for manual queue failed with status 0x%08x\n”, status));
return status;
}
//IOCTL routine which is called from user space via DeviceIoControl
VOID
IoCtlGetUSBBulkinData(
IN WDFQUEUE Queue,
IN WDFREQUEST Request,
IN size_t OutputBufferLength,
IN size_t InputBufferLength
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_CONTEXT devCtx = NULL;
UNREFERENCED_PARAMETER(InputBufferLength);
UNREFERENCED_PARAMETER(OutputBufferLength);
devCtx = GetDeviceContext(WdfIoQueueGetDevice(Queue));
status = WdfRequestForwardToIoQueue(Request,
devCtx->BulkinReadRequestsQueue); //this pushes a IO request into the quese that contains appropriate buffer space that were set DeviceIoControl inside the user space
if(!NT_SUCCESS(status))
{
KdPrint((__DRIVER_NAME
“WdfRequestForwardToIoQueue failed with code 0x%08x.\n”, status));
WdfRequestComplete(Request, status);
}
Else KdPrint((__DRIVER_NAME
“Request fired.\n”));
};
// BulkInContireader completion
VOID
UsbPipeReadComplete(
IN WDFUSBPIPE Pipe,
IN WDFMEMORY Buffer,
IN size_t NumBytesTransfered,
IN WDFCONTEXT Context
)
{
NTSTATUS status = STATUS_SUCCESS;
WDFMEMORY outputMemory = NULL;
BYTE *inBuffer = NULL;
size_t in_size = 0;
PDEVICE_CONTEXT devCtx = Context;
WDFREQUEST Request = NULL;
UNREFERENCED_PARAMETER(Pipe);
// get eventually a request from BulkinReadRequestsQueue ? which would be there if the user mode has previously called IoCtlGetUSBBulkinData via a DeviceIoControl call.
status = WdfIoQueueRetrieveNextRequest(devCtx->BulkinReadRequestsQueue, &Request);
if(NT_SUCCESS(status))
{
KdPrint((__DRIVER_NAME
“Got a Request\n”));
//get the user mode memory
status = WdfRequestRetrieveOutputMemory(Request, &outputMemory);
if(!NT_SUCCESS(status))
{
KdPrint((__DRIVER_NAME
“WdfRequestRetrieveOutputMemory failed with status 0x%08x\n”, status));
} //if
else {
//get the inBuffer pointer for the data packet which was recently send via bulkin
inBuffer = WdfMemoryGetBuffer(Buffer, &in_size);
//check whether the user mode has selected the right buffer size
if(in_size == NumBytesTransfered) {
// copy and paste the data packet from bulkin into the user mode memory
status = WdfMemoryCopyFromBuffer(outputMemory, 0, inBuffer, NumBytesTransfered);
if(!NT_SUCCESS(status))
{
KdPrint((__DRIVER_NAME
“WdfMemoryCopyFromBuffer failed with status 0x%08x\n”, status));
} //if
}// if
else KdPrint((__DRIVER_NAME “in_size != NumBytesTransfered\n”, status));
KdPrint((__DRIVER_NAME “Bytes Copied %d \n”, in_size));
WdfRequestCompleteWithInformation(Request, status, in_size*sizeof(BYTE));
} //else
} //if
return;
// Bulkin Read failed
BOOLEAN
UsbPipeReadFailed(
IN WDFUSBPIPE Pipe,
IN NTSTATUS Status,
IN USBD_STATUS UsbdStatus
)
{
UNREFERENCED_PARAMETER(Pipe);
//send a kd message
KdPrint((__DRIVER_NAME “UsbPipeReadFailed NTSTAUS 0x%08x and USBD Status 0x%08x \n”, Status, UsbdStatus));
return TRUE;
};
NTDEV is sponsored by OSR
OSR is HIRING!! See http://www.osr.com/careers
For our schedule of WDF, WDM, debugging and other seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer