WDK5600, Win2K, and USB

I recently swiched my driver development platform from 3790.1803/WDF to the new KMDF 1.5 (WDK 5600) version. Since 1.5 HAS to be developed in XP and my main workstation is 2k, my driver development is now done in a virtual machine until my new laptop gets here! I am developing a USB driver for a device that would prefer to use an alternate configuration containing an isochronous endpoint. This driver will support 2k, xp, and s2003. Since it is pretty well documented here that 2k has problems with a 1.1-based driver switching to alternate configurations, I switched to 1.5 and suddenly the other (Interrupt) endpoint in the alternate configuration worked! In pressing on, I discovered that in 2k, the WdfUsbTargetPipeSendUrbSynchronously call to read data from the isochronous pipe failed with a 0xc000000d (which is Invalid_Parameter i think). The exact same code built in the XP build environment and run on XP works fine.

There shouldn’t need to be any code differences for a driver to work under 2k and xp. Does this mean there’s most likely a problem in the 1.5 framework?

jorj

What does the KMDF log say? Just to see if you are passing in the right
parameters, try formatting the request
(WdfUsbTargetPipeFormatRequestForUrb) and then sending it synchronously
(WdfRequestSend). Does the format succeed? If so, then the error is
coming from the usb core, not KMDF.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@bhware.com
Sent: Tuesday, October 03, 2006 8:43 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] WDK5600, Win2K, and USB

I recently swiched my driver development platform from 3790.1803/WDF to
the new KMDF 1.5 (WDK 5600) version. Since 1.5 HAS to be developed in
XP and my main workstation is 2k, my driver development is now done in a
virtual machine until my new laptop gets here! I am developing a USB
driver for a device that would prefer to use an alternate configuration
containing an isochronous endpoint. This driver will support 2k, xp,
and s2003. Since it is pretty well documented here that 2k has problems
with a 1.1-based driver switching to alternate configurations, I
switched to 1.5 and suddenly the other (Interrupt) endpoint in the
alternate configuration worked! In pressing on, I discovered that in
2k, the WdfUsbTargetPipeSendUrbSynchronously call to read data from the
isochronous pipe failed with a 0xc000000d (which is Invalid_Parameter i
think). The exact same code built in the XP build environment and run
on XP works fine.

There shouldn’t need to be any code differences for a driver to work
under 2k and xp. Does this mean there’s most likely a problem in the
1.5 framework?

jorj


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

I wasn’t sure what you meant by “KMDF Log” so I googled it and found this page: http://www.microsoft.com/whdc/driver/tips/KMDF_IfrLog.mspx. If that is what you meant, I couldnt get it to work.

I tried using the WdfUsbTargetPipeFormatRequestForUrb/WdfRequestSend approach (what a PITA that is!) and discovered that calling that function makes it bug check very reliably. Here is the code:

***

KdPrint((_DN “WdfRequestCreate…\n”));
status = WdfRequestCreate(0,
0,
&Request);
if(!NT_SUCCESS(status)) {
KdPrint((_DN " - FAILED (0x%08x)\n", status));
goto end;
} else {
KdPrint((_DN " - OK\n"));
}

KdPrint((_DN “WdfUsbTargetPipeFormatRequestForUrb: get image…\n”));
status = WdfUsbTargetPipeFormatRequestForUrb(
devCtx->UsbInterruptOutPipe,
Request,
purb,
0);
if(!NT_SUCCESS(status)) {
KdPrint((_DN " - FAILED (0x%08x)\n", status));
goto end;
} else {
KdPrint((_DN " - OK\n"));
}

***

I dont even bother trying to send the request, and it appears that theres no need to anyway, as the function to build it blows everything up!

jorj

What is the bugcheck? Is pUrb a WDFMEMORY handle ?

Try http://blogs.msdn.com/doronh/archive/2006/07/31/684531.aspx for help
on viewing the log. Why is formatting a request and then sending it a
PITA? I can understand that for sync i/o it is a bit more work, but for
async i/o, I don’t see what the problem is. As Robert pointed out, what
is the type of purb? It needs to be a WDFMEMORY. Also, if you pass the
UsbInterruptOutPipe to WdfRequestCreate, it will know how big of a PIRP
to allocate at create time (vs format time)

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@bhware.com
Sent: Tuesday, October 03, 2006 1:40 PM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WDK5600, Win2K, and USB

