Life cycle of USB Pipes within WDF

Hi,

I’m creating an USB driver for a FX2 based device. The device particularly is a scanner,
so I wish to treat 2 of in endpoints as “interrupt” endpoints (one EP is a real INT
EP, thus providing status information, the other is a simple bulk in EP but it provides
scanned image information, thus it is the driver who has to buffer ALL incoming
data from this pipe, as nothing can be lost).
Everything seems to be going fine, I modified the usb sample code within the DDK,
added support for continous readers per pipes, added EvtFileCreate/EvtFileClose
to the EvtDeviceAdd.
Within the file create I:

  • open the pipe
  • setup and start the pipe with a continous reader (if it’s an INT or a “simulated” INT pipe).

Within the file close I would like to WdfIoTargetStop() the specific pipes naturally
that are having continous readers assigned to them.
Here comes the sad part I get BSOD when doing that so.
From the windbg analyzation it seems my code fails on the WdfIoTargetStop().
I was checking the code and the PipeHandle is not NULL, but apart from that
it seems (at least from the registers) that the WdfIoTargetStop() gets a NULL
parameter, so I would assume that the WdfUsbTargetPipeGetIoTarget() returns
NULL.

So technically what I would like to know:

  • what is the lifecycle of a pipe within the framework? (when is it "auto"closed)
  • how/when should I make sure that the continous readers are stopped when the
    file descriptors (to the pipes) are closed?

Thanks,

t.

Here are some details about the bug:

BugCheck 8E, {80000003, 804e3b14, bae8f9d0, 0}

EXCEPTION_CODE: (HRESULT) 0x80000003 (2147483651) - One or more arguments are invalid

FAULTING_IP:
nt!DbgBreakPoint+0
804e3b14 cc int 3

TRAP_FRAME: bae8f9d0 – (.trap 0xffffffffbae8f9d0)
ErrCode = 00000000
eax=00000000 ebx=00000000 ecx=00000001 edx=00000000 esi=ba51572c edi=82133008
eip=804e3b15 esp=bae8fa44 ebp=bae8fa58 iopl=0 nv up ei pl nz na po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000202
nt!DbgBreakPoint+0x1:
804e3b15 c3 ret
Resetting default scope

DEFAULT_BUCKET_ID: DRIVER_FAULT

BUGCHECK_STR: 0x8E

PROCESS_NAME: scanner_test.ex

LAST_CONTROL_TRANSFER: from 8051dea6 to 805339ae

STACK_TEXT:
bae8f598 8051dea6 0000008e 80000003 804e3b14 nt!KeBugCheckEx+0x1b
bae8f960 804dfada bae8f97c 00000000 bae8f9d0 nt!KiDispatchException+0x3b1
bae8f9c8 804e0208 bae8fa58 804e3b15 badb0d00 nt!CommonDispatchException+0x4d
bae8f9c8 804e3b15 bae8fa58 804e3b15 badb0d00 nt!KiTrap03+0xad
bae8fa40 ba4b584f 8228a8c8 8228a934 81f2239c nt!DbgBreakPoint+0x1
bae8fa58 baf3199a 021330c0 7e2925d0 00000001 wdf01000!imp_WdfIoTargetStop+0x9a
bae8fa6c baf318ff 7e2925d0 00000001 ba509f54 e6usb!WdfIoTargetStop+0x1a [c:\winddk\6001.18001\inc\wdf\kmdf\1.7\wdfiotarget.h @ 413]
bae8fa94 baf3114c 81d8f450 00000000 822d0c68 e6usb!StopInterruptEndPoint+0x1af [c:\wo2711\fx2drv.new\device.c @ 592]
bae8facc ba4eb944 7e22f4a8 81f222c0 8228a934 e6usb!E6UsbEvtFileClose+0x1cc [c:\wo2711\fx2drv.new\device.c @ 406]
bae8fae0 ba4ec0bc 7e22f4a8 8228a8c8 81f2239c wdf01000!FxFileObjectFileCleanup::Invoke+0x24
bae8fb04 ba4ec782 00000000 81f222d0 81eec1e8 wdf01000!FxPkgGeneral::OnClose+0x70
bae8fb20 ba4e2665 81f222c0 bae8fb74 804e3d77 wdf01000!FxPkgGeneral::Dispatch+0xdf
bae8fb2c 804e3d77 81de36e0 81f222c0 81f222c0 wdf01000!FxDevice::Dispatch+0x7f
bae8fb3c 8056afec 8235cc68 00000000 00000000 nt!IopfCallDriver+0x31
bae8fb74 80563ff6 0035cc80 8235cc68 00000000 nt!IopDeleteFile+0x132
bae8fb90 804e3c55 8235cc80 00000000 00000740 nt!ObpRemoveObjectRoutine+0xdf
bae8fbb4 80567543 8235cc69 00000740 e1524e80 nt!ObfDereferenceObject+0x5f
bae8fbcc 8058ad2d e1298788 8235cc80 00000740 nt!ObpCloseHandleTableEntry+0x155
bae8fbec 8058b12d e1524e80 00000740 bae8fc3c nt!ObpCloseHandleProcedure+0x1f
bae8fc1c 8058aa46 e1298788 8058ad0e bae8fc3c nt!ExSweepHandleTable+0x4f
bae8fc48 8058b04a 81dd0650 821d20b8 c000013a nt!ObKillProcess+0x5c
bae8fcf0 8058b341 c000013a bae8fd4c 804e6851 nt!PspExitThread+0x5e9
bae8fcfc 804e6851 821d20b8 bae8fd48 bae8fd3c nt!PsExitSpecialApc+0x22
bae8fd4c 804df0d4 00000001 00000000 bae8fd64 nt!KiDeliverApc+0x1af
bae8fd4c 7c90eb94 00000001 00000000 bae8fd64 nt!KiServiceExit+0x58
00f1fe8c 7c90d8ef 7c801671 00000754 00000000 ntdll!KiFastSystemCallRet
00f1fe90 7c801671 00000754 00000000 00000000 ntdll!ZwDeviceIoControlFile+0xc
00f1fef0 00403bb1 00000754 5500600e 00000000 kernel32!DeviceIoControl+0xdd
WARNING: Stack unwind information not available. Following frames may be wrong.
00f1ff30 004012ad 00413590 00000006 00f1ff58 scanner_test!_GetExceptDLLinfo+0x2b58
00f1ffb4 7c80b50b 00942c4c 00000000 00000005 scanner_test!_GetExceptDLLinfo+0x254
00f1ffec 00000000 00401231 00942c4c 00000000 kernel32!BaseThreadStart+0x37

