none
How to properly initilize MDL for isochronous USB transfer? RRS feed

  • Question

  • Hello,

    I try to perform isochronous transfers in my driver. However I can't get it working.

    My first version of sending routine looks like this: http://pastebin.com/kLmMr5ZF Sending buffer is allocated via ExAllocatePoolWithTag. When I call this routine for the first time, everything seems to work. When I call the routine for the second time I get bug check BAD_POOL_HEADER or SYSTEM_SERVICE_EXCEPTION. This bug check occurs outside my driver.

    In all examples I have read so far is used MDL for the buffer instead of the raw buffer. So I rewrite my code to this version: http://pastebin.com/4MFE1e1P This code seems to work properly - until I write data into the buffer. When I write data in the buffer after 10-15 calls of the routine the same bug check occurs. When I use empty buffer (withou using memset or popSamples) no bug check occurs.

    As my last attempt, I changed initialization of MDL. I have made these changes to the code:

    context->dataBufferPointer = ExAllocatePoolWithTag(NonPagedPool, buffer->getSampleSize()*buffer->getSize(), 'TAG1'); 
    context->dataBuffer = IoAllocateMdl(context->dataBufferPointer, (ULONG)(buffer->getSampleSize()*buffer->getSize()), FALSE, FALSE, NULL);
    MmBuildMdlForNonPagedPool(context->dataBuffer);
    ...
    urb->UrbIsochronousTransfer.TransferBufferMDL = context->dataBuffer;

    This code causes another bug check - when I call WdfUsbTargetPipeFormatRequestForUrb I get SYSTEM_THREAD_EXCEPTION_NOT_HANDLED with error code STATUS_ACCESS_VIOLATION.

    What am I doing wrong? How should I properly initialize/allocate buffer for isochronous transfer?

    Saturday, April 19, 2014 11:00 AM

Answers

  • first one you ran out stack, the Io repeatedly completed synchronously. The second is the USB core referencing null, usually happens when your driver frees a resource while still in use or you leave Io pending after the device has been removed. Third is a null deref in kmdf, I would suspect a bad wdfusbpipe or wdfmemory handle in this case

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

    Sunday, April 20, 2014 3:54 PM
  • from the completion routine you can queue a doc (WDFDPC can be used) to defer to another thread. Since this is a Ks driver, I assume you are using wdf in miniport mode which means you need to destroy the wdfusbdevice when you receive a pnp remove and stop the wdfusbdevice when you see a pnp surprise remove.

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

    Sunday, April 20, 2014 9:47 PM

All replies

  • run !analyze -v and see what memory reference caused the exception and then see if it is within range of your buffer, or close to the range. Can your two get() calls to compute the size return different between two invocations?

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

    Saturday, April 19, 2014 3:43 PM
  • Thank you for your respond. I was trying to debug the driver, however I don't really understand the !analyze output. I was able to find out there are 3 bug check, which occurs randomly.

    Log from bug check 1: http://pastebin.com/ZJghLyKZ

    Log from bug check 2: http://pastebin.com/5sczT7VT

    Log from bug check 3: http://pastebin.com/NY5AVd4N

    What is really weird is the first bug check - it seems like kernel stack overflow. From my completine rotouine I call sending routine. I was assuming that transfers are perfomed asynochrously and the coumpletine routine is called from different thread. However in the call stack of the firs bug check the completion routine is called in the same thread - like the request was send synchronously.

    Could you help me to analyze the logs?

    EDIT: These logs are from the last version of the code - where I allocte buffer via ExAllocatePoolWithTag and then i build MDL - becouse I think that's the correct approach.

    • Edited by yaqwsx Sunday, April 20, 2014 2:41 PM
    Sunday, April 20, 2014 2:39 PM
  • first one you ran out stack, the Io repeatedly completed synchronously. The second is the USB core referencing null, usually happens when your driver frees a resource while still in use or you leave Io pending after the device has been removed. Third is a null deref in kmdf, I would suspect a bad wdfusbpipe or wdfmemory handle in this case

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

    Sunday, April 20, 2014 3:54 PM
  • Thank you for such a quick response! From what you have wrote I'm starting to think I don't abort pending request when the WdfUsbDevice is being destroyed. I have to look at it.

    I am getting a little bit confused about how does the USB part of WDF works. I need to periodically send data to an isochronous endpoint of my device. So I thought I call send routine, which sends first packet and than in a completion routine I call the send routine again - I thought the completion routine runs in a different thread since the request should be handeled asynchronously. But from the bug check it seems like the request is proccessed  synchronously...  What's the correct way of sending data periodically?

    Sunday, April 20, 2014 5:28 PM
  • from the completion routine you can queue a doc (WDFDPC can be used) to defer to another thread. Since this is a Ks driver, I assume you are using wdf in miniport mode which means you need to destroy the wdfusbdevice when you receive a pnp remove and stop the wdfusbdevice when you see a pnp surprise remove.

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

    Sunday, April 20, 2014 9:47 PM