I wasn’t sure what you meant by “KMDF Log” so I googled it and found
this page: http://www.microsoft.com/whdc/driver/tips/KMDF_IfrLog.mspx.
If that is what you meant, I couldnt get it to work.

I tried using the WdfUsbTargetPipeFormatRequestForUrb/WdfRequestSend
approach (what a PITA that is!) and discovered that calling that
function makes it bug check very reliably. Here is the code:

***

KdPrint((_DN “WdfRequestCreate…\n”));
status = WdfRequestCreate(0,
0,
&Request);
if(!NT_SUCCESS(status)) {
KdPrint((_DN " - FAILED (0x%08x)\n", status));
goto end;
} else {
KdPrint((_DN " - OK\n"));
}

KdPrint((_DN “WdfUsbTargetPipeFormatRequestForUrb: get
image…\n”));
status = WdfUsbTargetPipeFormatRequestForUrb(
devCtx->UsbInterruptOutPipe,
Request,
purb,
0);
if(!NT_SUCCESS(status)) {
KdPrint((_DN " - FAILED (0x%08x)\n", status));
goto end;
} else {
KdPrint((_DN " - OK\n"));
}

***

I dont even bother trying to send the request, and it appears that
theres no need to anyway, as the function to build it blows everything
up!

jorj


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

When I call WdfUsbTargetPipeFormatRequestForUrb, I get the following bugcheck:

Thu Oct 5 08:17:35.546 2006 (GMT-5): Access violation - code c0000005 (!!! second chance !!!)
Wdf01000!FxObjectHandleGetPtr+0x7f:
bd2bc6bb 66395f04 cmp word ptr [edi+4],bx

***

Once I got the log figured out (thank you for the link), I got this output:

wdftrace: gTracePrefix: “”
wdftrace: gTracePrefixDefault: "%7!u!: %2!-20.20s! – "
wdftrace: trace format prefix: %7!u!: %2!-20.20s! –
Log at 82185000
Gather log: Please wait, this may take a moment (reading 4032 bytes).
% read so far … 10, 20, 100
There are 24 log entries
— start of log —
Unknown( 14): GUID=7027751f-fc0a-2cd4-9eb3-d463b8020d05 (No Format Information found).
Unknown( 10): GUID=d9bac651-67f0-a6af-37c0-9c0156e983a5 (No Format Information found).
Unknown( 14): GUID=7027751f-fc0a-2cd4-9eb3-d463b8020d05 (No Format Information found).
Unknown( 14): GUID=7027751f-fc0a-2cd4-9eb3-d463b8020d05 (No Format Information found).
Unknown( 20): GUID=e82be483-56ef-98d3-4d84-6e3606cddadf (No Format Information found).
Unknown( 20): GUID=e82be483-56ef-98d3-4d84-6e3606cddadf (No Format Information found).
Unknown( 15): GUID=df1b4494-a2bd-2280-16d3-fbdd9b6b5289 (No Format Information found).
Unknown( 16): GUID=13319c39-85e2-a5da-6f87-d41f5df1dd1d (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 16): GUID=13319c39-85e2-a5da-6f87-d41f5df1dd1d (No Format Information found).
Unknown( 16): GUID=13319c39-85e2-a5da-6f87-d41f5df1dd1d (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 15): GUID=df1b4494-a2bd-2280-16d3-fbdd9b6b5289 (No Format Information found).
Unknown( 15): GUID=df1b4494-a2bd-2280-16d3-fbdd9b6b5289 (No Format Information found).
Unknown( 15): GUID=df1b4494-a2bd-2280-16d3-fbdd9b6b5289 (No Format Information found).
Unknown( 16): GUID=13319c39-85e2-a5da-6f87-d41f5df1dd1d (No Format Information found).
Unknown( 14): GUID=7027751f-fc0a-2cd4-9eb3-d463b8020d05 (No Format Information found).
Unknown( 14): GUID=7027751f-fc0a-2cd4-9eb3-d463b8020d05 (No Format Information found).
Unknown( 26): GUID=e84b66a6-fc35-8cf1-3ad9-569326e99511 (No Format Information found).
---- end of log ----