STACK_COMMAND: kb

FOLLOWUP_IP:
e6usb!WdfIoTargetStop+1a [c:\winddk\6001.18001\inc\wdf\kmdf\1.7\wdfiotarget.h @ 413]
baf3199a 5d pop ebp

FAULTING_SOURCE_CODE:
409: WDF_IO_TARGET_SENT_IO_ACTION Action
410: )
411: {
412: ((PFN_WDFIOTARGETSTOP) WdfFunctions[WdfIoTargetStopTableIndex])(WdfDriverGlobals, IoTarget, Action);

413: }
414:
415: //
416: // WDF Function: WdfIoTargetGetState
417: //
418: typedef

SYMBOL_STACK_INDEX: 6

SYMBOL_NAME: e6usb!WdfIoTargetStop+1a

FOLLOWUP_NAME: MachineOwner

MODULE_NAME: e6usb

IMAGE_NAME: e6usb.sys

DEBUG_FLR_IMAGE_TIMESTAMP: 48eb187d

FAILURE_BUCKET_ID: 0x8E_e6usb!WdfIoTargetStop+1a

BUCKET_ID: 0x8E_e6usb!WdfIoTargetStop+1a

Followup: MachineOwner

Lame me, didn’t post the code snippet that fails:

WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(pPipeContext->PipeHandle), WdfIoTargetCancelSentIo);

PipeHandle is the handle that was WdfUsbInterfaceGetConfiguredPipe()-ed in EvtFileCreate().

Hey,

just noticed the following in the doc.

"
Additionally, if a driver calls WdfUsbTargetPipeConfigContinuousReader to configure a continuous reader for a USB pipe, the driver’s EvtDeviceD0Exit callback function function must call WdfIoTargetStop to stop the reader.
"

Is it so? Does that mean that I can’t stop the continous reader within EvtFileClose?
Does that means that I can’t close the continous readers only when the DEVICE
is removed? Meaning that I can’t even follow a:

  • pipe open,
  • continous reader start,
  • pipe close
  • cotinous reader stop

scenario?!?

Thanks,
t.

Or is there a way to set a power policy, so that:
when all handles are gone (actually it is feasibly that I close all handles to the device at once)
the device goes into EvtDeviceD0Exit? (guess some magic within EvtFileClose)

I know(?) this kind of (?) logic is implemented within kmdf/serial, but as the serial port is
hardware interrupt driver I don’t quite see how should I port that logic to the USB driver.

Thanks,

Specify idle support for your device, with an idle timeout of zero.

When there are handles in use, call WdfDeviceStopIdle. When there are no handles in use call WdfDeviceResumeIdle.

Is that what you wanted to know??

Peter
OSR

Actually yes,

I just wanted to have a confirmation, that:
a.) I cannot stop continous readers elsewhere than in EvtDeviceD0Exit
b.) It’s reasonable (but I don’t see it a MUST) to start them (c.r.) within EvtDeviceD0Enter
c.) Because of the D0Exit issue of WdfIoTargetStop I need to change the power policy of my
driver so that Idle time will be zero, so that D0Exit will be called at once after all references
to my device are removed
d.) To enforce the logic I need to “flag” within EvtFileClose (and naturally the oposite in
EvtFileCreate) that my device indeed can go into idle

