Re: [PATCH 0/3] UAC2 Gadget: feedback endpoint support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sun, Nov 22, 2020 at 2:52 PM Ruslan Bilovol <ruslan.bilovol@xxxxxxxxx> wrote:
>
> On Fri, Nov 13, 2020 at 5:35 PM Glenn Schmottlach
> <gschmottlach@xxxxxxxxx> wrote:
> >
> > On Thu, Nov 12, 2020 at 6:20 PM Ruslan Bilovol <ruslan.bilovol@xxxxxxxxx> wrote:
> > >
> > > On Wed, Nov 11, 2020 at 11:30 AM Peter Chen <peter.chen@xxxxxxx> wrote:
> > > >
> > > > On 20-11-08 02:18:28, Ruslan Bilovol wrote:
> > > > > Current UAC2 gadget implements capture/sync paths
> > > > > as two USB ISO ASYNC endpoints (IN and OUT).
> > > > >
> > > > > This violates USB spec which says that ISO ASYNC OUT endpoint
> > > > > should have feedback companion endpoint.
> > > > > See USB2.0 spec  "5.12.4.1 Synchronization Type": asynchronous
> > > > > sink provides explicit feedback (isochronous pipe).
> > > > > Interesting that for ISO ASYNC *IN* endpoint respective
> > > > > feedback isn't required since source provides implicit
> > > > > feedforward (data stream).
> > > > >
> > > > > While it's not an issue if UAC2 Gadget is connected to
> > > > > Linux host (Linux ignores missing feedback endpoint),
> > > > > with other hosts like Windows or MacOS the UAC2 Gadget
> > > > > isn't enumerated due to missing feedback endpoint.
> > > > >
> > > > > This patch series adds feedback endpoint support to
> > > > > UAC2 function, new control to UAC2 mixer which can
> > > > > be used by userspace tools (like alsaloop from alsa-utils)
> > > > > for updating feedback frequency reported to the host.
> > > > > This is useful for usecases when UAC2 Gadget's audio
> > > > > samples are played to another codec or audio card
> > > > > with its own internal freerunning clock so host can
> > > > > be notified that more/less samples are required.
> > > > >
> > > > > The alsaloop tool requires some (relatively small)
> > > > > modifications in order to start support driving
> > > > > feedback frequency through UAC2 mixer control.
> > > > > That change will be sent as a separate patch
> > > > > to ALSA community.
> > > > >
> > > > > Also added ability to switch ISO ASYNC OUT endpoint into
> > > > > adaptive endpoint which doesn't require feedback endpoint
> > > > > (as per USB spec).
> > > > >
> > > > > Ruslan Bilovol (3):
> > > > >   usb: gadget: f_uac2/u_audio: add feedback endpoint support
> > > > >   usb: gadget: f_uac2: add adaptive sync support for capture
> > > > >   usb: gadget: u_audio: add real feedback implementation
> > > >
> > > > Hi Ruslan,
> > > >
> > > > I applied your patches, but WIN10 still can't recognize it well.
> > > > The UAC1 is OK for WIN10 with the below same configuration.
> > > > Any debug information you would like to know to check it?
> > > >
> > > >
> > > > if [ "$FUNC" == "uac2" ]; then
> > > > mkdir functions/$FUNC".0"
> > > > echo 2 > functions/$FUNC".0"/p_ssize
> > > > echo 48000 > functions/$FUNC".0"/p_srate
> > > > echo 3 > functions/$FUNC".0"/p_chmask
> > > >
> > > > echo 2 > functions/$FUNC".0"/c_ssize
> > > > echo 48000 > functions/$FUNC".0"/c_srate
> > > > echo 3 > functions/$FUNC".0"/c_chmask
> > > > #echo 4 > functions/$FUNC".0"/req_number
> > > > ln -s functions/$FUNC".0" configs/c.1
> > > > echo high-speed > /sys/kernel/config/usb_gadget/g1/max_speed
> > > > fi
> > > >
> > >
> > > Hmm... I just tested below config and it works fine with my Win10.
> > > The only thing I noticed is Windows doesn't enable UAC2 gadget
> > > by default, but this can be done from Win10 sound settings
> > >
> > > --------------------------------->8--------------------------------------
> > > 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
> > >
> > > # 44.1 kHz sample rate
> > > echo 44100 > functions/uac2.0/c_srate
> > > echo 44100 > functions/uac2.0/p_srate
> > >
> > > 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 > UDC
> > > --------------------------------->8--------------------------------------
> > >
> > > Thanks,
> > > Ruslan
> >
> > Hi Ruslan -
> >
> > With your configuration (above) Win10 was able to recognize and load
> > the driver. What appears to prevent my configuration from loading is
> > the fact that I selected 48K as my sample rate and my capture/playback
> > channel mask includes more than two (2) channels. If I take your
> > configuration and change the sample rate (c_srate/p_srate) to 48000
> > Windows will fail to load the driver. Likewise, setting the
> > c_chmask/p_chmask to 7 (three channels) will also cause the driver to
> > fail to load.
> >
> > You mentioned there is an option in Win10 Sound Settings to "enable"
> > UAC2 by default. I cannot find that option and I wonder if this is
> > what is preventing me from changing the sample rate or channel mask?
> > Could Windows be treating my audio gadget as a UAC1 device rather than
> > a fully multi-channel audio device (even though the usbaudio2.sys
> > driver is loaded)? Have you tried other configurations to verify your
> > Win10 box supports more than two channels and a 44.1K sample rate? I
> > look forward to your feedback and any suggestions you might offer.
> >
>
> I was able to reproduce the issue and prepared a patch below, please
> try it and see if it fixes the issue.
>
> Maximum data rates that I used were (AFAIR) 8 channel 192kHz/32bit,
> but there is another issue with high data rate if someone uses so many
> channels, very high sampling frequency or sample size that data can't
> fit into allowed (by USB spec) max packet size of endpoint. In this case
> need to decrease bInterval of endpoint.
> I test it in a high-performance audio case so always use a minimal possible
> bInterval (set to '1').
> Of course in the future that need to be calculated dynamically depending on
> the UAC2 settings
>
> Please test patches below and see it it helps
>
> ---------------------------------------------8<----------------------------------------
> From 51516435bbf2486574ec7bc9fd4726677cd474a4 Mon Sep 17 00:00:00 2001
> From: Ruslan Bilovol <ruslan.bilovol@xxxxxxxxx>
> Date: Sun, 22 Nov 2020 21:05:38 +0200
> Subject: [PATCH] usb: gadget: f_uac2: always increase endpoint max_packet_size
>  by one audio slot
>
> As per UAC2 Audio Data Formats spec (2.3.1.1 USB Packets),
> if the sampling rate is a constant, the allowable variation
> of number of audio slots per virtual frame is +/- 1 audio slot.
>
> It means that endpoint should be able to accept/send +1 audio
> slot.
>
> Previous endpoint max_packet_size calculation code
> was adding sometimes +1 audio slot due to DIV_ROUND_UP
> behaviour which was rounding up to closest integer.
> However this doesn't work if the numbers are divisible.
>
> It had no any impact with Linux hosts which ignore
> this issue, but in case of more strict Windows it
> caused rejected enumeration
>
> Thus always add +1 audio slot to endpoint's max packet size
>
> Signed-off-by: Ruslan Bilovol <ruslan.bilovol@xxxxxxxxx>
> ---
>  drivers/usb/gadget/function/f_uac2.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/usb/gadget/function/f_uac2.c
> b/drivers/usb/gadget/function/f_uac2.c
> index ebdb2a1..1698587 100644
> --- a/drivers/usb/gadget/function/f_uac2.c
> +++ b/drivers/usb/gadget/function/f_uac2.c
> @@ -486,7 +486,7 @@ static void set_ep_max_packet_size(const struct
> f_uac2_opts *uac2_opts,
>   }
>
>   max_packet_size = num_channels(chmask) * ssize *
> - DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1)));
> + ((srate / (factor / (1 << (ep_desc->bInterval - 1)))) + 1);
>
>   if (!is_playback && (uac2_opts->c_sync == USB_ENDPOINT_SYNC_ASYNC))
>   max_packet_size = max_packet_size * FBACK_FREQ_MAX / 100;
> --
> 1.9.1
>
>
> ---------------------------------------------8<----------------------------------------
> From c8f2f2b414af672ec40841e75fb1ea761ae29122 Mon Sep 17 00:00:00 2001
> From: Ruslan Bilovol <ruslan.bilovol@xxxxxxxxx>
> Date: Sun, 16 Feb 2020 22:40:23 +0200
> Subject: [PATCH] usb: gadget: f_uac2: change bInterval to 1 for
>  8ch/24bit/44.1kHz
>
> With bInterval=4 one audio slot in case of 8ch/24bit/44.1kHz
> exeeds MaxPacket size of ISO endpoint (>1024) and can't be
> transferred in time.
> USB spec ("5.6.3 Isochronous Transfer Packet Size Constraints")
> says if we need to transfer more than 1024 it is a high speed, high
> bandwidth endpoint and should have bInterval=1.
>
> In the future, bInterval should be dynamically calculated
> depending on bandwith requirementes
>
> Signed-off-by: Ruslan Bilovol <ruslan.bilovol@xxxxxxxxx>
> ---
>  drivers/usb/gadget/function/f_uac2.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/usb/gadget/function/f_uac2.c
> b/drivers/usb/gadget/function/f_uac2.c
> index 3633df6..fb9b875 100644
> --- a/drivers/usb/gadget/function/f_uac2.c
> +++ b/drivers/usb/gadget/function/f_uac2.c
> @@ -281,7 +281,7 @@ enum {
>
>   .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
>   .wMaxPacketSize = cpu_to_le16(1024),
> - .bInterval = 4,
> + .bInterval = 1,
>  };
>
>  /* CS AS ISO OUT Endpoint */
> @@ -358,7 +358,7 @@ enum {
>
>   .bmAttributes = USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC,
>   .wMaxPacketSize = cpu_to_le16(1024),
> - .bInterval = 4,
> + .bInterval = 1,
>  };
>
>  /* CS AS ISO IN Endpoint */
> --
> 1.9.1
>
>
> ---------------------------------------------8<----------------------------------------
>
> Thanks,
> Ruslan