***

Now a question: In the WdfUsbTargetPipeFormatRequestForUrb call, should I specify the ISOCHRONOUS IN endpoint as the pipe? I know I set it in the urb (I am reading from the device), but should it be set in the call as well? I know that in my older code with the WdfUsbTargetPipeSendUrbSynchronously call, I specify an INTERRUPT OUT endpoint in the function call and the ISOCHRONOUS IN in the urb and this worked fine in XP.

thanks for the feedback.

jorj

Given the code you showed previously, the fact that you were previously using the synchronous form of send (which uses a pointer to the URB) and the fact that you have an access violation in the routine that converts a WDF handle to an object pointer, I’d say the odds are quite high that my previous post was right on:

You are passing a pointer to the URB where you have to be passing a pointer to a WDFMEMORY containing the URB (the third parameter to the format DDI). If the URB is not already in a WDFMEMORY, then you can wrap it in one using WdfMemorycreatePreAllocated.

Also, to get a usable log, you need to tell the debugger extension where the log formatting information is:

!wdftmffile \tools\tracing<processor-architecture>\wdf01005.tmf

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@bhware.com
Sent: Thursday, October 05, 2006 6:55 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] WDK5600, Win2K, and USB

When I call WdfUsbTargetPipeFormatRequestForUrb, I get the following bugcheck:

Thu Oct 5 08:17:35.546 2006 (GMT-5): Access violation - code c0000005 (!!! second chance !!!)
Wdf01000!FxObjectHandleGetPtr+0x7f:
bd2bc6bb 66395f04 cmp word ptr [edi+4],bx



Once I got the log figured out (thank you for the link), I got this output:

wdftrace: gTracePrefix: “”
wdftrace: gTracePrefixDefault: "%7!u!: %2!-20.20s! – "
wdftrace: trace format prefix: %7!u!: %2!-20.20s! –
Log at 82185000
Gather log: Please wait, this may take a moment (reading 4032 bytes).
% read so far … 10, 20, 100
There are 24 log entries
— start of log —
Unknown( 14): GUID=7027751f-fc0a-2cd4-9eb3-d463b8020d05 (No Format Information found).
Unknown( 10): GUID=d9bac651-67f0-a6af-37c0-9c0156e983a5 (No Format Information found).
Unknown( 14): GUID=7027751f-fc0a-2cd4-9eb3-d463b8020d05 (No Format Information found).
Unknown( 14): GUID=7027751f-fc0a-2cd4-9eb3-d463b8020d05 (No Format Information found).
Unknown( 20): GUID=e82be483-56ef-98d3-4d84-6e3606cddadf (No Format Information found).
Unknown( 20): GUID=e82be483-56ef-98d3-4d84-6e3606cddadf (No Format Information found).
Unknown( 15): GUID=df1b4494-a2bd-2280-16d3-fbdd9b6b5289 (No Format Information found).
Unknown( 16): GUID=13319c39-85e2-a5da-6f87-d41f5df1dd1d (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 16): GUID=13319c39-85e2-a5da-6f87-d41f5df1dd1d (No Format Information found).
Unknown( 16): GUID=13319c39-85e2-a5da-6f87-d41f5df1dd1d (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 13): GUID=b4075e09-345a-ed88-6820-5859710ee974 (No Format Information found).
Unknown( 15): GUID=df1b4494-a2bd-2280-16d3-fbdd9b6b5289 (No Format Information found).
Unknown( 15): GUID=df1b4494-a2bd-2280-16d3-fbdd9b6b5289 (No Format Information found).
Unknown( 15): GUID=df1b4494-a2bd-2280-16d3-fbdd9b6b5289 (No Format Information found).
Unknown( 16): GUID=13319c39-85e2-a5da-6f87-d41f5df1dd1d (No Format Information found).
Unknown( 14): GUID=7027751f-fc0a-2cd4-9eb3-d463b8020d05 (No Format Information found).
Unknown( 14): GUID=7027751f-fc0a-2cd4-9eb3-d463b8020d05 (No Format Information found).
Unknown( 26): GUID=e84b66a6-fc35-8cf1-3ad9-569326e99511 (No Format Information found).
---- end of log ----



