I am writing an USB Audio Playback
driver using ALSA APIs
. For that I was trying to understand existing audio drivers in Linux
kernel. But I get confused on when to update the kernel audio buffer pointer. We know kernel puts new audio data in a ring buffer and our drivers task is to take new data from the ring buffer, pass it over USB and update the kernel buffer pointer.
The drivers I was looking at takes care of this in URB
completion function. Say they have a predefined macro for USB transfer size, which is around 4096
bytes in almost all cases. So when the URB
transfer is finished and the code execution path comes in URB
completion, they copy another 4096
bytes from the kernel buffer into the URB
buffer, submit the URB
again to the USB
controller and forward the kernel buffer pointer by 4096
bytes.
But what I don't understand is, how come they be so sure that by the time a URB
trasfer is finished, there are 4096
bytes of new data in the kernel buffer? The new data amount in the kernel buffer might be smaller than 4096
bytes? Then why does it always update the buffer pointer by 4096
bytes. I think there should be some of knowing how many new bytes are in the kernel buffer and the driver should only update by that amount or may be I misunderstood something? Any suggestion or guideline is appreciable.
These USB audio drivers behave exactly like a PCI sound card, i.e., when the device needs some samples, those samples are just read from the ring buffer.
A PCI chip has no way of knowing what part of the buffer actually contains valid samples. A buffer underrun is detected later by software (the device informs the driver about the current position with an interrupt; the interrupt handler then raises the underrun error if the position is too far ahead).
USB audio drivers use exactly the same mechanism for detecting underruns, i.e., the
snd_pcm_period_elapsed()
function checks whether the current position (as returned by your.pointer
callback) is too far ahead.