Re: [PATCH v2 0/3] USB Audio Gadget refactoring

From: Ruslan Bilovol
Date: Tue Aug 16 2016 - 16:40:50 EST


On Tue, Aug 16, 2016 at 12:16 PM, Peter Chen <hzpeterchen@xxxxxxxxx> wrote:
> On Sun, Aug 14, 2016 at 01:21:21AM +0300, Ruslan Bilovol wrote:
>> I came to this patch series when wanted to do two things:
>> - use UAC1 as virtual ALSA sound card on gadget side,
>> just like UAC2 is used so it's possible to do rate
>> resampling
>> - have both playback/capture support in UAC1
>>
>> Since I wanted to have same behavior for both UAC1/UAC2,
>> obviously I've got an utility part (u_audio.c) for
>> virtual ALSA sound card handling like we have
>> for ethernet(u_ether) or serial(u_serial) functions.
>> Function-specific parts (f_uac1/f_uac2) became almost
>> as storage for class-specific USB descriptors, some
>> boilerplate for configfs, binding and few USB
>> config request handling.
>>
>> Originally in RFC [1] I've posted before, there was
>> major change to f_uac1 after that it couldn't do
>> direct play to existing ALSA sound card anymore,
>> representing audio on gadget side as virtual
>> ALSA sound card where audio streams are simply
>> sinked to and sourced from it, so it may break
>> current usecase for some people (and that's why
>> it was RFC).
>>
>> During RFC discussion, it was agreed to not touch
>> existing f_uac1 implementation and create new one
>> instead. This patchset (v2) introduced new function
>> named f_uac1_newapi and doesn't touch current f_uac1
>> implementation, so people still can use old behavior
>>
>> Now, it's possible to use existing user-space
>> applications for audio routing between Audio Gadget
>> and real sound card. I personally use alsaloop tool
>> from alsautils and have ability to create PCM
>> loopback between two different ALSA cards using
>> rate resampling, which was not possible with previous
>> "direct play to ALSA card" approach in f_uac1.
>>
>> While here, also dropped redundant platform
>> driver/device creation in f_uac2 driver (as well as
>> didn't add "never implemented" volume/mute functionality
>> in f_uac1 to f_uac1_newapi) that made this work even
>> easier to do.
>>
>> This series is tested with both legacy g_audio.ko and
>> modern configfs approaches under Ubuntu 14.04 (UAC1 and
>> UAC2) and under Windows7 x64 (UAC1 only) having
>> perfect results in all cases.
>>
>
> I find UAC2 (UAC1 is ok) support is not well with the latest mainline
> kernel w/o your patch set. The windows7 can't install the driver
> successfully and the playback shows underrun (using local codec)
> using Linux host.

As Clemens already pointed, Windows 7 doesn't have
UAC2 support "out of the box". That's why I tested only UAC1 on it.

>
> Do you use the unchanged mainline kernel?

Yes, this patchset is based on v4.8-rc1 tag.

>
> My configfs parameters like below:
> echo 2 > functions/uac2.1/c_ssize
> echo 48000 > functions/uac2.1/c_srate
> echo 3 > functions/uac2.1/c_chmask
> echo 2 > functions/uac2.1/p_ssize
> echo 48000 > functions/uac2.1/p_srate
> echo 3 > functions/uac2.1/p_chmask

I usually don't change these (use default values here)

I use BeagleBone Black for this patchset verification.
Here is how I configure it through configfs:

uac_2
------------
mkdir cfg
mount none cfg -t configfs
mkdir cfg/usb_gadget/g1
cd cfg/usb_gadget/g1
mkdir configs/c.1
mkdir functions/uac2.0
mkdir strings/0x409
mkdir configs/c.1/strings/0x409
echo 0x0101 > idProduct
echo 0x1d6b > idVendor
echo my-serial-num > strings/0x409/serialnumber
echo my-manufacturer > strings/0x409/manufacturer
echo "Test gadget" > strings/0x409/product
echo "Conf 1" > configs/c.1/strings/0x409/configuration
echo 120 > configs/c.1/MaxPower
ln -s functions/uac2.0 configs/c.1
echo musb-hdrc.0.auto > UDC


uac_1 (new api)
-------------
mkdir cfg
mount none cfg -t configfs
mkdir cfg/usb_gadget/g1
cd cfg/usb_gadget/g1
mkdir configs/c.1
mkdir functions/uac1_newapi.0
mkdir strings/0x409
mkdir configs/c.1/strings/0x409
echo 0x0101 > idProduct
echo 0x1d6b > idVendor
echo my-serial-num > strings/0x409/serialnumber
echo my-manufacturer > strings/0x409/manufacturer
echo "Test gadget" > strings/0x409/product
echo "Conf 1" > configs/c.1/strings/0x409/configuration
echo 120 > configs/c.1/MaxPower
ln -s functions/uac1_newapi.0 configs/c.1
echo musb-hdrc.0.auto > UDC


>
>
> Console output:
> root@imx6qdlsolo:~# arecord -f dat -t wav -D hw:1,0 | aplay -D hw:0,0 &
> [1] 859
> root@imx6qdlsolo:~#
> root@imx6qdlsolo:~# Recording WAVE 'stdin' : Signed 16 bit Little
> Endian, Rate 48000 Hz, Stereo
> Playing WAVE 'stdin' : Signed 16 bit Little Endian, Rate 48000 Hz,
> Stereo
> underrun!!! (at least 36.634 ms long)
> underrun!!! (at least 36.117 ms long)
> underrun!!! (at least 42.132 ms long)
> underrun!!! (at least 40.157 ms long)
> underrun!!! (at least 36.207 ms long)
> underrun!!! (at least 39.173 ms long)
> underrun!!! (at least 36.119 ms long)
> underrun!!! (at least 36.164 ms long)
>
>

I use alsaloop tool that is more powerful than just arecord/aplay
through pipe. It is compiled with libsamplerate so can do
resampling on the fly. Also it has few clever algorithms for
processing overruns/underruns. There are many possible
configuration option combinations. For example, one of used
by me (but I use other combinations as well) was:
$ alsaloop -C hw:0,0 -P hw:1,0 -t 10000 -A 3 -S 1 -b -v

This is for routing audio from gadget to real ALSA card

Hope this may be helpful for you and for other people
who want to try this new u_audio API.

Best regards,
Ruslan