USB Bulk Read Size

Hello All,

I am currently looking through USB documentation and examples and would like to ask a question about size of read transfer.
Efficiency aside, I would like to understand the theory of things.
In WDM example, USB transfer is “staged” by multiple URBs, each is a multiply of max_packet_size.
A thread in this regard here suggests splitting the transaction into 512bytes stages, with <32 simultaneous URBs.

Now here is my question - when I try to make a single URB transaction request of 600bytes over bulk usb 2.0 HS endpoint, I get USBD_CRC_ERROR from host controller, while 1024bytes single transfer is working just fine.
Now i have been thinking - if the host controller breaks the request into 512b sized packets anyway, what would it return an error on attempt to send 600bytes ?
Can this be HW related only ?

Generally, how does the host controller handle a single bulk read URB of size >512b ?

Thanks
Sagi

Sagi Bar wrote:

Now here is my question - when I try to make a single
URB transaction request of 600bytes over bulk usb 2.0 HS
endpoint, I get USBD_CRC_ERROR from host controller,
while 1024bytes single transfer is working just fine.

Your URB bulk read size must be an exact multiple of the endpoint’s maximum packet size, so 600 bytes is probably not a valid read size.

Now i have been thinking - if the host controller breaks the
request into 512b sized packets anyway, what would it return
an error on attempt to send 600bytes ?

Well, to be more precise, a read of 600 bytes will cause an IN token to be sent to the device, and up to 512 bytes can be returned. If exactly 512 bytes is returned, another IN token will be sent (because it was not a short packet).

Unfortunately at this point, the device can return up to 512 bytes *again*, so anything more than 88 bytes will result in an error. (This is called “babble”).

When in doubt, RTFM. In particular, read the USB specs. The maximum bulk
data packet size is different for USB 1, USB 2, and USB 3. Since the USB
spec is a fre download from the USB site (I think it is www.usb.org),
there’s no reason to not have it.

I no longer remember the packet sizes for each, but I think each revision
multiplied the size by 2.

My suspicion is that if you expect to get an entire packet, the URB must
be the maximum packet size for that level of device, and 600 isn’t. My
memory is that whatever packet is received is returned in accordance with
the URB specification, but that the remaindervof the packet is not
retained for the next call. Every example I’ve seen uses the “native” max
packet size for the USB revision level, so I suspect that you odd transfer
size is the problem.

Also, all the examples I’ve seen send only one URB down, and in the
completion routine either complete the read IRP or send a request down for
the next fragment, rather than firing off a large number of URBs, but that
may simply reflect a history of how it was done in the original DDK
example.
joe

Hello All,

I am currently looking through USB documentation and examples and would
like to ask a question about size of read transfer.
Efficiency aside, I would like to understand the theory of things.
In WDM example, USB transfer is “staged” by multiple URBs, each is a
multiply of max_packet_size.
A thread in this regard here suggests splitting the transaction into
512bytes stages, with <32 simultaneous URBs.

Now here is my question - when I try to make a single URB transaction
request of 600bytes over bulk usb 2.0 HS endpoint, I get USBD_CRC_ERROR
from host controller, while 1024bytes single transfer is working just
fine.
Now i have been thinking - if the host controller breaks the request into
512b sized packets anyway, what would it return an error on attempt to
send 600bytes ?
Can this be HW related only ?

Generally, how does the host controller handle a single bulk read URB of
size >512b ?

Thanks
Sagi


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

Thanks guys.

Btw Joseph, you answered a wrong question, which would be “what is a max_packet_size” for USB.

Actually, USB spec doesn’t mention that max_transfer_size (as opposed to max_packet_size) should be a multiply of max_packet_size - that’s the reason I was confused.

Anyway, problem solved.
Thanks again.

xxxxx@walla.co.il wrote:

Actually, USB spec doesn’t mention that max_transfer_size (as opposed to max_packet_size) should be a multiply of max_packet_size - that’s the reason I was confused.

The concept of a “transfer”, and hence a “maximum transfer size”, is a
policy of the operating system. It has no meaning to the hardware. It
just works with packets.


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

Joseph M. Newcomer wrote:

Also, all the examples I’ve seen send only one URB
down, and in the completion routine either complete
the read IRP or send a request down for the next
fragment, rather than firing off a large number of URBs,
but that may simply reflect a history of how it was done
in the original DDK example.

This approach can greatly limit performance; the continuous reader that is built into KMDF has multiple URBs sitting at the host controller.

Thanks for the info.
What I don’t understand is why does the transfer size have to a multiple of max_packet_size.
I mean that the host controller brakes the transfer into packets anyway. Last packet might be less then max_packet_size, but since you have set SHORT_PACKET_OK, I don’t see why it has to be a problem. And yet I keep getting USBD_CRC_ERROR

As Tim mentioned, there is no reference to this issue in USB spec since it is only relevant to how the host controller driver handles the transaction.

I do understand that this issue is irrelevant when using KMDF contonious reader or braking down the transaction in user driver.

Still, I would like to understand why.
Any suggestions ?

Thanks
Sagi

xxxxx@walla.co.il wrote:

What I don’t understand is why does the transfer size have to a multiple of max_packet_size.
I mean that the host controller brakes the transfer into packets anyway. Last packet might be less then max_packet_size, but since you have set SHORT_PACKET_OK, I don’t see why it has to be a problem.

It’s because the device is never told how much data to send. The device
is merely sent a signal saying “OK, go!” Thus, the device is allowed to
send anything, up to its full packet size.

If you give the HCD a packet of 32 bytes, the HCD will schedule enough
room for 32 bytes. If your device actually sends 512 bytes (which it is
allowed to do), then you have screwed up the scheduling. You’re
stepping on some other device’s time slot, and that’s a protocol
violation called “babble”.

SHORT_PACKET_OK just means that the device is allowed to send less than
what you requested without it being considered an error. It does not
mean “I’m not giving you room enough for a full packet”.

And yet I keep getting USBD_CRC_ERROR

Do you mean USBD_STATUS_CRC? Is that the error from the URB, or is it
from the IRP? In the IRP, that code (C0000001) would be
STATUS_UNSUCCESSFUL.


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

Hello Tim,

Thank you again for your detailed answer.

I do get USBD_STATUS_CRC upon URB completion.

Also, think I had it all wrong.
I am now guessing that this is not an issue of max_packet_size product but rather of how the device communicates. I will split the transaction in two stages :

  1. transaction_size div max_packet_size
  2. transaction_size mod max_packet_size

If second transactions terminates with error, It will mean that it has nothing to do with tranasaction_size, but rather with the device always sending max_packet_size.

I will update tomorrow.
Thank you very much again.

Sagi

xxxxx@walla.co.il wrote:

I do get USBD_STATUS_CRC upon URB completion.

That doesn’t answer my question. Are you getting that status in the URB
header Status field, or in the IRP’s IoStatus.Status field? Even though
they have the same name, those two fields have different meanings. In
UrbHeader.Status, C0000001 is USBD_STATUS_CRC. But in IoStatus.Status,
C0000001 is STATUS_UNSUCCESSFUL.


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

Hello Tim,

You were right again, the actual status from urb->UrbHeader.Status was USBD_STATUS_BABBLE_DETECTED.

It looks exactly as you have suggested.
I am checking with USB Analyzer and will update.

Thank you again,
Sagi