On Tue, 6 Oct 2015, Panu Matilainen wrote:
Having dived into this, and looking carefully at the data produced by the Windows driver, it appears that what's happening is that the driver stuffs a 32-bit length specifier at the start of each isochronous data packet.
So, for instance, instead of transferring the sample data
00 12 bf 34 00 98 87 76 00 3c 24 35 00 86 75 64 .. .. (40 bytes)
the Zoom driver would send:
28 00 00 00 00 12 bf 34 00 98 87 76 00 3c 24 35 00 86 75 64 ... (44 bytes)
At the moment I'm considering adding some additional code to sound/usb/pcm.c: prepare_playback_urb(), governed by a new boolean in struct snd_usb_substream in a similar vain as txfr_quirk in that structure (which in turn is set in some quirk function detecting the R16).
What needs to be done is to add 4 bytes to the length, and adjust the offset accordingly, in urb->iso_frame_desc[i], and then add the additional length descriptor for each packet when copying out the data further down in the same function.
It would be nice to add a foo_quirk() function but since the actual copying of the data needs to be changed, it's not really possible to do efficiently with a separate routine.
Sounds like a plan to me, but keep in mind I'm just another newbie in all this. Anyway, I wouldn't worry about cleanest possible way at this point, just do a quick-n-dirty hack to see if adding the length is enough to get it working and worry about the rest later. I'll try to have a look at it too as soon as time permits, but meanwhile if more experienced people have better suggestions...
I tried this out yesterday, with good results. I only had time for limited testing, but I managed to playback a couple of 44.1 kHz files (didn't test anything else) without any hitches. So this is definitely the right way to go. Actually it was a real joy after the R16 has been silent for a week. :-)
Apart from prepare_playback_urb(), I had to make a similar change to endpoint.c:prepare_outound_urb() which outputs silence before there is data to send.
Patch to follow, but there are a couple of things I need to straighten out first:
- Since we're stuffing more data in the outgoing packets, some allowance must be made for this when allocating the urb->transfer_buffer. I've got to review that code so that we don't spill over the end of the allocated buffer in some case. - The best way to trigger the quirk. I'm thinking something along the lines of introducing a QUIRK_AUDIO_ZOOM_INTERFACE which enables the aforementioned bit in order to enable the quirk in prepare_playback_urb() and prepare_output_urb(), and then calls create_standard_audio_quirk() (just as QUIRK_AUDIO_STANDARD_INTERFACE would have resulted in). Then it's clear in quirks-table.h that something special is going on. (Currently I've added the quirk initialization directly in create_standard_audio_quirk(), but it seems wrong to hide it away in there).
And I also need to test some more.
Also, in the dump from the Windows driver I saw some form of sample rate control message being sent that Linux doesn't send, on the other hand, that was sent as part of starting capture, which already has been proven to work, so it might simply not be needed.
/Ricard