When to Update ALSA Audio Driver Buffer Pointer

988 views Asked by At

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.

1

There are 1 answers

2
CL. On BEST ANSWER

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.