Receiving STATUS_UNSUCCESSFUL on EvtIoRead completion routine

Our driver (USB) is working fine on a specific user-mode app (connecting, doing transfers, etc.). I found it a little strange that on a different user-mode application our driver returns STATUS_UNSUCCESSFUL (0xC0000001) on the completion routine of EvtIoRead. One difference is that the user-mode app that causes the error sends very small packets (4 bytes) for reading. I’ve been trying out different things like making the queue sequential (didn’t work).

The user-app does asynchronous processing (via GetOverlappedResult) and returns ERROR_GEN_FAILURE (0x1F) on GetLastError. Any suggestions on what might be causing the error?

A read buffer has to be at least one packet size: 64 bytes for 12 Mbps, 512 bytes for 480 Mbps.

Are you referring to the size of user-mode application buffer? Or is it the packet size that needs to be sent to the default IoTarget, which is the lower driver?

A read buffer has to be at least one packet size: 64 bytes for 12 Mbps, 512
bytes for 480 Mbps.

xxxxx@gmail.com wrote:

Are you referring to the size of user-mode application buffer? Or is it the packet size that needs to be sent to the default IoTarget, which is the lower driver?

Here’s the problem. A USB device is never told how much data to send.
All it gets is a signal that says “GO!”. The device is allowed to send
any amount of data, up to the maximum packet size in its endpoint
descriptor.

When you queue up a read URB, the host controller driver schedules time
on the bus for your request based on the size you specified. It assumes
you know what your device will do. If you send down a 12-byte buffer,
and the host controller makes room for that much, but your device
decides to send 512 bytes, you will step on the transactions that
follow. That is a protocol violation called “babble”. If it happens to
occur right at the microframe boundary, it can actually cause a hub to
shut itself down.

So, as a rule, any read URB that you send down below should be a
multiple of the maximum packet size. The numbers Grigora quoted were
for bulk endpoints. The other types are different.

Usually, a USB client driver will hide this little detail from its
user-mode clients. If your client asks for 12 bytes from a high-speed
bulk endpoint, you will probably want to send down a 512-byte read and
copy what you need.


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

Thank for your insight Tim. So that means that if the user-app requests for 4 bytes and the lower-driver returns say 120 bytes then we need to divide those 120 bytes into 4 bytes packets?

xxxxx@gmail.com wrote:

Thank for your insight Tim. So that means that if the user-app requests for 4 bytes and the lower-driver returns say 120 bytes then we need to divide those 120 bytes into 4 bytes packets?

That’s up to you to decide, based on what your hardware does and what
your applications expect. You can return the 4 bytes and save the other
116 for the next user request, or you can return the 4 bytes and throw
away the rest, or you can return STATUS_BUFFER_OVERFLOW. I’ve done all
3 in different situations.

You have to know your intended use cases to decide this.


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