KMDF USB Driver crash when I unplug the device.

Hi,
I’m developing a USB KMDF driver for my device. My USB device buffers A/D Data and send it over using Isochronous Endpoint IN. After windows loads the driver and selects configuration my driver does the following:
1- Looks for the Isochronous Pipe IN and retrieves a WDFUSBPIPE Handle.
2- Creates a driver Request using WdfRequestCreate.
3- Create URB for Isochronous transfer with 100 Isochronous packets.
4- Format Request Using WdfUsbTargetDeviceFormatRequestForUrb.
5- Set a completion routine and then send the request using WdfRequestSend.
After the USB Stack completes the transfers the request complete routine event is called and does the following:
6- Copies the retrieved data buffer to the application’s buffer if it has been requested earlier.
7- Calls WdfObjectDelete to complete the request.
8- Then calls WdfRequestReuse to reuse the request and creates the same Urb for Isochronous transfers.
I used this method to continuously read data from the usb pipe.
So far everything works just fine. I am able to read data from a C# application.
My problems is when I unplug my usb device. The moment I unplug the usb device i get bluescreen with bugcheck 1000007f. However, if I ejected the device before unplugging it the bugcheck does not occur. Please help me figure out what the problem. I’m running my driver on a Windows 7 32-bit machine

Below is the routine used to create Urb for Isochronous transfers

Sorry I couldn’t post it in one post.

NTSTATUS CreateIsochReadRequest(
WDFUSBDEVICE UsbDevice,
WDFREQUEST Request,
WDFUSBPIPE IsochronousPipeIN,
PVOID OutputBuffer,
ULONG BufferLength)
{
/* Define Variables */
WDF_OBJECT_ATTRIBUTES Attributes;
WDFMEMORY UrbMemory;
ULONG NumberOfIsochPackets = 100; // number of Isochronous packets
UINT16 packetID, BufferPerPacketSize = 256;
NTSTATUS Status;

/* Check if the Buffer is large enough */

if (BufferLength < (BufferPerPacketSize*NumberOfIsochPackets))
{
return STATUS_INVALID_BUFFER_SIZE;
}

/* Create URB */

WDF_OBJECT_ATTRIBUTES_INIT(&Attributes);
Attributes.ParentObject = UsbDevice;

Status = WdfUsbTargetDeviceCreateIsochUrb(UsbDevice, &Attributes, NumberOfIsochPackets, &UrbMemory, &UsbURB);

if (!NT_SUCCESS(Status))
return Status;

UsbURB->UrbIsochronousTransfer.Hdr.Length = GET_ISO_URB_SIZE(NumberOfIsochPackets);
UsbURB->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
UsbURB->UrbIsochronousTransfer.NumberOfPackets = NumberOfIsochPackets;
UsbURB->UrbIsochronousTransfer.PipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(IsochronousPipeIN);
UsbURB->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN | USBD_START_ISO_TRANSFER_ASAP;
UsbURB->UrbIsochronousTransfer.TransferBuffer = OutputBuffer;
UsbURB->UrbIsochronousTransfer.TransferBufferLength = BufferLength;

/* Packet Descriptors */

for (packetID = 0; packetID < NumberOfIsochPackets; packetID++){
UsbURB->UrbIsochronousTransfer.IsoPacket[packetID].Offset = BufferPerPacketSize*packetID;
UsbURB->UrbIsochronousTransfer.IsoPacket[packetID].Length = 0;
UsbURB->UrbIsochronousTransfer.IsoPacket[packetID].Status = 0;
}

/* Send Urb Asychronously */
Status = WdfUsbTargetDeviceFormatRequestForUrb(UsbDevice, Request, UrbMemory, NULL);

if (!NT_SUCCESS(Status))
return Status;

WdfRequestSetCompletionRoutine(Request, ReadComplete, UsbDevice);

if (!WdfRequestSend(Request, WdfUsbTargetPipeGetIoTarget(IsochronousPipeIN), NULL))
return STATUS_UNSUCCESSFUL;

return STATUS_SUCCESS;

}

For some reason I can post large texts, I already posted this on MSDN forums, can you please check it out.

crash dump and other routines are attached there

http://social.msdn.microsoft.com/Forums/windowshardware/en-US/66aef1aa-d57f-473e-ae87-a97f15e63d40/kmdf-usb-driver-crash-when-i-unplug-the-device

Thanks in advance!

Your crash is a stack overflow crash. You’ve blown through the stack
because your continuous reader is not noticing that the device is unplugged
and just keeps on resending the request, which completes immediately in the
usbport driver, which re-enters your completion handler, which doesn’t
realize the device has been unplugged so it just sends another request,
which completes immediately in the usbport driver which re-enters your
completion handler which which doesn’t realize the device has been
unplugged so it just sends another request, which completes immediately in
the usbport driver which re-enters your completion handler …

