Dne 13. 07. 21 v 15:16 Pavel Hofman napsal(a):
Dne 13. 07. 21 v 14:05 Jerome Brunet napsal(a):
On Tue 13 Jul 2021 at 12:22, Pavel Hofman <pavel.hofman@xxxxxxxxxxx>
wrote:
Hi,
I am testing the three Ruslan's async feedback patches as modified by
Jerome and I hit a regression in windows 10 enumeration.
Ruslan posted an already accepted patch
https://github.com/torvalds/linux/commit/789ea77310f0200c84002884ffd628e2baf3ad8a#diff-876615ece7fb56ce8d45fc70623bef9caa2548e810426f217fb785ffa10b33d5
which allowed win10 enumeration.
Ruslan's async feedback patchset kept the change:
https://patchwork.kernel.org/project/linux-usb/patch/1614603943-11668-5-git-send-email-ruslan.bilovol@xxxxxxxxx/
diff --git a/drivers/usb/gadget/function/f_uac2.c
b/drivers/usb/gadget/function/f_uac2.c
index 72b42f8..91b22fb 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -506,6 +506,10 @@ static int set_ep_max_packet_size(const struct
f_uac2_opts *uac2_opts,
max_size_bw = num_channels(chmask) * ssize *
((srate / (factor / (1 << (ep_desc->bInterval - 1)))) + 1);
+
+ if (!is_playback && (uac2_opts->c_sync == USB_ENDPOINT_SYNC_ASYNC))
+ max_size_bw = max_size_bw * FBACK_FREQ_MAX / 100;
+
ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_size_bw,
max_size_ep));
Jerome's rebase patch which was accepted recently changed the
functionality
to the original code:
https://patchwork.kernel.org/project/linux-usb/patch/20210603220104.1216001-4-jbrunet@xxxxxxxxxxxx/
diff --git a/drivers/usb/gadget/function/f_uac2.c
b/drivers/usb/gadget/function/f_uac2.c
index 321e6c05ba93..ae29ff2b2b68 100644
--- a/drivers/usb/gadget/function/f_uac2.c
+++ b/drivers/usb/gadget/function/f_uac2.c
@@ -584,8 +584,11 @@ static int set_ep_max_packet_size(const struct
f_uac2_opts *uac2_opts,
ssize = uac2_opts->c_ssize;
}
+ if (!is_playback && (uac2_opts->c_sync == USB_ENDPOINT_SYNC_ASYNC))
+ srate = srate * (1000 + uac2_opts->fb_max) / 1000;
+
max_size_bw = num_channels(chmask) * ssize *
- ((srate / (factor / (1 << (ep_desc->bInterval - 1)))) + 1);
+ DIV_ROUND_UP(srate, factor / (1 << (ep_desc->bInterval - 1)));
ep_desc->wMaxPacketSize = cpu_to_le16(min_t(u16, max_size_bw,
max_size_ep));
With this version my Win10 does not enumerate the USB AUDIO device,
even if
it has only EP-IN capability (i.e. is_playback = true). For my setup the
EP-IN wMaxPacketSize is 192bytes vs. 196bytes in Ruslan's version,
causing
win10 reporting "The specified range could not be found in the range
list."
Maybe I am lacking USB expertize, but is there any reason why a 192bytes
maximum packet size should be considered invalid ? Just from your
comment, I can't figure it out.
It would help if you could detail the parameters you started your gadget
with (rate, format, channel number)
IIRC, Ruslan initial patchset reserved a fixed additional bandwidth
(around 20% I think) to deal with the explicit feedback.
The idea is that, 99.9% of the time, all you need is the ability to fit
one more sample in each packet. This is should be what the default
setting provides (up to 192kHz). If it does not do that, I made mistake.
The setting configurable because I was trying to avoid wasting USB
bandwith but still support poor quality platforms where 1 extra sample
is not enough (I think Ruslan mentioned having seen such system)
I am absolutely no USB expert. What I did was testing Jerome's patchset
and win10 refused to enumerate, even with the most trivial configuration
c_srate=p_srate=48000, 16bits, capture 2ch, playback 0ch which
configures no EP-OUT and no feedback EP-IN. To find the cause I went
back one patch (HEAD^) and win10 happily enumerated this no-EP-OUT
configuration. So I compared the usb config dump - see attached files
from Theosycon USB Descriptor Dumper - see the two attached files, named
after commit IDs.
The dumps differ in only one parameter EP-IN 1 wMaxPacketSize, for both
HS and the dumped "Other Speed Configuration Descriptor" i.e. FS:
diff 650f7f40dc1691a8ab4d1dc411f8f327b36e8d14.txt
cb1c270600b2c6f55f55f227775aaddf2cc78bed.txt
185c185
< 0x00C4 wMaxPacketSize (1 x 196 bytes)
---
> 0x00C0 wMaxPacketSize (1 x 192 bytes)
339c339
< 0x00C4 wMaxPacketSize (1 x 196 bytes)
---
> 0x00C0 wMaxPacketSize (1 x 192 bytes)
So I looked at the patch and saw the changed wMaxPacketSize calculation.
Adding +1 yielded what the original Ruslan's code yielded - one more
sample (i.e. 196 bytes instead of 192bytes). Therefore I put it in the
patch here. This value is accepted by win10.
I do not know how windows uac2 driver verifies validity of
wMaxPacketSize but clearly 196bytes (+1 sample) is accepted while
192bytes is refused. Linux does not care, just like Ruslan described in
his commit 789ea77310f020.
I checked duplex with EP-OUT enabled (i.e. with the feedback EP-IN), the
"new" calculation works OK in win10 (while the Jerome's values were
refused).
I really do not know the correct code for calculating the wMaxPacketSize
to satisfy the windows driver, but what I am posting works. I'll be
happy if someone knowledgeable fixes my layman quickfix.
The original Ruslan's patch (in the mainline branch
https://github.com/torvalds/linux/commit/789ea77310f0200c84002884ffd628e2baf3ad8a
) explains the reasoning.