none
KMDF USB Driver crash when I unplug the device. RRS feed

  • General discussion

  • Hi MSDN community,

    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

    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;
    
    
    }


    Below is the CompleteRoutine

    void ReadComplete(
    	_In_  WDFREQUEST Request,
    	_In_  WDFIOTARGET Target,
    	_In_  PWDF_REQUEST_COMPLETION_PARAMS Params,
    	_In_  WDFCONTEXT Context
    	)
    {
    	NTSTATUS Status;
    	ULONG ApplicationBufferOffSet = 0;
    	UCHAR packetId;
    	PVOID Buffer0Ptr = NULL;
    	PVOID ApplicationBufferPtr = NULL;
    	DWORD64 BytesRead = 0;
    
    	WDF_REQUEST_REUSE_PARAMS ReuseParams;
    	WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_SUCCESS);
    
    	/* If an Application Issued read operation, copy the retrieved data to the application buffer */
    
    	if (CopyNextBuffer && ApplicationBuffer0 != NULL){
    
    		for (packetId = 0; packetId < UsbURB->UrbIsochronousTransfer.NumberOfPackets; packetId++){
    
    			if (UsbURB->UrbIsochronousTransfer.IsoPacket[packetId].Length != 0){ // Copy Isochronous packets that have data.
    
    				Buffer0Ptr = (PUCHAR) Buffer0 + UsbURB->UrbIsochronousTransfer.IsoPacket[packetId].Offset;
    				ApplicationBufferPtr = (PUCHAR) ApplicationBuffer0 + ApplicationBufferOffSet;
    
    				RtlCopyMemory(ApplicationBufferPtr, Buffer0Ptr, UsbURB->UrbIsochronousTransfer.IsoPacket[packetId].Length); // Copy Data To Application buffer
    
    				ApplicationBufferOffSet += UsbURB->UrbIsochronousTransfer.IsoPacket[packetId].Length; // Increment Application buffer offset
    				BytesRead += UsbURB->UrbIsochronousTransfer.IsoPacket[packetId].Length;
    			}
    		}
    
    		CopyNextBuffer = 0; // Clear Flag
    		WdfRequestCompleteWithInformation(ApplicationRequest, STATUS_SUCCESS, BytesRead); // Complete the Application Request
    	}
    
    	WdfObjectDelete(Request);
    
    	/* Re-issue another request */
    	if (!WdfRequestIsCanceled(Request)){
    		Status = WdfRequestReuse(Request, &ReuseParams);
    
    		WdfRequestMarkCancelable(Request, EvtRequestCancel);
    		if (NT_SUCCESS(Status))
    		{
    			if (Context != NULL)
    				CreateIsochReadRequest((WDFUSBDEVICE) Context, Request, IsochronousPipeIN, Buffer0, Buffer0Length);
    		}
    	}
    	
    
    }

    This is the crash dump

    0: kd> !analyze -v
    *******************************************************************************
    *                                                                             *
    *                        Bugcheck Analysis                                    *
    *                                                                             *
    *******************************************************************************
    
    UNEXPECTED_KERNEL_MODE_TRAP_M (1000007f)
    This means a trap occurred in kernel mode, and it's a trap of a kind
    that the kernel isn't allowed to have/catch (bound trap) or that
    is always instant death (double fault).  The first number in the
    bugcheck params is the number of the trap (8 = double fault, etc)
    Consult an Intel x86 family manual to learn more about what these
    traps are. Here is a *portion* of those codes:
    If kv shows a taskGate
            use .tss on the part before the colon, then kv.
    Else if kv shows a trapframe
            use .trap on that value
    Else
            .trap on the appropriate frame will show where the trap was taken
            (on x86, this will be the ebp that goes with the procedure KiTrap)
    Endif
    kb will then show the corrected stack.
    Arguments:
    Arg1: 00000008, EXCEPTION_DOUBLE_FAULT
    Arg2: 801e0000
    Arg3: 00000000
    Arg4: 00000000
    
    Debugging Details:
    ------------------
    
    
    BUGCHECK_STR:  0x7f_8
    
    CUSTOMER_CRASH_COUNT:  1
    
    DEFAULT_BUCKET_ID:  WIN7_DRIVER_FAULT
    
    PROCESS_NAME:  svchost.exe
    
    CURRENT_IRQL:  2
    
    TAG_NOT_DEFINED_c000000f:  FFFFFFFF8078B000
    
    LAST_CONTROL_TRANSFER:  from 88e52fa9 to 88e49ffd
    
    STACK_TEXT:  
    80788020 88e52fa9 aadd3530 88ea84e8 0000004f Wdf01000!FxIFR+0x1c9
    8078804c 88e53482 aadd3530 00000002 0000004f Wdf01000!WPP_IFR_SF_q+0x7a
    8078807c a13ec3de aadd3618 aadbd1e0 a13ec2b8 Wdf01000!imp_WdfRequestMarkCancelable+0xd0
    WARNING: Stack unwind information not available. Following frames may be wrong.
    807880b8 88e46419 55242e18 7193d8b8 8e63cb0c ADCDriver+0x13de
    807880e0 88e43163 8548ce28 8e6c2740 854d3890 Wdf01000!FxRequestBase::CompleteSubmitted+0xf1
    8078810c 88e4323c 8e6c2740 a30c4908 80788144 Wdf01000!FxIoTarget::RequestCompletionRoutine+0x140
    8078811c 83297ed2 00000000 8548ce28 aadbd1e0 Wdf01000!FxIoTarget::_RequestCompletionRoutine+0x33
    80788144 8328cdd3 00000000 8548ce28 a30c4908 nt!IopUnloadSafeCompletion+0x4a
    8078818c 8fc271c3 00000000 807881e4 8fc28235 nt!IopfCompleteRequest+0x128
    80788198 8fc28235 881ec028 8548ce28 a30eb840 USBPORT!USBPORT_Core_IoCompleteIrp+0x2e
    807881e4 8fc2852c 881ec028 c000000e 8548ce28 USBPORT!USBPORT_ProcessURB+0x8ff
    8078820c 8fc25a34 881ec028 8548ce28 a30eb840 USBPORT!USBPORT_PdoInternalDeviceControlIrp+0xfb
    80788234 8324bc1e 881ec028 881ec2cc ffef3ff7 USBPORT!USBPORT_Dispatch+0x18a
    8078824c 88ed53da ffef3ff7 8078826c 88edbc20 nt!IofCallDriver+0x63
    80788258 88edbc20 885b1368 8548ce28 8548cf94 ACPI!ACPIDispatchForwardIrp+0x2a
    8078826c 88ed5664 885b1368 8548ce28 98a36028 ACPI!ACPIIrpDispatchDeviceControl+0xa4
    8078829c 8324bc1e 885b1368 85ed8310 8548ce28 ACPI!ACPIDispatchIrp+0x198
    807882b4 8fd5cc8e 8548ce28 852f8760 00000000 nt!IofCallDriver+0x63
    807882c8 8fd5cee5 98a360e0 852f86a8 8548ce28 usbhub!UsbhFdoUrbPdoFilter+0x68
    807882ec 8fd5cb91 852f86a8 8548cf94 852f86a8 usbhub!UsbhPdoInternalDeviceControl+0xf6
    80788300 8324bc1e 852f86a8 8548ce28 ffef3ff7 usbhub!UsbhGenDispatch+0x4a
    80788318 88ed53da ffef3ff7 80788338 88edbc20 nt!IofCallDriver+0x63
    80788324 88edbc20 aadd3b40 8548ce28 8548cf94 ACPI!ACPIDispatchForwardIrp+0x2a
    80788338 88ed5664 aadd3b40 8548ce28 00000005 ACPI!ACPIIrpDispatchDeviceControl+0xa4
    80788368 8324bc1e aadd3b40 85ed9910 8e6c2740 ACPI!ACPIDispatchIrp+0x198
    80788380 88e46cc5 00000064 5cf17890 00000064 nt!IofCallDriver+0x63
    80788430 88e46419 55242e18 7193d8b8 8e63cb0c Wdf01000!imp_WdfRequestSend+0x33c
    80788458 88e43163 8548ce28 8e6c2740 854d3890 Wdf01000!FxRequestBase::CompleteSubmitted+0xf1
    80788484 88e4323c 8e6c2740 a3153618 807884bc Wdf01000!FxIoTarget::RequestCompletionRoutine+0x140
    80788494 83297ed2 00000000 8548ce28 aadbd1e0 Wdf01000!FxIoTarget::_RequestCompletionRoutine+0x33
    807884bc 8328cdd3 00000000 8548ce28 a3153618 nt!IopUnloadSafeCompletion+0x4a
    80788504 8fc271c3 00000000 8078855c 8fc28235 nt!IopfCompleteRequest+0x128
    80788510 8fc28235 881ec028 8548ce28 a30eb840 USBPORT!USBPORT_Core_IoCompleteIrp+0x2e
    8078855c 8fc2852c 881ec028 c000000e 8548ce28 USBPORT!USBPORT_ProcessURB+0x8ff
    80788584 8fc25a34 881ec028 8548ce28 a30eb840 USBPORT!USBPORT_PdoInternalDeviceControlIrp+0xfb
    807885ac 8324bc1e 881ec028 881ec2cc ffef3ff7 USBPORT!USBPORT_Dispatch+0x18a
    807885c4 88ed53da ffef3ff7 807885e4 88edbc20 nt!IofCallDriver+0x63
    807885d0 88edbc20 885b1368 8548ce28 8548cf94 ACPI!ACPIDispatchForwardIrp+0x2a
    807885e4 88ed5664 885b1368 8548ce28 98a36028 ACPI!ACPIIrpDispatchDeviceControl+0xa4
    80788614 8324bc1e 885b1368 85ed8310 8548ce28 ACPI!ACPIDispatchIrp+0x198
    8078862c 8fd5cc8e 8548ce28 852f8760 00000000 nt!IofCallDriver+0x63
    80788640 8fd5cee5 98a360e0 852f86a8 8548ce28 usbhub!UsbhFdoUrbPdoFilter+0x68
    80788664 8fd5cb91 852f86a8 8548cf94 852f86a8 usbhub!UsbhPdoInternalDeviceControl+0xf6
    80788678 8324bc1e 852f86a8 8548ce28 ffef3ff7 usbhub!UsbhGenDispatch+0x4a
    80788690 88ed53da ffef3ff7 807886b0 88edbc20 nt!IofCallDriver+0x63
    8078869c 88edbc20 aadd3b40 8548ce28 8548cf94 ACPI!ACPIDispatchForwardIrp+0x2a
    807886b0 88ed5664 aadd3b40 8548ce28 00000005 ACPI!ACPIIrpDispatchDeviceControl+0xa4
    807886e0 8324bc1e aadd3b40 85ed9910 8e6c2740 ACPI!ACPIDispatchIrp+0x198
    807886f8 88e46cc5 00000064 5cf17890 00000064 nt!IofCallDriver+0x63
    807887a8 88e46419 55242e18 7193d8b8 8e63cb0c Wdf01000!imp_WdfRequestSend+0x33c
    807887d0 88e43163 8548ce28 8e6c2740 854d3890 Wdf01000!FxRequestBase::CompleteSubmitted+0xf1
    807887fc 88e4323c 8e6c2740 a31a1148 80788834 Wdf01000!FxIoTarget::RequestCompletionRoutine+0x140
    8078880c 83297ed2 00000000 8548ce28 aadbd1e0 Wdf01000!FxIoTarget::_RequestCompletionRoutine+0x33
    80788834 8328cdd3 00000000 8548ce28 a31a1148 nt!IopUnloadSafeCompletion+0x4a
    8078887c 8fc271c3 00000000 807888d4 8fc28235 nt!IopfCompleteRequest+0x128
    80788888 8fc28235 881ec028 8548ce28 a30eb840 USBPORT!USBPORT_Core_IoCompleteIrp+0x2e
    807888d4 8fc2852c 881ec028 c000000e 8548ce28 USBPORT!USBPORT_ProcessURB+0x8ff
    807888fc 8fc25a34 881ec028 8548ce28 a30eb840 USBPORT!USBPORT_PdoInternalDeviceControlIrp+0xfb
    80788924 8324bc1e 881ec028 881ec2cc ffef3ff7 USBPORT!USBPORT_Dispatch+0x18a
    8078893c 88ed53da ffef3ff7 8078895c 88edbc20 nt!IofCallDriver+0x63
    80788948 88edbc20 885b1368 8548ce28 8548cf94 ACPI!ACPIDispatchForwardIrp+0x2a
    8078895c 88ed5664 885b1368 8548ce28 98a36028 ACPI!ACPIIrpDispatchDeviceControl+0xa4
    8078898c 8324bc1e 885b1368 85ed8310 8548ce28 ACPI!ACPIDispatchIrp+0x198
    807889a4 8fd5cc8e 8548ce28 852f8760 00000000 nt!IofCallDriver+0x63
    807889b8 8fd5cee5 98a360e0 852f86a8 8548ce28 usbhub!UsbhFdoUrbPdoFilter+0x68
    807889dc 8fd5cb91 852f86a8 8548cf94 852f86a8 usbhub!UsbhPdoInternalDeviceControl+0xf6
    807889f0 8324bc1e 852f86a8 8548ce28 ffef3ff7 usbhub!UsbhGenDispatch+0x4a
    80788a08 88ed53da ffef3ff7 80788a28 88edbc20 nt!IofCallDriver+0x63
    80788a14 88edbc20 aadd3b40 8548ce28 8548cf94 ACPI!ACPIDispatchForwardIrp+0x2a
    80788a28 88ed5664 aadd3b40 8548ce28 00000005 ACPI!ACPIIrpDispatchDeviceControl+0xa4
    80788a58 8324bc1e aadd3b40 85ed9910 8e6c2740 ACPI!ACPIDispatchIrp+0x198
    80788a70 88e46cc5 00000064 5cf17890 00000064 nt!IofCallDriver+0x63
    80788b20 88e46419 55242e18 7193d8b8 8e63cb0c Wdf01000!imp_WdfRequestSend+0x33c
    80788b48 88e43163 8548ce28 8e6c2740 854d3890 Wdf01000!FxRequestBase::CompleteSubmitted+0xf1
    80788b74 88e4323c 8e6c2740 9d9f22f0 80788bac Wdf01000!FxIoTarget::RequestCompletionRoutine+0x140
    
    
    STACK_COMMAND:  kb
    
    FOLLOWUP_IP: 
    ADCDriver+13de
    a13ec3de ??              ???
    
    SYMBOL_STACK_INDEX:  3
    
    SYMBOL_NAME:  ADCDriver+13de
    
    FOLLOWUP_NAME:  MachineOwner
    
    MODULE_NAME: ADCDriver
    
    IMAGE_NAME:  ADCDriver.sys
    
    DEBUG_FLR_IMAGE_TIMESTAMP:  5227456a
    
    FAILURE_BUCKET_ID:  0x7f_8_ADCDriver+13de
    
    BUCKET_ID:  0x7f_8_ADCDriver+13de
    
    Followup: MachineOwner
    ---------
    

    Thursday, September 5, 2013 10:36 PM

