feat: 完善 OTG UAC 音频支持

This commit is contained in:
mofeng-git
2026-07-26 11:59:58 +08:00
parent f86cba6ce5
commit 5963dfa01a
46 changed files with 2875 additions and 1867 deletions

78
src/config/schema/uac.rs Normal file
View File

@@ -0,0 +1,78 @@
use serde::{Deserialize, Serialize};
use typeshare::typeshare;
use crate::error::{AppError, Result};
/// Configuration for the USB Audio Class microphone gadget.
#[typeshare]
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(default)]
pub struct UacConfig {
pub enabled: bool,
pub sample_rate: u32,
pub channels: u8,
}
impl Default for UacConfig {
fn default() -> Self {
Self {
enabled: false,
sample_rate: 48_000,
channels: 2,
}
}
}
impl UacConfig {
pub fn validate(&self) -> Result<()> {
// Older configurations stored zero-valued placeholders while UAC was
// disabled. Accept them until the feature is enabled and normalized.
if !self.enabled {
return Ok(());
}
if self.sample_rate != 48_000 {
return Err(AppError::BadRequest(format!(
"unsupported UAC sample rate {} (expected 48000)",
self.sample_rate
)));
}
if self.channels != 2 {
return Err(AppError::BadRequest(format!(
"unsupported UAC channel count {} (expected 2)",
self.channels
)));
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_match_the_audio_transport() {
let config = UacConfig::default();
assert_eq!(config.sample_rate, 48_000);
assert_eq!(config.channels, 2);
assert!(config.validate().is_ok());
}
#[test]
fn rejects_formats_the_transport_cannot_convert() {
assert!(UacConfig {
enabled: true,
sample_rate: 44_100,
..Default::default()
}
.validate()
.is_err());
assert!(UacConfig {
enabled: true,
channels: 1,
..Default::default()
}
.validate()
.is_err());
}
}