[alsa-devel] Attempting to understand odd snd-usb-audio code and behavior

Keith A. Milner maillist at superlative.org
Tue Aug 22 22:25:40 CEST 2017


Over the last few weeks I've been trying to dig through the snd-usb-audio code 
to try to get an understanding of it. I've used ftrace and also a local 
version which I have heavily polluted with kprintf(KERN_INFO statements so I 
can track what it's doing in practice.

I've been playing with this with some USB audio interfaces I have some which 
work, and some which don't, and trying to understand the differences and, 
ultimately, what I can do to make the non-functioning ones work.

I've got to the point where I have a fairly good understanding of some parts, 
but I'm struggling to understand why the code is behaving as it does in 
practice.

My observation when plugging the USB device in is that, as expected, it tries 
to build the audio device, and add components to it including attaching 
capture and playback streams. It seems to go through this phase without too 
many surprises, and we get to the standard dmesg output:

usbcore: registered new interface driver snd-usb-audio

After this, it gets confusing.

It seems to open and close the PCMs (e.g, snd_usb_capture_open) several times 
in a row. Each time it sets up the hardware info, checks and sets the format 
and then closes the PCM. I don't see anything obviously different between most 
of these cycles. Here's an example my logging output (hopefully this will make 
sense):

Aug 22 20:04:16 kerneldev kernel: [  923.140789] Called: pcm.c - 
snd_usb_capture_open for pcm substream 0
Aug 22 20:04:16 kerneldev kernel: [  923.140789] Called: pcm.c - 
snd_usb_pcm_open for pcm substream 0
Aug 22 20:04:16 kerneldev kernel: [  923.140789] Setting up hw info
Aug 22 20:04:16 kerneldev kernel: [  923.140789] Checking format:
Aug 22 20:04:16 kerneldev kernel: [  923.140790]  Interface number = 2
Aug 22 20:04:16 kerneldev kernel: [  923.140790]  alt setting = 1
Aug 22 20:04:16 kerneldev kernel: [  923.140790]  alt setting index = 1
Aug 22 20:04:16 kerneldev kernel: [  923.140790]  format type = 1
Aug 22 20:04:16 kerneldev kernel: [  923.140790]  frame size = 0
Aug 22 20:04:16 kerneldev kernel: [  923.140791] Setting pt=125 ptmin=125
Aug 22 20:04:16 kerneldev kernel: [  923.140792] Checking for unusual bit 
rates
Aug 22 20:04:16 kerneldev kernel: [  923.140794] Called: init.c - 
snd_card_file_remove
Aug 22 20:04:16 kerneldev kernel: [  923.140921] Called: pcm.c - 
snd_usb_hw_params for pcm substream 0
Aug 22 20:04:16 kerneldev kernel: [  923.140945] Setting format:
Aug 22 20:04:16 kerneldev kernel: [  923.140945]  Bytes per period = 8816
Aug 22 20:04:16 kerneldev kernel: [  923.140945]  Frames per period = 1102
Aug 22 20:04:16 kerneldev kernel: [  923.140946]  Periods per buffer = 4
Aug 22 20:04:16 kerneldev kernel: [  923.140946]  Channels = 2
Aug 22 20:04:16 kerneldev kernel: [  923.140946]  Rate = 44100
Aug 22 20:04:16 kerneldev kernel: [  923.141279] Called: endpoint.c - 
snd_usb_add_endpoint of type 0 with direction 1
Aug 22 20:04:16 kerneldev kernel: [  923.141292] Called: pcm.c - 
snd_usb_pcm_prepare for pcm substream 0
Aug 22 20:04:16 kerneldev kernel: [  923.141293] Called: pcm.c - 
configure_endpoint
Aug 22 20:04:16 kerneldev kernel: [  923.141294] Called: endpoint.c - 
snd_usb_endpoint_set_params for endpoint 142, type 0
Aug 22 20:04:16 kerneldev kernel: [  923.141294] Setting endpoint params for 
endpoint num 142
Aug 22 20:04:16 kerneldev kernel: [  923.141294]  channels=2
Aug 22 20:04:16 kerneldev kernel: [  923.141294]  period bytes=8816
Aug 22 20:04:16 kerneldev kernel: [  923.141295]  frames per period=1102
Aug 22 20:04:16 kerneldev kernel: [  923.141295]  periods per buffer=4
Aug 22 20:04:16 kerneldev kernel: [  923.141296] Called: endpoint.c - 
data_ep_set_params for endpoint 142, type 0
Aug 22 20:04:16 kerneldev kernel: [  923.141301] Called: pcm.c - 
snd_usb_pcm_prepare for pcm substream 0
Aug 22 20:04:16 kerneldev kernel: [  923.142768] Called: init.c - 
snd_card_file_add
Aug 22 20:04:16 kerneldev kernel: [  923.142772] Called: init.c - 
snd_card_file_remove
Aug 22 20:04:16 kerneldev kernel: [  923.142774] Called: init.c - 
snd_card_file_add
Aug 22 20:04:16 kerneldev kernel: [  923.142830] Called: init.c - 
snd_card_file_remove
Aug 22 20:04:16 kerneldev kernel: [  923.142836] Called: pcm.c - 
snd_usb_hw_free for pcm substream 0
Aug 22 20:04:16 kerneldev kernel: [  923.142837] Called: endpoint.c - 
snd_usb_endpoint_deactivate for endpoint 142, type 0
Aug 22 20:04:16 kerneldev kernel: [  923.142846] Called: pcm.c - 
snd_usb_capture_close for pcm substream 0
Aug 22 20:04:16 kerneldev kernel: [  923.146760] Called: init.c - 
snd_card_file_remove
Aug 22 20:04:16 kerneldev kernel: [  923.146834] Called: init.c - 
snd_card_file_add
Aug 22 20:04:16 kerneldev kernel: [  923.146838] Called: init.c - 
snd_card_file_remove
Aug 22 20:04:16 kerneldev kernel: [  923.146841] Called: init.c - 
snd_card_file_add
Aug 22 20:04:16 kerneldev kernel: [  923.146845] Called: init.c - 
snd_card_file_add
Aug 22 20:04:16 kerneldev kernel: [  923.146848] Called: pcm.c - 
snd_usb_capture_open for pcm substream 0
Aug 22 20:04:16 kerneldev kernel: [  923.146849] Called: pcm.c - 
snd_usb_pcm_open for pcm substream 0
Aug 22 20:04:16 kerneldev kernel: [  923.146849] Setting up hw info

