summaryrefslogtreecommitdiff
path: root/src/class/audio
diff options
context:
space:
mode:
authorHiFiPHile <[email protected]>2026-08-25 09:27:35 +0200
committerHiFiPHile <[email protected]>2026-08-25 09:27:35 +0200
commit3e3de770979b1afa375153de7c789176e39342bd (patch)
tree72463e5a8e4ad05c59cde1fddd2ce2e8c1da0915 /src/class/audio
parent5fb0a3d04509d6904feff387d4669e2d6184cdb9 (diff)
fix(audio): close endpoints before stream reconfiguration
Close the previously selected HCD endpoint before opening another alternate setting. This prevents stale endpoint size and controller state from surviving a format change. Signed-off-by: HiFiPHile <[email protected]>
Diffstat (limited to 'src/class/audio')
-rw-r--r--src/class/audio/audio_host.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/src/class/audio/audio_host.c b/src/class/audio/audio_host.c
index d8b5324f2..72c00576f 100644
--- a/src/class/audio/audio_host.c
+++ b/src/class/audio/audio_host.c
@@ -356,7 +356,23 @@ static void audioh_stream_playback_xfer(tuh_audio_stream_t *s) {
// Configure state machine
//--------------------------------------------------------------------+
+static bool audioh_stream_close_ep(tuh_audio_stream_t *s) {
+ if (!tu_edpt_stream_is_opened(&s->edpt)) {
+ return true;
+ }
+
+ const uint8_t ep_addr = s->edpt.ep_addr;
+ if (!tuh_edpt_close(s->daddr, ep_addr)) {
+ TU_LOG_DRV(" AUDIO close endpoint failed: addr=%u ep=%02x\r\n", s->daddr, ep_addr);
+ return false;
+ }
+
+ tu_edpt_stream_close(&s->edpt);
+ return true;
+}
+
static void audioh_stream_fail(tuh_audio_stream_t *s, tusb_xfer_result_t result) {
+ (void)audioh_stream_close_ep(s);
s->state = STREAM_STATE_IDLE;
s->active_config = TUSB_INDEX_INVALID_8;
s->running = false;
@@ -1055,7 +1071,7 @@ bool tuh_audio_configure(uint8_t dev_idx, uint8_t stream_idx, uint8_t config_idx
TU_VERIFY(s->state != STREAM_STATE_CONFIG && !s->running, false);
if (s->state == STREAM_STATE_READY) {
// Wait for any in-flight transfer to complete and be discarded
- TU_VERIFY(!usbh_edpt_busy(s->daddr, s->map[s->active_config].ep_addr), false);
+ TU_VERIFY(!usbh_edpt_busy(s->daddr, s->edpt.ep_addr), false);
}
// A shared AS interface must not be left in two different alternate settings
@@ -1076,6 +1092,10 @@ bool tuh_audio_configure(uint8_t dev_idx, uint8_t stream_idx, uint8_t config_idx
}
}
+ // The HCD endpoint must be reopened even when the new configuration uses
+ // the same address, since its packet size and interval may have changed.
+ TU_VERIFY(audioh_stream_close_ep(s), false);
+
s->active_config = config_idx;
s->frame_bytes = (uint8_t)tuh_audio_config_frame_size(cfg);
s->frames_per_ms = (uint16_t)(cfg->sample_rate / 1000);