summaryrefslogtreecommitdiff
path: root/examples/host
diff options
context:
space:
mode:
authorHiFiPHile <[email protected]>2026-08-26 15:54:38 +0200
committerHiFiPHile <[email protected]>2026-08-27 10:34:33 +0200
commitcca648556dd0c096aa7210ee5a2b962efae36440 (patch)
treecbf897160767f5dab6b762ce7fc4fbe3b828f35e /examples/host
parent804e54f9e59dc2b6442844d1194581e2b39c35b1 (diff)
audio: add UAC2 host streaming support
Add protocol-selectable UAC1/UAC2 parsing, UAC2 terminal and Feature Unit topology, Clock Source discovery, sampling-frequency ranges, and protocol-specific stream controls. Cover UAC2 playback, capture, control discovery, and malformed descriptors with unit tests. Signed-off-by: HiFiPHile <[email protected]>
Diffstat (limited to 'examples/host')
-rw-r--r--examples/host/audio_host/README.md18
-rw-r--r--examples/host/audio_host/src/audio_app.c2
-rw-r--r--examples/host/audio_host/src/main.c2
-rw-r--r--examples/host/audio_host/src/tusb_config.h3
4 files changed, 16 insertions, 9 deletions
diff --git a/examples/host/audio_host/README.md b/examples/host/audio_host/README.md
index 06cc4f197..2b5df7785 100644
--- a/examples/host/audio_host/README.md
+++ b/examples/host/audio_host/README.md
@@ -1,10 +1,10 @@
# USB Audio Host Example
-This example demonstrates how to use TinyUSB's USB Audio Host driver (TUH_AUDIO) to capture audio from a UAC 1.0 compatible USB microphone and echo it back to the speaker, using a WASAPI/ALSA-like high-level API. The application never touches USB interfaces, alternate settings, or endpoint addresses — it only selects supported `{format, sample_rate, channels}` configurations by stream index.
+This example demonstrates how to use TinyUSB's USB Audio Host driver (TUH_AUDIO) to capture audio from a UAC 1.0 or UAC 2.0 USB microphone and echo it back to the speaker, using a WASAPI/ALSA-like high-level API. The application never touches USB interfaces, alternate settings, or endpoint addresses — it only selects supported `{format, sample_rate, channels}` configurations by stream index.
## Features
-- Enumerates and mounts USB Audio Class 1.0 devices
+- Enumerates and mounts USB Audio Class 1.0 and 2.0 devices
- Discovers the device's logical streams (capture/playback) and their supported configurations (discrete tuples only)
- Reports each stream's master mute/volume capabilities and cached volume range
- Configures and starts an S16_LE capture stream (48 kHz preferred, 44.1 kHz fallback; stereo preferred, mono accepted)
@@ -14,7 +14,7 @@ This example demonstrates how to use TinyUSB's USB Audio Host driver (TUH_AUDIO)
## Supported Devices
-This example supports UAC 1.0 devices whose Type I Format descriptor lists discrete sampling frequencies (`bSamFreqType > 0`), such as:
+This example supports UAC1 devices whose Type I Format descriptor lists discrete sampling frequencies (`bSamFreqType > 0`) and UAC2 devices using a directly connected Clock Source, such as:
- USB microphones
- USB headsets (mono microphone + speaker)
@@ -26,8 +26,10 @@ The echo needs a matching S16_LE playback stream at the capture sample rate; dev
- Explicit feedback endpoints are supported with both 10.14 and 16.16 feedback values. An implicit-feedback IN endpoint is treated as an ordinary audio-data endpoint and is not used to pace playback.
- UAC1 Type I Format descriptors with `bSamFreqType == 0` are unsupported; the driver requires a list of discrete sampling frequencies.
-- Master mute and volume controls are discovered before the mount callback, including the volume MIN/MAX/RES range. Feature Units without master mute or volume are ignored. The typed API controls the master channel; the lower-level Feature Unit API remains available for fixed-width UAC1 controls on the associated unit.
-- The UAC1 `MaxPacketsOnly` endpoint attribute is not supported. OUT transfers are not padded to `wMaxPacketSize`, and padding in IN transfers is not removed from the reported audio data.
+- UAC2 supports direct Clock Sources. Clock Selectors, Clock Multipliers, Sampling Rate Converters, Clock Validity, and Valid Alternate Settings controls are not handled.
+- UAC2 sampling-frequency RANGE responses are expanded into at most `CFG_TUH_AUDIO_MAX_SAM_FREQ` discrete configurations. A read-only Clock Source exposes only its current frequency.
+- Master mute and volume controls are discovered before the mount callback, including the volume range. Feature Units without master mute or volume are ignored. UAC2 volume discovery supports the common RANGE response containing one subrange.
+- The `MaxPacketsOnly` endpoint attribute is not supported. OUT transfers are not padded to `wMaxPacketSize`, and padding in IN transfers is not removed from the reported audio data.
## Building
@@ -63,7 +65,7 @@ make BOARD=<your_board> flash
## Usage
1. Build and flash the example to your board
-2. Connect a USB Audio device (UAC 1.0) to the USB host port
+2. Connect a USB Audio device (UAC 1.0 or 2.0) to the USB host port
3. Open a serial terminal to view output
4. The example will:
- Print each stream's Feature Unit ID, master mute/volume capabilities, cached volume range, and supported configurations when mounted
@@ -77,7 +79,7 @@ make BOARD=<your_board> flash
```
TinyUSB Host USB Audio Example
-Connect a USB Audio Device (UAC 1.0) to test
+Connect a USB Audio Device (UAC 1.0 or 2.0) to test
Audio device mounted: idx=0 addr=1
capture stream 1 Feature Unit ID: 5, configurations: 2
master mute supported
@@ -105,6 +107,8 @@ Audio device mounted: idx=0 addr=1
Edit `src/tusb_config.h` to modify:
- `CFG_TUH_AUDIO_MAX`: Maximum number of audio devices supported
+- `CFG_TUH_AUDIO_PROTOCOLS`: Bitmask selecting UAC1 and/or UAC2 support; the example enables both
+- `CFG_TUH_AUDIO_MAX_SAM_FREQ`: Maximum number of discrete frequencies retained per alternate setting or UAC2 Clock Source
- `CFG_TUH_AUDIO_EPIN_BUFSIZE`: Maximum size of one capture transfer the driver submits (configurations needing a larger per-poll-interval packet are rejected)
- `CFG_TUH_AUDIO_EPOUT_BUFSIZE`: Maximum size of one playback transfer the driver submits
- `CFG_TUH_AUDIO_STREAM_BUFSIZE`: Per-stream FIFO depth in bytes (default 1024, i.e. four 256 B packets); capture overwrites the oldest frames when full
diff --git a/examples/host/audio_host/src/audio_app.c b/examples/host/audio_host/src/audio_app.c
index 9a1434284..4623dff5a 100644
--- a/examples/host/audio_host/src/audio_app.c
+++ b/examples/host/audio_host/src/audio_app.c
@@ -30,7 +30,7 @@
// - SAMPLE_RATES: sample rates tried in order, first match wins (44.1 kHz stereo by default)
#define AUDIO_MAX_FRAME_COUNT 48
#define AUDIO_MAX_CHANNELS 2
-#define SAMPLE_RATES {48000, 44100}
+#define SAMPLE_RATES {44100, 48000}
#define FEATURE_UNIT_VOLUME_DB (-6 * 256)
static uint8_t audio_idx = TUSB_INDEX_INVALID_8; // index of the selected audio device
static uint8_t cap_stream_idx = TUSB_INDEX_INVALID_8; // capture stream index
diff --git a/examples/host/audio_host/src/main.c b/examples/host/audio_host/src/main.c
index 3a3e18ab7..45c468f23 100644
--- a/examples/host/audio_host/src/main.c
+++ b/examples/host/audio_host/src/main.c
@@ -31,7 +31,7 @@ int main(void) {
board_init();
printf("TinyUSB Host USB Audio Example\r\n");
- printf("Connect a USB Audio Device (UAC 1.0) to test\r\n");
+ printf("Connect a USB Audio Device (UAC 1.0 or 2.0) to test\r\n");
// init host stack on configured roothub port
tusb_rhport_init_t host_init = {.role = TUSB_ROLE_HOST, .speed = TUSB_SPEED_AUTO};
diff --git a/examples/host/audio_host/src/tusb_config.h b/examples/host/audio_host/src/tusb_config.h
index 9b7f3c94b..5c2d54993 100644
--- a/examples/host/audio_host/src/tusb_config.h
+++ b/examples/host/audio_host/src/tusb_config.h
@@ -87,6 +87,9 @@ extern "C" {
#define CFG_TUH_MSC 0
#define CFG_TUH_VENDOR 0
#define CFG_TUH_AUDIO 1
+#ifndef CFG_TUH_AUDIO_PROTOCOLS
+ #define CFG_TUH_AUDIO_PROTOCOLS (TUH_AUDIO_PROTOCOL_UAC1 | TUH_AUDIO_PROTOCOL_UAC2)
+#endif
// max device support (excluding hub device): 1 hub typically has 4 ports
#define CFG_TUH_DEVICE_MAX (3 * CFG_TUH_HUB + 1)