Now a question: In the WdfUsbTargetPipeFormatRequestForUrb call, should I specify the ISOCHRONOUS IN endpoint as the pipe? I know I set it in the urb (I am reading from the device), but should it be set in the call as well? I know that in my older code with the WdfUsbTargetPipeSendUrbSynchronously call, I specify an INTERRUPT OUT endpoint in the function call and the ISOCHRONOUS IN in the urb and this worked fine in XP.

thanks for the feedback.

jorj


Questions? First check the Kernel Driver FAQ at http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer

Yes, you were right on about that. Before you posted, I noticed that I was making a new WDFMEMORY object and having purb point to the data chunk of it. Then I was making purb point to a new chunk of memory allocated with a different function (I saw that code in a different example), THEN I was actuall yusing purb! I removed the other allocation and that didnt fix it. Then I saw your reply and passed the whole MWFMEMORY object instead of just the urb.

I now get past the format function and even send it. Unfortunately, it falls apart quickly after that. I have observed:

  1. If I just plug in the device, request the ISO read, I get no data back, but it doesnt crash. If i request a second time, it bugchecks.

  2. If I plug in the device, request the ISO read, and then unplug the device, it bugchecks after completing EvtDeviceD0Exit (something I’m pretty sure I’ve never seen this code do before - the code i based off the WDF examples at codeprojects.com).

  3. If I plug in the device, do some Interrupt communications, and the try the ISO read, it bugchecks.

Progress has been made, but something is still not quite right.

jorj

I made some new discoveries this morning. I am pretty convinced that the problem is how I load the urb. I started commenting out large blocks of code and seeing what crashed the system and what didn’t. Some of this code was taken from the WDM iso example in the ddk. Here is my routine to requesting an image from a usb device:

***

//get the buffers and sizes ready
imageBufferSize = bufferSize;
chunkSize = (ird->imgX * 2) + 4; //2 rows plus 4-byte header
numOfChunks = (imageBufferSize+(chunkSize-1)) / chunkSize;
urbSize = GET_ISO_URB_SIZE(numOfChunks);
KdPrint((_DN “* Need to send %d bytes *\n”, imageBufferSize));
KdPrint((_DN “* That makes %d packets of size %d *\n”, numOfChunks, chunkSize));
KdPrint((_DN “* urbSize = %d *\n”, urbSize));
//first, zero it out
//RtlZeroMemory(purb, urbSize); //<– THIS LINE CRASHES WIN2K AFTER A FEW TRIES
RtlFillMemory(retBuffer, imageBufferSize, 255);

purb->UrbIsochronousTransfer.Hdr.Length = (short)urbSize;
purb->UrbIsochronousTransfer.Hdr.Function = URB_FUNCTION_ISOCH_TRANSFER;
purb->UrbIsochronousTransfer.PipeHandle = WdfUsbTargetPipeWdmGetPipeHandle(devCtx->UsbDataInPipe);
purb->UrbIsochronousTransfer.TransferFlags = USBD_TRANSFER_DIRECTION_IN|USBD_START_ISO_TRANSFER_ASAP;
purb->UrbIsochronousTransfer.TransferBufferLength = imageBufferSize;
purb->UrbIsochronousTransfer.TransferBuffer = retBuffer;
purb->UrbIsochronousTransfer.TransferBufferMDL = NULL;
//purb->UrbIsochronousTransfer.StartFrame = CurrentFrameNumber;
purb->UrbIsochronousTransfer.NumberOfPackets = numOfChunks;
// THIS CRASHES WIN2K
// for(i=0; i// purb->UrbIsochronousTransfer.IsoPacket[i].Offset = ichunkSize;
// purb->UrbIsochronousTransfer.IsoPacket[i].Length = 0;
// }

**

