On Mon, 12 Sep 2005, Istvan De wrote:

> Hi,
> 
> How do you implement buffers for streaming USB data in a kernel driver?
> 
> For me, ring buffers would be an obvious choice,

They seem like the obvious solution for almost any case.

>  however, what if I
> allocate
> a 128byte buffer just for the sake of this example, and submit URBs with
> 64 byte transfer buffers.

I hope you're speaking only theoretically.  A 64-byte transfer buffer is
very inefficient for streaming.  Your transfer buffers should be much
bigger.  At full speed, a USB bus can transfer up to 19 64-byte bulk
packets per frame, which is over 1 KB.  Because of interrupt latency, you
might as well have a buffer capable of holding several milliseconds worth
of data.  That means your transfer buffers should be at least 4 KB (1
memory page on x86).

>  For the first bulk IN transfer, the 64 byte
> arrives
> OK, however, for the second, let's suppose that the URB returns with
> only
> 32 bytes instead of 64 (AFAIK the usb core is legitimate to do this..)

It is.  Note that in general with bulk transfers, arrival of a 
short packet (32 bytes instead of 64, for example) indicates the end of a 
data stream.

> Then at the next 64 byte transfer, the ring buffer would wrap around in
> the middle
> of the packet..

This wouldn't happen, since the data stream ended with the 32-byte packet.  
But suppose for the sake of argument that it didn't end.  You still
wouldn't wrap in the middle of a packet; what would happen is that the
next transfer buffer would be at the start of the ring buffer and the next
64 bytes of data would go there, as expected.  In other words, your ring
buffer would have a 32-byte "gap" between the end of the 32-byte packet
and the start of the following 64-byte packet.

If you think about it, it has to work this way.  Since you are streaming,
you always want to have an active URB -- otherwise you lose an opportunity
to transfer data.  You don't want to wait for one URB to finish before
submitting the next one.  So even though URB "B" only transfers 32 bytes,
you must submit URB "C" before "B" completes, before you know that it will
get a short packet.  Hence you must assume that "B" will transfer the full
64 bytes and leave that much space in the buffer.

> Or do you re-submit an URB w/ only 32 bytes if that is the ammount left
> at the
> end of the ring buffer?

If you do that, and the device ends up sending a 64-byte packet, you'll 
get an EOVERFLOW error.  So don't do it.

>  Or maybe you start over at the beginning of the
> ring buffer
> where there is enough space?
> (suppose the user already read and removed the first 64 byte packet from
> the buffer by that time)

If you're doing this right then URB "C" has already been submitted, with 
its transfer address at the start of the ring buffer, and it's too late to 
change that.

> I've also read that the kernel has a generic ring buffer implementation,
> is there
> an USB driver example using it?

Not as far as I know.

Alan Stern



-------------------------------------------------------
SF.Net email is Sponsored by the Better Software Conference & EXPO
September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices
Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA
Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to