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
