feat: UAC USB microphone passthrough

- Add UAC1 gadget function (ConfigFS) with optimized endpoint config
- Browser mic capture with Opus encoding via WebCodecs AudioEncoder
- WebSocket audio transport (Opus 64kbps, 100x bandwidth reduction vs raw PCM)
- aplay subprocess for reliable PCM playback to USB gadget
- Settings toggle + ActionBar mic button (hidden when UAC disabled)
- Dynamic PCM device resolution (/proc/asound)
- c_chmask=0 + req_number=4 fixes DWC3 composite isochronous endpoint issue
This commit is contained in:
arounyf
2026-07-23 06:56:53 +00:00
parent 4e32b05124
commit e9bed3688f
27 changed files with 977 additions and 16 deletions

View File

@@ -47,6 +47,7 @@ pub struct OtgGadgetManager {
hid_instance: u8,
msd_instance: u8,
network_instance: u8,
uac_instance: u8,
functions: Vec<Box<dyn GadgetFunction>>,
bound_udc: Option<String>,
created_by_us: bool,
@@ -73,6 +74,7 @@ impl OtgGadgetManager {
hid_instance: 0,
msd_instance: 0,
network_instance: 0,
uac_instance: 0,
functions: Vec::with_capacity(4),
bound_udc: None,
created_by_us: false,
@@ -148,6 +150,14 @@ impl OtgGadgetManager {
Ok(func_clone)
}
pub fn add_uac(&mut self, sample_rate: u32, channels: u8) -> Result<super::uac::UacFunction> {
let func = super::uac::UacFunction::new(self.uac_instance, sample_rate, channels)?;
let func_clone = func.clone();
self.add_function(Box::new(func))?;
self.uac_instance += 1;
Ok(func_clone)
}
fn add_function(&mut self, func: Box<dyn GadgetFunction>) -> Result<()> {
self.functions.push(func);
Ok(())