The dbg output of those 3 KdPrint calls is:
Fri Oct 6 10:06:56.515 2006 (GMT-5): SSFP: * Need to send 25920 bytes *
Fri Oct 6 10:06:56.515 2006 (GMT-5):
Fri Oct 6 10:06:56.531 2006 (GMT-5): SSFP: * That makes 144 packets of size 180 *
Fri Oct 6 10:06:56.531 2006 (GMT-5):
Fri Oct 6 10:06:56.546 2006 (GMT-5): SSFP: * urbSize = 1824 *

The big chrashers are the RtlZeroMemory call and the loop filling the IsoPacket structs. I saw these functions used in a WDM example. Are they not supposed to be used in WDF? Am I missing something?

jorj

Both of those indicate your Urb was allocated smaller than the size you are using it as. Since pUrb’s allocation isn’t in this code, there’s no way to be absolutely certain, but that’s the most likely cause by far of what you’re reporting.

So the question is, how are you allocating that memory?

xxxxx@bhware.com wrote:

I made some new discoveries this morning. I am pretty convinced that the problem is how I load the urb. I started commenting out large blocks of code and seeing what crashed the system and what didn’t. Some of this code was taken from the WDM iso example in the ddk. Here is my routine to requesting an image from a usb device:

***

//get the buffers and sizes ready
imageBufferSize = bufferSize;
chunkSize = (ird->imgX * 2) + 4; //2 rows plus 4-byte header
numOfChunks = (imageBufferSize+(chunkSize-1)) / chunkSize;
urbSize = GET_ISO_URB_SIZE(numOfChunks);
KdPrint((_DN “* Need to send %d bytes *\n”, imageBufferSize));
KdPrint((_DN “* That makes %d packets of size %d *\n”, numOfChunks, chunkSize));
KdPrint((_DN “* urbSize = %d *\n”, urbSize));
//first, zero it out
//RtlZeroMemory(purb, urbSize); //<– THIS LINE CRASHES WIN2K AFTER A FEW TRIES
RtlFillMemory(retBuffer, imageBufferSize, 255);

How do you allocate the URB? You show us computing the urbSize, but I
don’t see where you allocate it. If you are reusing some other URB, are
you sure it’s big enough?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Sorry. Here is where I allocate the urb:

***

//allocate buffer for urb
KdPrint((_DN “WdfMemoryCreate: Allocating URB buffer…\n”));
status = WdfMemoryCreate(
WDF_NO_OBJECT_ATTRIBUTES,
NonPagedPool,
0,
sizeof(struct _URB_ISOCH_TRANSFER),
&urbMemory,
NULL);
if(!NT_SUCCESS(status)){
KdPrint((_DN " - ERROR (0x%08x)\n", status));
goto end;
} else {
KdPrint((_DN " - OK\n"));
}

purb = WdfMemoryGetBuffer(
urbMemory,
NULL);

***

The actual “retBuffer” that the data gets put in is the buffer I pass from my DeviceIOControl call and get from a WdfRequestRetrieveOutputBuffer call.

Thanks for the feedback.

jorj

I think i see the problem. I’m now allocating the urb to size ‘urbSize’ instead of that struct size. I’ll see if that fixes it.

jorj

xxxxx@bhware.com wrote:

Sorry. Here is where I allocate the urb:

***

//allocate buffer for urb
KdPrint((_DN “WdfMemoryCreate: Allocating URB buffer…\n”));
status = WdfMemoryCreate(
WDF_NO_OBJECT_ATTRIBUTES,
NonPagedPool,
0,
sizeof(struct _URB_ISOCH_TRANSFER),
&urbMemory,
NULL);

And this clearly explains why you are getting a crash. You are
allocating only enough room for the URB_ISOCH_TRANSFER structure,
without including room for any of the packet descriptors. Later, when
you do this:

urbSize = GET_ISO_URB_SIZE(numOfChunks);
KdPrint((_DN “* Need to send %d bytes *\n”, imageBufferSize));
KdPrint((_DN “* That makes %d packets of size %d *\n”, numOfChunks, chunkSize));
KdPrint((_DN “* urbSize = %d *\n”, urbSize));
//first, zero it out
//RtlZeroMemory(purb, urbSize); //<– THIS LINE CRASHES WIN2K AFTER A FEW TRIES

urbSize is way bigger than sizeof(struct _URB_ISOCH_TRANSFER). Boom.