Hi Ruslan -

I have had some mixed success with your additional patches. First, the
UAC2 gadget does correctly register with Windows 10 but only for 1-31
channels. For a fully specified channel map (32 channels):

c_chmask = 0xFFFFFFFF    ( Does not load)
p_chmask = 0xFFFFFFFF   ( Does not load)

the driver fails to load (code=10). This seems similar to the prior
problem. Could there be another off-by-one problem here?

With a 31 channel mask the Windows 10 usbaudio2.sys loads successfully, e.g.

c_chmask = 0x7FFFFFFF (loads)
p_chmask = 0x7FFFFFFF (loads)

Once Windows 10 loads the driver successfully, however, I can't seem
to select the device through Audacity on Windows. The device appears
in the Windows "Device Manager" under "Sound, video and game
controllers -> Source/Sink". How are you testing audio
playback/capture under Windows? Perhaps my test approach is wrong?

I used the same approach on my Linux host where the USB UAC2 device
appears as an ALSA device and I use speaker-test on the target
(BeagleBone Black) to play and then capture the audio using Audacity
on the Linux host. I was hoping to do the same or something similar
under Windows.

Below is the script I've been using on the target to configure my UAC2 device:

mkdir -p "/sys/kernel/config/usb_gadget/g_multi"
echo "${idVendor:-0x11F5}" > "/sys/kernel/config/usb_gadget/g_multi/idVendor"
echo "${idProduct:-0x0009}" > "/sys/kernel/config/usb_gadget/g_multi/idProduct"
echo "${bcdDevice:-0x0001}" > "/sys/kernel/config/usb_gadget/g_multi/bcdDevice"
echo "${bDeviceClass:-0x00}" >
"/sys/kernel/config/usb_gadget/g_multi/bDeviceClass"
echo "${bDeviceSubClass:-0x00}" >
"/sys/kernel/config/usb_gadget/g_multi/bDeviceSubClass"
echo "${bDeviceProtocol:-0x00}" >
"/sys/kernel/config/usb_gadget/g_multi/bDeviceProtocol"
echo "${bcdUSB:-0x0200}" > "/sys/kernel/config/usb_gadget/g_multi/bcdUSB"
echo "${bMaxPacketSize0:-0x00}" >
"/sys/kernel/config/usb_gadget/g_multi/bMaxPacketSize0"
mkdir -p "/sys/kernel/config/usb_gadget/g_multi/strings/0x409"
echo "${serialnumber:-000000000000}" >
"/sys/kernel/config/usb_gadget/g_multi/strings/0x409/serialnumber"
echo "${product:-UAC2}" >
"/sys/kernel/config/usb_gadget/g_multi/strings/0x409/product"
echo "${manufacturer:-www.acme.com}" >
"/sys/kernel/config/usb_gadget/g_multi/strings/0x409/manufacturer"
mkdir -p "/sys/kernel/config/usb_gadget/g_multi/functions/uac2.usb0"
echo "${req_number:-4}" >
"/sys/kernel/config/usb_gadget/g_multi/functions/uac2.usb0/req_number"
echo "${c_ssize:-4}" >
"/sys/kernel/config/usb_gadget/g_multi/functions/uac2.usb0/c_ssize"
echo "${c_srate:-48000}" >
"/sys/kernel/config/usb_gadget/g_multi/functions/uac2.usb0/c_srate"
echo "${c_chmask:-0x00000003}" >
"/sys/kernel/config/usb_gadget/g_multi/functions/uac2.usb0/c_chmask"
echo "${c_sync:-asynchronous}" >
"/sys/kernel/config/usb_gadget/g_multi/functions/uac2.usb0/c_sync"
echo "${p_ssize:-4}" >
"/sys/kernel/config/usb_gadget/g_multi/functions/uac2.usb0/p_ssize"
echo "${p_srate:-48000}" >
"/sys/kernel/config/usb_gadget/g_multi/functions/uac2.usb0/p_srate"
echo "${p_chmask:-0x00000003}" >
"/sys/kernel/config/usb_gadget/g_multi/functions/uac2.usb0/p_chmask"
mkdir -p "/sys/kernel/config/usb_gadget/g_multi/configs/c.1"
echo "${bmAttributes:-0x80}" >
"/sys/kernel/config/usb_gadget/g_multi/configs/c.1/bmAttributes"
echo "${MaxPower:-500}" >
"/sys/kernel/config/usb_gadget/g_multi/configs/c.1/MaxPower"
mkdir -p "/sys/kernel/config/usb_gadget/g_multi/configs/c.1/strings/0x409"
echo "${configuration:-BeagleBone Composite}" >
"/sys/kernel/config/usb_gadget/g_multi/configs/c.1/strings/0x409/configuration"
ln -s "/sys/kernel/config/usb_gadget/g_multi/functions/uac2.usb0"
"/sys/kernel/config/usb_gadget/g_multi/configs/c.1/uac2.usb0"
mkdir -p "/sys/kernel/config/usb_gadget/g_multi/os_desc"
ln -s "//sys/kernel/config/usb_gadget/g_multi/configs/c.1"
"/sys/kernel/config/usb_gadget/g_multi/os_desc/c.1"
echo "${qw_sign:-MSFT100}" >
"/sys/kernel/config/usb_gadget/g_multi/os_desc/qw_sign"
echo "${b_vendor_code:-0x00}" >
"/sys/kernel/config/usb_gadget/g_multi/os_desc/b_vendor_code"
echo "${use:-1}" > "/sys/kernel/config/usb_gadget/g_multi/os_desc/use"

basename /sys/class/udc/* > /sys/kernel/config/usb_gadget/g_multi/UDC

This is only a two channel playback/capture configuration. I hoped to
get this working under Windows before increasing my channel count to a
full 32 channel mask with a 48K sample rate.

I look forward to hearing your suggestions and possibly pointing out
where I've gone astray.

Thanks,

Glenn



[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux