Help please: USB surprise removal problem in streaming miniport driver

Hello. I will describe my plight in some detail. I have been assigned to
debug a problem in another project in which I have not worked.
Unfortunately, this is a streaming class driver (stream.sys is the port
driver) over the USB bus (1.1), and I have experience in neither. Also, the
project uses DriverWorks, and I am not familiar with this tool. But
anyways, here goes.

The problem is as follows; on Win2k SP3, when performing MIDI capture on a
bulk in endpoint, and I unplug the device, the system crashes with such
severity that WinDBG does not seem to trap the exception, and the system
reboots. SoftICE sometimes does trap the fault, and it seemed that the
crash occurred in one of the pool functions (ExAllocatePoolWithTag,
ExFreePool). I could never get a memory dump or stack trace with either
debugger. Of course, I had previously configured the system to yield a
kernel mode dump, and to not automatically reboot.

Unfortunately, with stream class port driver, I don’t have control over the
PnP dispatch routine. Nevertheless I overrode the routine with my own, and
called stream class’ routine. I merely put this in place to see what PnP
manager was sending the port driver. When MIDI capture was not on, I
clearly saw a call of IoInvalidateDeviceRelations call by the USB bus
driver, followed by two IRP_MN_QUERY_DEVICE_RELATIONS, and then a
IRP_MN_SURPRISE_REMOVAL. This last IRP triggers a surprise removal SRB to
be sent to my miniport, and I have of course have control the function which
responds to this SRB.

Unfortunately, when MIDI capture is in progress, and I unplug, I don’t even
see the USB bus driver calling IoInvalidateDeviceRelations, let alone
IRP_MN_SURPRISE_REMOVAL; the system merely reboots. Rarely, WinDBG pops up,
with a failure message: “unable to get context” (or something like that).

Using driver verifier did not help me, except to find some other minor bugs.
I therefore did a small experiment. I broke into my driver, set a global
variable which made my driver no longer touch the hardware, and unplugged
the device while the system was still frozen. This time the I saw the call
to IoInvalidateDeviceRelations, IRP_MN_QUERY_DEVICE_RELATIONS, and
IRP_MN_SURPRISE_REMOVAL. The driver unloaded fine.

Looking into the capture architecture of the driver, I saw that in the
completion routine for the IOCTL_INTERNAL_USB_SUBMIT_URB call to the USB bus
driver (which is at DISPATCH), that the data received from the bus driver
was copied up to stream class, and that a new URB was sent down, all at
DISPATCH. I thought that perhaps it would be more prudent to send down the
next URB at PASSIVE, even though the service
UsbBuildInterruptOrBulkTransferRequest can be called at DISPATCH. I also
used IoAllocateIrp, which is fine to call at DISPATCH. Of course no waiting
is done at DISPATCH in the driver.

So as a test I used a system thread to send the next URB down at PASSIVE.
This seemed to solve the problem! What I don’t understand is why the
previous architecture failed. I did not find any stricture stating that
IOCTL_INTERNAL_USB_SUBMIT_URB must be sent at PASSIVE. Surely in the
original architecture, the USB bus driver would pend my IRP, and the system
would drop down to PASSIVE, giving enough time to low IRQL for the USB bus
driver to note that the device is not present any more on the USB bus (and
send the required PnP IRPs at PASSIVE).

Any ideas on why this change worked? I’m really not comfortable not knowing
why this helped. For all I know this is masking the real issue. Thanks
in advance.

Philip Lukidis

Hi Sri. Thanks for your reply. QA did report a bugcheck when the device
was unplugged in WinXP SP1, but I did not have a chance to get to debug this
yet. They did say that it was much harder to reproduce, though. Hopefully
tomorrow I will get to it and see what is causing this. If it seems to be
the same problem I will let you know by replying to the list.

I also seem to be getting a pretty rare 0x1E (KMODE_EXCEPTION_NOT_HANDLED)
with param1 = 0xC0000005 (STATUS_ACCESS_VIOLATION) after my system thread
has called IoCallDriver just after the time when the device was unplugged (I
check for surprise removal only once before sending another URB down in my
system thread). The exception was in IoCallDriver, OR (in another dump)
when I accessed the next lower DEVICE_OBJECT myself in the same function
just before calling IoCallDriver in my system thread. It looks like this
next lower DEVICE_OBJECT it is being prematurely deleted by the bus driver
(my guess- I’ll try again with driver verifier on when I reghost to 2k). I
seem to have worked around this, but out of curiosity, have you ever seen
this in Win2k (SP3) for a USB bulk driver? Again, thanks for your reply.

Philip Lukidis

----- Original Message -----
From: “Deevi, Srinivasa”
To: “NT Developers Interest List”
Sent: Monday, March 17, 2003 12:42 PM
Subject: [ntdev] RE: Help please: USB surprise removal problem in streamin g
miniport driver

> Hi Philip
>
> It’s not you alone who are having this problem I guess . I also had the
> similar problem and solved this issue with similar technique. for some
> reason Win2K does not like this and crash occurs . Did you see this
problem
> on WinXP ? I have not seen this problem on WinXP . In my case , when the
> device is surprise removed the USB audio driver starts calling the next
> level driver with out going through our driver. When I made the requests
go
> through thread running at passive level, everything came under control.
>
> I have not got any solution for my problem. But I don’t think there is
> anything wrong in doing the way you are doing.
>
> Sri.
>