diff options
| author | HiFiPHile <[email protected]> | 2026-08-25 09:27:36 +0200 |
|---|---|---|
| committer | HiFiPHile <[email protected]> | 2026-08-25 09:27:36 +0200 |
| commit | ef631435ce8c3dd0fde720f097ffea317ad6f06a (patch) | |
| tree | aa8e4ca779e42b7027e7cf75ffc136c4aa0e2beb /src | |
| parent | a57307b3c20fb25c95eee143fa1a36254c354922 (diff) | |
fix(audio): resolve Feature Units independent of order
Record terminal and Feature Unit links while parsing the AudioControl block, then resolve the stream association after all entities are known. Common capture and playback descriptor orders are both supported.
Signed-off-by: HiFiPHile <[email protected]>
Diffstat (limited to 'src')
| -rw-r--r-- | src/class/audio/audio_host.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/src/class/audio/audio_host.c b/src/class/audio/audio_host.c index 968e8da3c..8918ca86e 100644 --- a/src/class/audio/audio_host.c +++ b/src/class/audio/audio_host.c @@ -882,6 +882,9 @@ uint16_t audioh_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface audioh_ac_header_t header = {0}; uint8_t usb_input_terminal_id = 0; uint8_t usb_output_source_id = 0; + // A Feature Unit may precede the USB terminal that identifies its stream. + uint8_t pending_fu_id = 0; + uint8_t pending_fu_source_id = 0; bool have_header = false; p_desc = tu_desc_next(p_desc); @@ -911,6 +914,11 @@ uint16_t audioh_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface if (terminal->bLength >= sizeof(audio10_desc_input_terminal_t) && tu_le16toh(terminal->wTerminalType) == AUDIO_TERM_TYPE_USB_STREAMING && usb_input_terminal_id == 0) { usb_input_terminal_id = terminal->bTerminalID; + if (pending_fu_source_id == usb_input_terminal_id) { + p_audio->out_stream.feature_unit_id = pending_fu_id; + pending_fu_id = 0; + pending_fu_source_id = 0; + } } break; } @@ -919,18 +927,30 @@ uint16_t audioh_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface if (terminal->bLength >= sizeof(audio10_desc_output_terminal_t) && tu_le16toh(terminal->wTerminalType) == AUDIO_TERM_TYPE_USB_STREAMING && usb_output_source_id == 0) { usb_output_source_id = terminal->bSourceID; + if (pending_fu_id == usb_output_source_id) { + p_audio->in_stream.feature_unit_id = pending_fu_id; + pending_fu_id = 0; + pending_fu_source_id = 0; + } } break; } case AUDIO10_CS_AC_INTERFACE_FEATURE_UNIT: { if (p_desc[0] >= 5) { + bool mapped = false; if (usb_input_terminal_id != 0 && p_audio->out_stream.feature_unit_id == 0 && p_desc[4] == usb_input_terminal_id) { p_audio->out_stream.feature_unit_id = p_desc[3]; + mapped = true; } if (usb_output_source_id != 0 && p_audio->in_stream.feature_unit_id == 0 && p_desc[3] == usb_output_source_id) { p_audio->in_stream.feature_unit_id = p_desc[3]; + mapped = true; + } + if (!mapped) { + pending_fu_id = p_desc[3]; + pending_fu_source_id = p_desc[4]; } } break; |
