I'm about to go crazy. The problem I am having is that I need to reset
a USB pipe at Dispatch Level. I didn't think it would be a big deal, I
thought I would simply Issue a RESET PIPE URB (don't have the correct name
in front of me at the moment), and then issue an Internal Device Control
IRP down to the USB Driver. I didn't think this would be any big deal
because that is how I'm issuing Data to read/write from the same routine.
Well, it turns out that it must be a bigger deal than I thought. On
Windows 98 it hangs the system on a call to IoCallDriver, and on Windows
2000 (Checked Build) it issues a IRQL_NOT_LESS_OR_EQUAL Bug Check. I used
as a basis for the reset URB code that was presented in Walter Oney's
book. So, I format the URB (by setting the parameters), then I issue a
Device Internal IOCTL (the Same exact code that I use to issue a Bulk Read
IOCTL, except that I set the URB equal to the RESET PIPE URB. I then
install a completion routine (the idea is that when it finishes I'll check
the return value and either issue a RESET DEVICE URB or Issue the original
Read Bulk USB IOCTL (I have to use IRP Queueing, so I can't simply issue a
Reset Pipe URB and wait for it complete (like the code in Walter Oney's
book or the Samples in the DDK). Here is the code that sets it up:
[SNIP]
//Irp is a Device IOCTL that was submitted to the Driver by User
//Mode and has gotten to the following code (dequeued) which is
//executing at DISPATCH_LEVEL. Also of note is that the IRP has
//been marked with IoMarkIrpPending() when it was queued.
NextIRPStackLocation = IoGetNextIrpStackLocation(Irp))
RtlZeroMemory(&(DeviceExtension->DataINURB), sizeof(URB));
DeviceExtension->DataINURB.UrbHeader.Length =
(USHORT)sizeof(struct _URB_PIPE_REQUEST);
DeviceExtension->DataINURB.UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
DeviceExtension->DataINURB.UrbPipeRequest.PipeHandle =
DeviceExtension->DataINPipeHandle;
NextIRPStackLocation->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
NextIRPStackLocation->Parameters.DeviceIoControl.IoControlCode =
IOCTL_INTERNAL_USB_SUBMIT_URB;
NextIRPStackLocation->DeviceObject = DeviceExtension->LowerDeviceObject;
NextIRPStackLocation->Parameters.Others.Argument1 =
(PVOID)&(DeviceExtension->DataINURB);
IoSetCompletionRoutine(Irp,
(PIO_COMPLETION_ROUTINE)CompleteDataReadCallback,
(PVOID)DeviceObject, TRUE, TRUE, TRUE);
Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
//Completion routine (test code only).
NTSTATUS CompleteDataReadCallback(IN PDEVICE_OBJECT Garbage,
IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
{
NTSTATUS ret_val = Irp->IoStatus.Status;
KdPrint(("Enter CompleteReadDataCallback()\n"));
if(Irp->PendingReturned)
IoMarkIrpPending(Irp);
KdPrint(("Exit CompleteReadDataCallback(), return code: 0x%08X\n",
ret_val));
return(ret_val);
}
//End Complete IRP Test Code
[SNIP]
That's it, the above code basically dies and I can't figure out
why. Any ideas or thoughts? I've even tried building a new IRP with
IoAllocateIrp() and issuing it, but it still doesn't work. I can't figure
out why if I submit an URB built with UsbBuildInterruptOrBulkURB (or
whatever it's called) the code works, but with the simple URB above it
fails. Am I just overlooking something obvious? This should be easy (I'm
glad I tried to test the above code, because it doesn't work :)) I'm
about at my wit's end because this is some of the least complicated code
in the driver (or I thought it would be anyway). The idea orignally was
that if an error was detected (upon a read completion) then the next time
a Read IRP was dequeued at Dispatch Level it would issue the Reset Pipe,
then in the completion routine, it would issue the original Read on the
Pipe if the reset pipe succeeded or reset the device (and when it
completed via a callback routine it would submit the original Read Irp).
Thanks in advance (or at least reading).
-Damon Lange
Look at:
case IOCTL_BULKUSB_RESET_PIPE
and functions, BulkUsb_ResetPipe(...) and BulkUsb_CallUSBD(...).
--In a NUTSHELL -----
Allocate memory for, and setup your urb something like:
urb->UrbHeader.Length = (USHORT) sizeof (struct _URB_PIPE_REQUEST);
urb->UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
urb->UrbPipeRequest.PipeHandle = PipeInfo->PipeHandle;
create a new IRP and stack pointer and event like:
PIO_STACK_LOCATION nextStack;
PIRP pIrp
KEVENT event
and then initialize the event like:
KeInitializeEvent(&event, NotificationEvent, FALSE);
and call
irp = IoBuildDeviceIoControlRequest(
IOCTL_INTERNAL_USB_SUBMIT_URB,
deviceExtension->TopOfStackDeviceObject,
NULL, 0, NULL, 0, TRUE, &event, &ioStatus);
check for a valid irp and then use that irp in call to:
nextStack = IoGetNextIrpStackLocation(irp);
then set:
nextStack->Parameters.Others.Argument1 = Urb;
and call:
ntStatus = IoCallDriver(deviceExtension->TopOfStackDeviceObject,
irp);
and wait for event, or completion routine if you add that to the call.
Good Luck,
Tim
I'm using very similiar code to that, and all works fine. Perhaps,
you're lacking a call to IoBuildDeviceIoControlRequest()? The Irp
to use in IoGetNextIrpStackLocation(Irp) for Control request would
be returned from that call.
Hope this helps,
Tim
Seems to me I had the same problem with reset pipe and the irql dispatch
level. I queue a work item to reset the pipe and issue the reset pipe at
irql_passive.
Rob
"tim" <laws...@lawsonlabs.com> wrote in message
news:399996...@lawsonlabs.com...
> > file://Irp is a Device IOCTL that was submitted to the Driver by User
> > file://Mode and has gotten to the following code (dequeued) which is
> > file://executing at DISPATCH_LEVEL. Also of note is that the IRP has
> > file://been marked with IoMarkIrpPending() when it was queued.
> > NextIRPStackLocation = IoGetNextIrpStackLocation(Irp))
> >
> > RtlZeroMemory(&(DeviceExtension->DataINURB), sizeof(URB));
> > DeviceExtension->DataINURB.UrbHeader.Length =
> > (USHORT)sizeof(struct _URB_PIPE_REQUEST);
> > DeviceExtension->DataINURB.UrbHeader.Function = URB_FUNCTION_RESET_PIPE;
> > DeviceExtension->DataINURB.UrbPipeRequest.PipeHandle =
> > DeviceExtension->DataINPipeHandle;
> >
> > NextIRPStackLocation->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
> >
> > NextIRPStackLocation->Parameters.DeviceIoControl.IoControlCode =
> > IOCTL_INTERNAL_USB_SUBMIT_URB;
> > NextIRPStackLocation->DeviceObject = DeviceExtension->LowerDeviceObject;
> > NextIRPStackLocation->Parameters.Others.Argument1 =
> > (PVOID)&(DeviceExtension->DataINURB);
> >
> > IoSetCompletionRoutine(Irp,
> > (PIO_COMPLETION_ROUTINE)CompleteDataReadCallback,
> > (PVOID)DeviceObject, TRUE, TRUE, TRUE);
> >
> > Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
> >
> > file://Completion routine (test code only).
> > NTSTATUS CompleteDataReadCallback(IN PDEVICE_OBJECT Garbage,
> > IN PIRP Irp, IN PDEVICE_OBJECT DeviceObject)
> > {
> > NTSTATUS ret_val = Irp->IoStatus.Status;
> >
> > KdPrint(("Enter CompleteReadDataCallback()\n"));
> >
> > if(Irp->PendingReturned)
> > IoMarkIrpPending(Irp);
> >
> > KdPrint(("Exit CompleteReadDataCallback(), return code: 0x%08X\n",
> > ret_val));
> >
> > return(ret_val);
> > }
> > file://End Complete IRP Test Code
Thanks,
-Damon
Robert Brown wrote in message ...