Am I getting it right?
Thanks,

You don’t HAVE to ONLY stop your continuous reader(s) in EvtDeviceD0Exit. You CAN stop your continuous reader(s) anywhere that makes sense (not anywhere, but anywhere that makes sense). Likewise, you can START your continuous reader anywhere it makes sense. You may NOT have your continuous reader(s) enabled when your device exits D0.

If what you want to do is idle your device as soon as there are no open handles (a common requirement) then what you’ve described will work.

Peter
OSR

Hello Peter,

if that is true what you have written, can you suggest why can my code failing when I try to
stop my reader within EvtFileClose? Anyhow will try to do your idle suggestion tomorrow
and will post the result.
Thanks

I dunno… You’re calling WdfIoTargetStop, yes? What options are you specifying? What does “my code is failing” mean (I didn’t think WdfIoTargetStop returned any status). Do you have KMDF Verifier enabled? What does the log say?

Peter
OSR

This is what I do (from EvtFileClose):

WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(pPipeContext->PipeHandle),
WdfIoTargetCancelSentIo);

PipeHandle is the handle that was WdfUsbInterfaceGetConfiguredPipe()-ed in
EvtFileCreate().

Here is what I receive (BSOD):

BugCheck 8E, {80000003, 804e3b14, bae8f9d0, 0}

EXCEPTION_CODE: (HRESULT) 0x80000003 (2147483651) - One or more arguments are
invalid

No I didn’t run verifier yet, will do that.
Thanks,

Please send the output of !analyze -v (with correct symbols please). that will give a better initial indication of where the error is

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@chello.hu
Sent: Tuesday, October 07, 2008 11:09 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Life cycle of USB Pipes within WDF

This is what I do (from EvtFileClose):

WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(pPipeContext->PipeHandle),
WdfIoTargetCancelSentIo);

PipeHandle is the handle that was WdfUsbInterfaceGetConfiguredPipe()-ed in
EvtFileCreate().

Here is what I receive (BSOD):

BugCheck 8E, {80000003, 804e3b14, bae8f9d0, 0}

EXCEPTION_CODE: (HRESULT) 0x80000003 (2147483651) - One or more arguments are
invalid

No I didn’t run verifier yet, will do that.
Thanks,


NTDEV is sponsored by OSR

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

Hello Doron,

sorry to tell but I’m a bit lost :frowning:
my WinDbg doesn’t complain about missing symbols, what I gave to in the beginning (first post)
was all that I received with !analyze -v :frowning:
Why do you think the symbols are bad?
Thanks,

(I assume that, like me, Doron was reading this thread from approximately the middle and didn’t see the !analyze -v output… I know *I* didn’t :slight_smile:

Peter
OSR

This

bae8fa40 ba4b584f 8228a8c8 8228a934 81f2239c nt!DbgBreakPoint+0x1
bae8fa58 baf3199a 021330c0 7e2925d0 00000001 wdf01000!imp_WdfIoTargetStop+0x9a

leads me to believe that the KMDF verifier is on and that you are calling the DDI at IRQL > PASSIVE_LEVEL, probably DISPATCH_LEVEL because you are holding onto a spinlock (but that is just a guess :slight_smile: ). To stop a c.r. you must be at passive so the api can synchronously collect all pending io and return when they have been successfully canceled.

!wdfkd.wdflogdump e6usb

Would have told you this

D

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@chello.hu
Sent: Tuesday, October 07, 2008 11:49 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Life cycle of USB Pipes within WDF

Hello Doron,

sorry to tell but I’m a bit lost :frowning:
my WinDbg doesn’t complain about missing symbols, what I gave to in the beginning (first post)
was all that I received with !analyze -v :frowning:
Why do you think the symbols are bad?
Thanks,


NTDEV is sponsored by OSR

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

Doron Holan wrote:

To stop a c.r. you must be at passive so the api can synchronously collect
all pending io and return when they have been successfully canceled.

…even if you pass WdfIoTargetLeaveSentIoPending.

Yes, the c.r. will override this into a cancel synchronous call

d

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Tuesday, October 07, 2008 1:56 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Life cycle of USB Pipes within WDF

Doron Holan wrote:

To stop a c.r. you must be at passive so the api can synchronously collect
all pending io and return when they have been successfully canceled.

…even if you pass WdfIoTargetLeaveSentIoPending.


NTDEV is sponsored by OSR

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

Hello Doron,

I guess you’re the genie in the bottle. Yes indeed I’m holding on a spinlock (wanted to synch
pipe close and the c.r. is accessing it). Thanks, will check what I can do about it!
Thanks,

Guys, you are simply unbelievable. I blindly missed that i’m going to dispatch_level when acquire-ing the spinlock :((( Lame me. Put the acquire after the wdfiotargetstop and everything works normal now. Thanks again!