Compute urbSize first. THEN call WdfMemoryCreate.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Yes. That did fix that, and I fully understand why it failed.

I think the problem I have now takes us way back to the top of this thread. In Win2k, the WdfRequestSend function returns true, but the Hdr.Status part of the urb is 80000300, which usb.h defines as USBD_STATUS_INVALID_PARAMETER. Since the invalid parameter is happening at this level, I take it that something in the urb is still not quite right. The same code does work in XP though, but seeing that XP worked pretty well with a buffer overflow, it seems that it’s (dangerously) more forgiving about errors like this.

jorj

xxxxx@bhware.com wrote:

Yes. That did fix that, and I fully understand why it failed.

I think the problem I have now takes us way back to the top of this thread. In Win2k, the WdfRequestSend function returns true, but the Hdr.Status part of the urb is 80000300, which usb.h defines as USBD_STATUS_INVALID_PARAMETER. Since the invalid parameter is happening at this level, I take it that something in the urb is still not quite right. The same code does work in XP though, but seeing that XP worked pretty well with a buffer overflow, it seems that it’s (dangerously) more forgiving about errors like this.

How many packets are you shoving in your URB? Win2K has a smaller
data-transfer-per-URB limit than XP.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I have been working on getting the Iso transfers in XP to work better. Once its the way I want it, I will get back to getting the 2k version to work.

In XP, I have been having problems getting larger transfers to work.

According to the help in the 5600 DDK:

***

Maximum Transfer Sizes in Windows 2000, Windows XP and Windows 2003 Server
Control Pipes 4,000 bytes on the endpoint associated with Alt setting 0, 64,000 other pipes
Bulk and Interrupt Pipes 256,000 bytes.
Isochronous Pipes 256 frames on full-speed devices, 1024 frames high-speed devices.

***

I also read that Iso is limited to 255 frames if the ASAP bit is set due to a bug, and that the ASAP bit should not be set on transfers done immediately after a previous transfer. After learning this, I took out the ASAP bit and set the start frame to current frame plus some number (currently 30, but we will tune this once we get it working). This still works with smaller packets, but once they get bigger, it fails.

From what I observed, when I load an URB for this:
MaxPacketSize = 708 bytes
TotalBytesRead = 69420 bytes
PacketSize = 356 bytes
NumOfPackets = 195

and call WdfUsbTargetPipeSendUrbSynchronously, it works.

However, if I load one like this:
MaxPacketSize = 708 bytes
TotalBytesRead = 71200 bytes
PacketSize = 356 bytes
NumOfPackets = 200

and call WdfUsbTargetPipeSendUrbSynchronously, the function never returns, even though I have set a timeout. Is there some 70K per URB limit that I didn’t see in the documentation?

xxxxx@bhware.com wrote:

I also read that Iso is limited to 255 frames if the ASAP bit is set due to a bug, and that the ASAP bit should not be set on transfers done immediately after a previous transfer. After learning this, I took out the ASAP bit and set the start frame to current frame plus some number (currently 30, but we will tune this once we get it working). This still works with smaller packets, but once they get bigger, it fails.

>From what I observed, when I load an URB for this:
MaxPacketSize = 708 bytes
TotalBytesRead = 69420 bytes
PacketSize = 356 bytes
NumOfPackets = 195

Any reason why you have PacketSize smaller than MaxPacketSize?
Ordinarily, you would set PS = MPS. I don’t think it is causing your
problem, but it means that data in each packet beyond the first 356
bytes might be lost.

Is this USB 2.0? What is your isochronous rate set to?

and call WdfUsbTargetPipeSendUrbSynchronously, it works.

However, if I load one like this:
MaxPacketSize = 708 bytes
TotalBytesRead = 71200 bytes
PacketSize = 356 bytes
NumOfPackets = 200

and call WdfUsbTargetPipeSendUrbSynchronously, the function never returns, even though I have set a timeout. Is there some 70K per URB limit that I didn’t see in the documentation?

I’m just speculating here, but I wonder if this is related to the 255
frame thing. Your number of packets plus your starting packet offset
aren’t equal to 255 yet, but that’s the only limit that I can see you
are approaching.

