Read isochronous data length is always 0

Hi,

I'm writing a USB driver which supports isochronous transfer and it takes me
a headache.

I need to continuously reading Isochronous, and I make a timer to send read
packet. Now I can send Isochronous read request, and both
CompletionParams->IoStatus.Status and Urb->UrbHeader.Status are success. But
the Urb->UrbIsochronousTransfer.TransferBufferLength is always 0. I'm sure
that there are isochronous data sent to the USB device, because I find the
SCO data in the air packet (the driver is for a Bluetooth dangle).

I'm not sure the reason now, my questions are as followed:

  1. I select Interface 1 Alternate 1 (the first Alternate which
    supports isochronous) to read isochronous data, but I'm not sure whether it
    is OK. If not, which pipe I should select.

  2. When I send Isochronous in request with TransferBufferLength=1024,
    the returned Urb->UrbIsochronousTransfer.TransferBufferLength is not 0, but
    when I send with Urb->UrbIsochronousTransfer.TransferBufferLength=256, the
    length is always 0. Is it just because of full-speed USB packet can not
    exceed 1023?

  3. Why there is always no data return?

I'm so puzzled now, please help me~~


Confidentiality Notice: The information contained in this e-mail and any accompanying attachment(s)
is intended only for the use of the intended recipient and may be confidential and/or privileged of
Neusoft Corporation, its subsidiaries and/or its affiliates. If any reader of this communication is
not the intended recipient, unauthorized use, forwarding, printing, storing, disclosure or copying
is strictly prohibited, and may be unlawful.If you have received this communication in error,please
immediately notify the sender by return e-mail, and delete the original message and all copies from
your system. Thank you.

You wrote:

I'm writing a USB driver which supports isochronous transfer and it takes
me a headache.

Yes, it can do that.

I need to continuously reading Isochronous, and I make a timer to send
read packet.

That is a VERY bad idea. Instead, you should submit a couple of requests immediately, as soon as you start streaming. Then, in the completion routine, you dispose of the data, and resubmit the request. USB already has timing -- use it, instead of reinventing the wheel.

Now I can send Isochronous read request, and both
CompletionParams->IoStatus.Status and Urb->UrbHeader.Status are success.
But the Urb->UrbIsochronousTransfer.TransferBufferLength is always 0.
I'm sure that there are isochronous data sent to the USB device, because
I find the SCO data in the air packet (the driver is for a Bluetooth
dangle).

Are you setting up the IsoPacket array? Isochronous requests work very differently from other requests. You don't just supply a single pointer to a single buffer. Instead, you set up the IsoPacket array to point to spots WITHIN your buffer where each individual packet will be copied (if it succeeds).

I'm not sure the reason now, my questions are as followed:

  1. I select Interface 1 Alternate 1 (the first Alternate which
    supports isochronous) to read isochronous data, but I'm not sure
    whether it is OK. If not, which pipe I should select.

Your question doesn't make sense. You need to select an alternate setting that has your isochronous pipe with a bandwidth that matches your needs. Only YOU can know which pipe you need. That's part of the specs for your device.

  1. When I send Isochronous in request with TransferBufferLength=1024,
    the returned Urb->UrbIsochronousTransfer.TransferBufferLength is not 0,
    but when I send with Urb->UrbIsochronousTransfer.TransferBufferLength=256, the
    length is always 0. Is it just because of full-speed USB packet can not
    exceed 1023?

Well, wait a minute. When you send an isochronous request, the individual packets in your request must EXACTLY match the packet size in your endpoint. If you have a full-speed device, and the isoch pipe in the alternate setting you selected has a packet size of 1023, then your buffer must be a multiple of 1023 bytes in length. If you want a single request to handle 10 packets, then the buffer is 10230 bytes, and the elements in the IsoPacket array should point to offset 0, 1023, 2046, 3069, and so on.

  1. Why there is always no data return?

My guess is that you have the packeting done wrong.

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

Thanks very much! But I still can not found the problem.

  1. As the length could be more than 1023, why the result is different for
    MAX_DATA_LEN=1024(the return length is always not 0) and
    MAX_DATA_LEN=256(the return length is always 0).
  2. My packet is similar with $\WinDDK\7600.16385.0\src\usb\usbsamp, the
    differences is just that we allocate the mdl by myself.
    Mdl = IoAllocateMdl((PVOID)Data, //Data is the buffer of a memory
    MAX_DATA_LEN, FALSE, FALSE,
    NULL);
    MmBuildMdlForNonPagedPool(Mdl);
    And we set the TransferBufferLength to be 256 and TransferBufferMDL to be
    Mdl.
    ...
    Urb->UrbIsochronousTransfer.TransferBufferLength =
    MAX_DATA_LEN;//256
    Urb->UrbIsochronousTransfer.TransferBufferMDL = Mdl;
    ...

The packet size is 9, so there are 29 packets in this URB, and the last
packet length is 4, WdfUsbTargetPipeSetNoMaximumPacketSizeCheck has been
sent when the during device configure, so I think this packet length may be
OK.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Tim Roberts
Sent: Monday, February 08, 2010 11:28 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Read isochronous data length is always 0

