teensy4: add capture-side USB Audio Feature Unit (mute/volume) for recording devices#799
Open
JayShoe wants to merge 1 commit intoPaulStoffregen:masterfrom
Open
Conversation
…cording devices Add a USB Audio Class 1.0 Feature Unit (ID 0x30) on the device-to-host capture path so the host OS can control mute and volume on audio the Teensy sends. Previously the AudioControl descriptor only had a Feature Unit on the playback path (FU 0x31), so the host never exposed a recording-device volume slider. Topology after the patch: capture: IT1 -> FU 0x30 -> OT2 <- new playback: IT3 -> FU 0x31 -> OT4 <- unchanged usb_desc.c: - Insert 10-byte FEATURE_UNIT descriptor (ID 0x30: master mute + L/R volume) between IT1 and OT2 on the capture path - Retarget OT2 bCSourceID from IT1 (0x01) to FU 0x30 - Bump AC header wTotalLength from 62 to 72 - Both high-speed and full-speed descriptor copies updated usb_audio.h: - Add AudioOutputUSB::features (mirrors AudioInputUSB::features) - Add volume()/mute() accessors to AudioOutputUSB - Add mute() accessor to AudioInputUSB for parity - Add friend declarations for set/get_feature to AudioOutputUSB usb_audio.cpp: - Define AudioOutputUSB::features - Add usb_audio_features_for_entity() to route by Entity ID: FU 0x31 -> AudioInputUSB::features (playback, unchanged) FU 0x30 -> AudioOutputUSB::features (capture, new) - Replace hardcoded AudioInputUSB::features in set/get_feature with entity-routed pointer The core does not auto-apply capture volume to the transmit path; the sketch decides how to use the value (same pattern as the existing AudioInputUSB::volume()). No changes to usb.c required. Tested on Teensy 4.1, Windows 11.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a USB Audio Class 1.0 Feature Unit on the device-to-host (capture/recording) path so the host OS can control mute and volume on audio the Teensy sends. Previously the AudioControl descriptor only had a Feature Unit on the playback path (FU 0x31), so the host never exposed a recording-device volume slider — the Microphone level control in Windows Sound Settings had nothing to bind to.
Topology after the patch:
Changes
usb_desc.cFEATURE_UNITdescriptor block (ID 0x30: master mute + L/R volume) between Input Terminal 1 and Output Terminal 2 on the capture pathbCSourceIDfrom IT1 (0x01) to FU 0x30wTotalLengthfrom 62 to 72AUDIO_INTERFACE_DESC_SIZEto account for the new blockusb_audio.hstatic struct usb_audio_features_struct featurestoAudioOutputUSB, mirroring the existingAudioInputUSB::featuresvolume()andmute()accessors toAudioOutputUSBmute()accessor toAudioInputUSBfor parity (the data was already there —volume()readsfeatures.muteinternally but there was no standalone accessor)frienddeclarations forusb_audio_set_feature/usb_audio_get_featuretoAudioOutputUSBusb_audio.cppAudioOutputUSB::features(initialized to same defaults asAudioInputUSB::features)usb_audio_features_for_entity()helper that routes by the Entity ID in thewIndexhigh byte:AudioInputUSB::features(playback, unchanged behavior)AudioOutputUSB::features(capture, new)AudioInputUSB::featuresreferences inusb_audio_set_feature()andusb_audio_get_feature()with the entity-routed pointerUsage
Notes
usb.c— the existingword1match in the control-endpoint dispatcher deliberately ignoreswIndex, so SET_CUR requests to either Feature Unit already fall through intousb_audio_set_feature(), which now disambiguates by entity ID.AudioInputUSB::volume()).bcdDeviceis not bumped (it's used for board identification byteensy_ports). Windows re-enumerates on descriptor-length change; if it caches stale topology, unplug/replug clears it.AudioOutputUSB::features.