The number-of-packets-per-URB question is one of diminishing returns.
At very low values, the overhead means you can’t keep up. As the number
goes up, efficiency improves, but after a certain point, you don’t gain
anything. The overhead becomes small enough to be ignorable. You end
up need to balance number-of-packets-per-URB with
number-of-simultaneous-outstanding-URBs.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Thanks for the reply.
The size of the data chunks coming back is determined by the request. We can and will change that though, to make the transfer more efficient. My ultimate goal here is to do multiple Iso urb requests for larger data chunks, and I am having lots of problems getting it working. I have a few ideas/questinons about the process.

  1. I am currently doing the urb requests synchronously. I am sure that asnychronous will be better, as sync would probably cause gaps in the received data. Is this true?

  2. I am writing the data straight to the buffer that I got from the WdfRequestRetrieveOutputBuffer call. Is this ok or do I have to create a WDFMEMORY object to catch the data and copy it to the return buffer?

  3. In my loop for filling and sending the URB_FUNCTION_ISOCH_TRANSFER urbs, I call WdfMemoryCreate at the top to create the memory urb. I always pass it the same WDFMEMORY object. Is it bad to pass the same WDFMEMORY object to multiple WdfMemoryCreate calls?

  4. I know there will only be a few URBs for each transaction. Am I better off allocating a big chunk of memory to hold each URB and fill them all out before I send them? This would probably require setting the startframe for each before sending it, but the rest could be all pre-loaded. Is this a preferred approach?

Thank you for the feedback. I just wish there were some samples of Iso transfers with the new WDK available!

jorj

xxxxx@bhware.com wrote:

Thanks for the reply.
The size of the data chunks coming back is determined by the request. We can and will change that though, to make the transfer more efficient. My ultimate goal here is to do multiple Iso urb requests for larger data chunks, and I am having lots of problems getting it working.

If you have variable length data, why are you using isochronous at all?
An isochronous pipe is intended for very regular data of a regular
size. If you have variable length data at irregular intervals, you
should be using a bulk pipe. A bulk pipe can sustain MUCH higher
bandwidth than an isochronous pipe. Plus bulk pipes will retry on
errors, whereas isochronous pipes don’t – packets with errors are
simply lost.

Isochronous pipes in USB 2.0 aren’t really very useful. That may be why
the KMDF team didn’t spent much time on them.

I have a few ideas/questinons about the process.

  1. I am currently doing the urb requests synchronously. I am sure that asnychronous will be better, as sync would probably cause gaps in the received data. Is this true?

True. If you only have one URB pending, you can’t complete it and turn
it around before the start of the next frame. If you don’t have a URB
queued up by the start of a frame, you will miss that frame. The host
controller will not tickle the device, even for isochronous pipes.

  1. I am writing the data straight to the buffer that I got from the WdfRequestRetrieveOutputBuffer call. Is this ok or do I have to create a WDFMEMORY object to catch the data and copy it to the return buffer?

You should be able to copy it directly. You get a pointer.

  1. In my loop for filling and sending the URB_FUNCTION_ISOCH_TRANSFER urbs, I call WdfMemoryCreate at the top to create the memory urb. I always pass it the same WDFMEMORY object. Is it bad to pass the same WDFMEMORY object to multiple WdfMemoryCreate calls?

It’s NOT the same object. The Memory parameter is an output parameter.
WdfMemoryCreate will create a new WDFMEMORY object each time. If you
are not calling WdfObjectDelete, then you have a memory leak, at least
until the parent object closes. What are you specifying as the parent?
If the buffer is the same size, can’t you just reuse the object and skip
the WdfMemoryCreate?

  1. I know there will only be a few URBs for each transaction. Am I better off allocating a big chunk of memory to hold each URB and fill them all out before I send them? This would probably require setting the startframe for each before sending it, but the rest could be all pre-loaded. Is this a preferred approach?

I’m not sure what the question is. If I have a high-bandwidth endpoint,
I generally try to have 6 or 8 URBs queued up. So, if I want 240
packets pending, I could have 6 URBs of 40 packets, or 8 URBs of 32
packets, or something like that.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.