You wrote:

I'm writing a USB driver which supports isochronous transfer and it takes
me a headache.

Yes, it can do that.

I need to continuously reading Isochronous, and I make a timer to send
read packet.

That is a VERY bad idea. Instead, you should submit a couple of requests
immediately, as soon as you start streaming. Then, in the completion
routine, you dispose of the data, and resubmit the request. USB already has
timing -- use it, instead of reinventing the wheel.

Now I can send Isochronous read request, and both
CompletionParams->IoStatus.Status and Urb->UrbHeader.Status are success.
But the Urb->UrbIsochronousTransfer.TransferBufferLength is always 0.
I'm sure that there are isochronous data sent to the USB device, because
I find the SCO data in the air packet (the driver is for a Bluetooth
dangle).

Are you setting up the IsoPacket array? Isochronous requests work very
differently from other requests. You don't just supply a single pointer to
a single buffer. Instead, you set up the IsoPacket array to point to spots
WITHIN your buffer where each individual packet will be copied (if it
succeeds).

I'm not sure the reason now, my questions are as followed:

  1. I select Interface 1 Alternate 1 (the first Alternate which
    supports isochronous) to read isochronous data, but I'm not sure
    whether it is OK. If not, which pipe I should select.

Your question doesn't make sense. You need to select an alternate setting
that has your isochronous pipe with a bandwidth that matches your needs.
Only YOU can know which pipe you need. That's part of the specs for your
device.

  1. When I send Isochronous in request with TransferBufferLength=1024,
    the returned Urb->UrbIsochronousTransfer.TransferBufferLength is not 0,
    but when I send with Urb->UrbIsochronousTransfer.TransferBufferLength=256,
    the
    length is always 0. Is it just because of full-speed USB packet can not
    exceed 1023?

Well, wait a minute. When you send an isochronous request, the individual
packets in your request must EXACTLY match the packet size in your endpoint.
If you have a full-speed device, and the isoch pipe in the alternate setting
you selected has a packet size of 1023, then your buffer must be a multiple
of 1023 bytes in length. If you want a single request to handle 10 packets,
then the buffer is 10230 bytes, and the elements in the IsoPacket array
should point to offset 0, 1023, 2046, 3069, and so on.

  1. Why there is always no data return?

My guess is that you have the packeting done wrong.

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


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars visit:

To unsubscribe, visit the List Server section of OSR Online at


Confidentiality Notice: The information contained in this e-mail and any accompanying attachment(s)
is intended only for the use of the intended recipient and may be confidential and/or privileged of
Neusoft Corporation, its subsidiaries and/or its affiliates. If any reader of this communication is
not the intended recipient, unauthorized use, forwarding, printing, storing, disclosure or copying
is strictly prohibited, and may be unlawful.If you have received this communication in error,please
immediately notify the sender by return e-mail, and delete the original message and all copies from
your system. Thank you.

zh.liang wrote:

Thanks very much! But I still can not found the problem.

  1. As the length could be more than 1023, why the result is different for
    MAX_DATA_LEN=1024(the return length is always not 0) and
    MAX_DATA_LEN=256(the return length is always 0).
  2. My packet is similar with $\WinDDK\7600.16385.0\src\usb\usbsamp, the
    differences is just that we allocate the mdl by myself.
    Mdl = IoAllocateMdl((PVOID)Data, //Data is the buffer of a memory
    MAX_DATA_LEN, FALSE, FALSE,
    NULL);
    MmBuildMdlForNonPagedPool(Mdl);
    And we set the TransferBufferLength to be 256 and TransferBufferMDL to be
    Mdl.

There’s no reason to use an MDL for this. Just shove your Data pointer
into TransferBuffer and leave TransferBufferMDL empty.


Urb->UrbIsochronousTransfer.TransferBufferLength =
MAX_DATA_LEN;//256
Urb->UrbIsochronousTransfer.TransferBufferMDL = Mdl;

The packet size is 9, so there are 29 packets in this URB, and the last
packet length is 4, WdfUsbTargetPipeSetNoMaximumPacketSizeCheck has been
sent when the during device configure, so I think this packet length may be
OK.

You still aren’t showing us the code that sets up the IsoPacket array.
When you say “the packet size is 9”, what, exactly, do you mean? Is
that actually the packet size from the endpoint descriptor? If not,
then the 9 is irrelevant. You need to set up the IsoPacket array to
match the packet size in the descriptor. If you expect to get 29
packets from an endpoint with a max packet size of 1023 bytes, then you
are required to submit a buffer of 29,667 bytes (29 x 1023), even if you
know that only 9 bytes will be filled in each packet.

Also remember that, for isochronous transfers, the data that comes back
is not necessarily packed into the buffer, like bulk and interrupt
transfers are. I wrote a little article on the difference between bulk
and isochronous transfers over the weekend that might offer a little help:
http://timr.probo.com/isoch.html


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