You need to look at the status and stop sending if the device is unplugged.
Something like USBD_STATUS_DEVICE_GONE. There may be other error conditions
that you should stop resending on too.

Mark Roddy

On Fri, Sep 6, 2013 at 7:59 AM, wrote:

> For some reason I can post large texts, I already posted this on MSDN
> forums, can you please check it out.
>
> crash dump and other routines are attached there
>
>
> http://social.msdn.microsoft.com/Forums/windowshardware/en-US/66aef1aa-d57f-473e-ae87-a97f15e63d40/kmdf-usb-driver-crash-when-i-unplug-the-device
>
> Thanks in advance!
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>
> 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
>

You could also detect that your completion handler is in the same thread
context and use a workitem for the resend operation instead of entering a
recursion loop like this, but I think just detecting that the device is
unplugged based on USBD_* status will work.

I posted the same previous answer on the MSDN forum.

Mark Roddy

On Fri, Sep 6, 2013 at 9:46 AM, Mark Roddy wrote:

> Your crash is a stack overflow crash. You’ve blown through the stack
> because your continuous reader is not noticing that the device is unplugged
> and just keeps on resending the request, which completes immediately in the
> usbport driver, which re-enters your completion handler, which doesn’t
> realize the device has been unplugged so it just sends another request,
> which completes immediately in the usbport driver which re-enters your
> completion handler which which doesn’t realize the device has been
> unplugged so it just sends another request, which completes immediately in
> the usbport driver which re-enters your completion handler …
>
> You need to look at the status and stop sending if the device is
> unplugged. Something like USBD_STATUS_DEVICE_GONE. There may be other error
> conditions that you should stop resending on too.
>
> Mark Roddy
>
>
> On Fri, Sep 6, 2013 at 7:59 AM, wrote:
>
>> For some reason I can post large texts, I already posted this on MSDN
>> forums, can you please check it out.
>>
>> crash dump and other routines are attached there
>>
>>
>> http://social.msdn.microsoft.com/Forums/windowshardware/en-US/66aef1aa-d57f-473e-ae87-a97f15e63d40/kmdf-usb-driver-crash-when-i-unplug-the-device
>>
>> Thanks in advance!
>>
>> —
>> NTDEV is sponsored by OSR
>>
>> Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev
>>
>> 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
>>
>
>

Hi,
Thanks for the reply Mark. I added the following check before send another request

if (UsbURB->UrbIsochronousTransfer.Hdr.Status != USBD_STATUS_DEVICE_GONE)
CreateIsochReadRequest((WDFUSBDEVICE) Context, Request, IsochronousPipeIN, Buffer0, Buffer0Length);

And it worked! the driver no longer crash the system. Thanks for the help Mark!!

> For some reason I can post large texts, I already posted this on MSDN

forums, can you please check it out.

crash dump and other routines are attached there

http://social.msdn.microsoft.com/Forums/windowshardware/en-US/66aef1aa-d57f-473e-ae87-a97f15e63d40/kmdf-usb-driver-crash-when-i-unplug-the-device

Thanks in advance!

It’s a double fault. I can’t recall the last time I saw one of these.
You should read the section on double faults in volume 3A of the Intel
manuals (google for Intel Volume 3A). It says, in part,

Interrupt 8—Double Fault Exception (#DF)

Exception Class Abort.

Description

Indicates that the processor detected a second exception while calling an
exception handler for a prior exception. Normally, when the processor
detects another exception while trying to call an exception handler, the
two exceptions can be handled serially. If, however, the processor cannot
handle them serially, it signals the double-fault exception.

…various tables and details omitted

Program State Change

A program-state following a double-fault exception is undefined. The
program or task cannot be resumed or
restarted. The only available action of the double-fault exception handler
is to collect all possible context information for use in diagnostics and
then close the application and/or shut down or reset the processor.

Bottom line: you’ve done something really nasty. I suspect that your
driver has been removed before a pending IRP at a lower level attempts to
call its dispatch routine, but that’s just a guess.

The other thing is that the symbol information is not available for the
stack display. There are many possible causes of this, but one is this
can happen if your driver code gets unloaded. So I’d suggest sprinkling
some KdPrints in the various shutdown functions, especially the unload
handler, and see what comes out before the bluescreen. At least, that’s
how I’d start going after it.
joe


NTDEV is sponsored by OSR

Visit the list at: http://www.osronline.com/showlists.cfm?list=ntdev

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

Thanks Joseph for further clarifications. After the solution that i have added to my driver, i used a usb sniffing software to see that packets that are sent after i unplug the usb device. That last packet sent returns with USBD_STATUS_CANCELLED and then the driver attempts to send another request however this time it returns with USBD_STATUS_DEVICE_GONE and because of the check that i have added it will stop sending requests. Otherwise, the driver will keep send iso packets and will keep returning the same status and eventually driver crash