All replies

  • You can't delete the request if you are going to reuse it. Just reuse the request without the delete

    d -- This posting is provided "AS IS" with no warranties, and confers no rights.

    Friday, September 6, 2013 4:52 AM
  • Hi again,

    Thanks for the reply. I changed the CompleteRoutine to just reuse the request without deleting it. But still, it crashes when I unplug the device.

    void ReadComplete(
    	_In_  WDFREQUEST Request,
    	_In_  WDFIOTARGET Target,
    	_In_  PWDF_REQUEST_COMPLETION_PARAMS Params,
    	_In_  WDFCONTEXT Context
    	)
    {
    	NTSTATUS Status;
    	ULONG ApplicationBufferOffSet = 0;
    	UCHAR packetId;
    	PVOID Buffer0Ptr = NULL;
    	PVOID ApplicationBufferPtr = NULL;
    	DWORD64 BytesRead = 0;
    
    	WDF_REQUEST_REUSE_PARAMS ReuseParams;
    	WDF_REQUEST_REUSE_PARAMS_INIT(&ReuseParams, WDF_REQUEST_REUSE_NO_FLAGS, STATUS_SUCCESS);
    
    	/* If an Application Issued read operation, copy the retrieved data to the application buffer */
    
    	if (CopyNextBuffer && ApplicationBuffer0 != NULL){
    
    		for (packetId = 0; packetId < UsbURB->UrbIsochronousTransfer.NumberOfPackets; packetId++){
    
    			if (UsbURB->UrbIsochronousTransfer.IsoPacket[packetId].Length != 0){ // Copy Isochronous packets that have data.
    
    				Buffer0Ptr = (PUCHAR) Buffer0 + UsbURB->UrbIsochronousTransfer.IsoPacket[packetId].Offset;
    				ApplicationBufferPtr = (PUCHAR) ApplicationBuffer0 + ApplicationBufferOffSet;
    
    				RtlCopyMemory(ApplicationBufferPtr, Buffer0Ptr, UsbURB->UrbIsochronousTransfer.IsoPacket[packetId].Length); // Copy Data To Application buffer
    
    				ApplicationBufferOffSet += UsbURB->UrbIsochronousTransfer.IsoPacket[packetId].Length; // Increment Application buffer offset
    				BytesRead += UsbURB->UrbIsochronousTransfer.IsoPacket[packetId].Length;
    			}
    		}
    
    		CopyNextBuffer = 0; // Clear Flag
    		WdfRequestCompleteWithInformation(ApplicationRequest, STATUS_SUCCESS, BytesRead); // Complete the Application Request
    	}
    
    	//WdfObjectDelete(Request);
    
    	/* Re-issue another request */
    	//if (!WdfRequestIsCanceled(Request)){
    	//	Status = WdfRequestReuse(Request, &ReuseParams);
    
    	//	WdfRequestMarkCancelable(Request, EvtRequestCancel);
    	//	if (NT_SUCCESS(Status))
    	//	{
    	//		if (Context != NULL)
    	//			CreateIsochReadRequest((WDFUSBDEVICE) Context, Request, IsochronousPipeIN, Buffer0, Buffer0Length);
    	//	}
    	//}
    
    	if (Context != NULL)
    		CreateIsochReadRequest((WDFUSBDEVICE) Context, Request, IsochronousPipeIN, Buffer0, Buffer0Length);
    
    }
    

    Friday, September 6, 2013 8:48 AM
  • 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 Windows Driver and OS consultant www.hollistech.com

    Friday, September 6, 2013 1:45 PM
    Moderator
  • Thanks to Mark the following solution worked. I just added a check before issuing another request.

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

    Thanks.

    Friday, September 6, 2013 5:50 PM