Have you run this under the driver verifier?
Hi,
I have a problem with USB. I can’t read from the device. Once I send the
IRP, I do not get any response from the underlying device. The IRP
completion routine never gets called.
I checked with the USBlyzer and it clearly states that the IRP gets stuck
at usbhci after passing through usbhub.
I have a windows server 2003 SDK. It contains the BulkUsb sample. That
sample works perfectly. Here is the code for it: -
fdoData->BulkUrb = (PURB)ExAllocatePoolWithTag( NonPagedPool,
(SIZE_T)sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER), USBDRV_POOL_TAG );
RtlZeroMemory( fdoData->BulkUrb, sizeof(struct
_URB_BULK_OR_INTERRUPT_TRANSFER) );
WTF is fdoData? NEVER give a code sample in which the variable
declarations do not appear! We are left to guess what fdoData might be,
but in the absence of seeing its declaration and initialization, we have
no idea what is going on here!
And, I might add, there may be many different places the declaration of
fdoData might appear, and only one, or at most two, of them would be
correct usage.
I think you missed an absolutely critical test here. How can you use the
result of ExAllocatePoolWithTag without knowing if the pointer is valid?
Where do deal with completing the incoming IRP with
STATUS_INSUFFICIENT_RESOURCES? You have made this error fairly
consistently, failing to test the return values of DDI calls that can
fail. This is unacceptable practice.
fdoData->ReadBuffer = ExAllocatePoolWithTag( NonPagedPool, 64,
USBDRV_POOL_TAG );
Another case of failing to test the result
UsbBuildInterruptOrBulkTransferRequest( fdoData->BulkUrb,
(USHORT)sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
fdoData->InPipe->PipeHandle,
fdoData->ReadBuffer,
NULL,
64,
USBD_TRANSFER_DIRECTION_IN | USBD_SHORT_TRANSFER_OK,
NULL );
// Allocate IRP
fdoData->BulkIrp = IoAllocateIrp(
fdoData->TopOfStackDeviceObject->StackSize + 1, FALSE );
Another case of failing to check the return value. RTFM. If the
documentation says a function can return a NULL pointer, then you MUST,
REPEAT MUST, check for a valid return. Failure to do this will result in
a BSOD. Note that you are responsible for freeing up any allocations that
you have already done.
// Set URB in the IRP
IoSetNextIrpStackLocation( fdoData->BulkIrp );
IoGetCurrentIrpStackLocation( fdoData->BulkIrp )->DeviceObject =
DeviceObject;
I think you should use a few more variables here. Generally, if you
writesomething of the form f(…)->field, you had better be certain that
the function f will ALWAYS, WITHOUT EXCEPTION, return a valid pointer. My
memory is that you cannot execute IoGetCurrenIrpStackLocation on a
newly-allocated IRP, and the documentation suggests that this is rarely
used. IoGetNextIrpStackLocation should be used on a newly-allocated IRP.
// Get next IRP stack location
nextStack = IoGetNextIrpStackLocation( fdoData->BulkIrp );
// Setup next stack parameters
nextStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
nextStack->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
nextStack->Parameters.Others.Argument1 = fdoData->BulkUrb;
nextStack->Parameters.Others.Argument2 = NULL;
// Set the IRP completion routine
IoSetCompletionRoutine( fdoData->BulkIrp,
(PIO_COMPLETION_ROUTINE)IsoReadIrpCompletionRoutine,
NULL,
TRUE,
TRUE,
TRUE );
// Pass down the IRP down to the next lower device
> IoCallDriver( fdoData->TopOfStackDeviceObject, fdoData->BulkIrp );
You said at some point this returns STATUS_PENDING, and how could you
possibly know this? You do not check the value, you don’t even store it
or process it. So what happens when the driver below you returns an error
code? Note that if the result is not STATUS_PENDING, or fails the
NT_ERROR predicate, you will have to engage in “graceful recovery” here.
Also, you have given this example completely out of context. When is this
code called? Where do we see the function definition? Answer: we don’t
know fro this piece of code where it is executed. We don’t see what its
caller expects.
One thing you must internalize is the notion of “graceful recovery”. This
means that if anything goes wrong, the incoming IRP is completed with a
proper error status, and NOTHING you allocated along the way remains
allocated. It also means that if this code is in the dequeue routine,
then it must ensure that the next IRP in the queue is dequeued, or your
driver will go into a persistent vegetative state. And in your completion
routine, ditto; if the IRP you sent down failed, you have to clean up
everything, and complete the original IRP.
Also, I know that I should use KDMF but i have to use WDM.
Any help will be highly appreciated.
Regards.
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