audio: flow control never starts if the host asks for the sample rate before selecting alt 1 - #3820
Conversation
audiod_calc_tx_packet_sz() asserts packet_sz_tx_max <= audio->ep_in_sz, but it runs from the clock source SAM_FREQ CUR handlers. Hosts send that request before SET_INTERFACE alt=1, which is where ep_in_sz is assigned, so ep_in_sz is still 0, the assert fails, and packet_sz_tx[] stays zeroed. Nothing recomputes it once the endpoint is open. audiod_tx_packet_size() then sees nominal_size[1] == 0, skips EP IN flow control entirely and returns tu_min16(data_count, max_depth). Recompute once the endpoint size is known.
There was a problem hiding this comment.
Pull request overview
Adds an early audio TX packet-size recalculation after opening an IN endpoint.
Changes:
- Recomputes flow-control packet sizes once endpoint and format data are available.
- Guards recalculation on a known sample rate.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if (audio->sample_rate_tx) { | ||
| audiod_calc_tx_packet_sz(audio); |
|
Good catch from the review, this is a duplicate and the behavior I reported does
My counters sampled inside the Closing. Sorry for the noise, and thanks for the careful read. |
I jumped in with @FoamyGuy and @relic-se on the usb_audio module for
CircuitPython, adafruit/circuitpython#11102, and trying to get UAC2 microphone
support going on the ESP32-S2 and S3. That PR already works on RP2040, RP2350 and
nRF52840, so I went looking for what was different on ESP32 and found this along
the way. It is not ESP32 specific.
packet_sz_tx[]is never computed, so EP IN flow control silently never engages.audiod_calc_tx_packet_sz()assertspacket_sz_tx_max <= audio->ep_in_sz, but itruns from the clock source
SAM_FREQ CURhandlers,audio_device.c:1288and:1697. Hosts send that beforeSET_INTERFACE alt=1, which is whereep_in_szgets set. So it is still 0, the assert fails, and nothing recomputes once the
endpoint opens.
audiod_tx_packet_size()then checksnominal_size[1], finds 0, skips flowcontrol entirely and returns
tu_min16(data_count, max_depth).Read off the device at 48 kHz stereo 16 bit:
sample_rate_txep_in_szat calc timepacket_sz_tx[0]packet_sz_tx[1]With the fix the endpoint sends the expected mix. A bus capture of a running
stream shows 3671 packets of 192 bytes and 335 of 188.
The fix recomputes once
ep_in_szis known.Tested on ESP32-S3 and ESP32-S2 against the TinyUSB commit CircuitPython currently pins,
5453ed09f.