It seems to do this several times, before the behavior changing slightly, as 
it now starts to try to set the endpoint parameters and seems to leave the 
stream open. However, it then tries to open the stream and set the endpoint 
parameters again resulting in errors:

Aug 22 20:22:00 kerneldev kernel: [ 1987.452945] Called: endpoint.c - 
snd_usb_endpoint_set_params for endpoint 142, type 0
Aug 22 20:22:00 kerneldev kernel: [ 1987.452945] Setting endpoint params for 
endpoint num 142
Aug 22 20:22:00 kerneldev kernel: [ 1987.452945]  channels=2
Aug 22 20:22:00 kerneldev kernel: [ 1987.452945]  period bytes=1768
Aug 22 20:22:00 kerneldev kernel: [ 1987.452946]  frames per period=221
Aug 22 20:22:00 kerneldev kernel: [ 1987.452946]  periods per buffer=593
Aug 22 20:22:00 kerneldev kernel: [ 1987.452947] usb 1-1: Unable to change 
format on ep #8e: already in use

Maybe this is driven by hotplug or something, but it seems to be performing a 
lot of pointless activities.

Eventually it seems to try to open the PCM playback or capture stream (with 
some devices it opens playback, with others capture) and then checks the 
pointer:

Aug 22 20:22:00 kerneldev kernel: [ 1987.470194] Called: pcm.c - 
snd_usb_substream_playback_trigger for pcm substream 0
Aug 22 20:22:00 kerneldev kernel: [ 1987.470198] Called: pcm.c - 
snd_usb_pcm_pointer for pcm substream 0
Aug 22 20:22:00 kerneldev kernel: [ 1987.470198]   Pointer is 0
Aug 22 20:22:00 kerneldev kernel: [ 1987.470656] Called: pcm.c - 
snd_usb_pcm_pointer for pcm substream 0
Aug 22 20:22:00 kerneldev kernel: [ 1987.470657]   Pointer is 0
Aug 22 20:22:00 kerneldev kernel: [ 1987.470660] Called: pcm.c - 
snd_usb_pcm_pointer for pcm substream 0
Aug 22 20:22:00 kerneldev kernel: [ 1987.470660]   Pointer is 0
Aug 22 20:22:05 kerneldev kernel: [ 1992.473567] Called: pcm.c - 
snd_usb_pcm_pointer for pcm substream 0
Aug 22 20:22:05 kerneldev kernel: [ 1992.473569]   Pointer is 0


The above is from a non-working device. For a working device the pointer 
increments. Eventually this activity ends:

Aug 22 20:22:05 kerneldev kernel: [ 1992.473575] Called: pcm.c - 
snd_usb_substream_playback_trigger for pcm substream 0
Aug 22 20:22:05 kerneldev kernel: [ 1992.473576] Called: endpoint.c - 
snd_usb_endpoint_stop for endpoint 142, type 0
Aug 22 20:22:05 kerneldev kernel: [ 1992.473578] Called: endpoint.c - 
snd_usb_endpoint_stop for endpoint 13, type 0
Aug 22 20:22:05 kerneldev kernel: [ 1992.473602] Called: pcm.c - 
snd_usb_hw_free for pcm substream 0
Aug 22 20:22:05 kerneldev kernel: [ 1992.503287] Called: endpoint.c - 
snd_usb_endpoint_deactivate for endpoint 142, type 0
Aug 22 20:22:05 kerneldev kernel: [ 1992.503288] Called: endpoint.c - 
snd_usb_endpoint_deactivate for endpoint 13, type 0
Aug 22 20:22:05 kerneldev kernel: [ 1992.503323] Called: pcm.c - 
snd_usb_playback_close for pcm substream 0
Aug 22 20:22:05 kerneldev kernel: [ 1992.503656] Called: init.c - 
snd_card_file_remove

This seems as if it might be some sort of test of the PCMs, to make sure they 
are working. Certainly in non-working devices the pcm_pointer stays at zero 
and in working devices it increments.

It also seems to try harder with some devices than others, even though the 
device descriptors seem very similar.

Can anyone explain any of this to me, particularly why it's exhibiting this 
behaviour.

I've uploaded one of the logs from a non-working device to Pastebin if anyone 
wants to look at a full example: https://pastebin.com/uBZEuQ57

Also, is this the best way to approach this, or are there other 
tools/techniques that can help? I've experimented with ftrace and that was 
useful, but didn't give the level of detail I wanted.

Cheers,

Keith


More information about the Alsa-devel mailing list