server udc fix

This commit is contained in:
Brad Stein 2025-06-25 23:51:30 -05:00
parent 140eef5513
commit 158b9ef3ab

View File

@ -54,6 +54,17 @@ impl UsbGadget {
Ok(())
}
// Wait (≤ `limit_ms`) until `/sys/class/udc/<ctrl>` exists again.
fn wait_udc_present(ctrl: &str, limit_ms: u64) -> Result<()> {
for _ in 0..=limit_ms / 50 {
if Path::new(&format!("/sys/class/udc/{ctrl}")).exists() {
return Ok(());
}
thread::sleep(Duration::from_millis(50));
}
Err(anyhow::anyhow!("⚠️ UDC {ctrl} did not reappear within {limit_ms}ms"))
}
/* public API */
/// Hardreset the gadget → identical to a physical cable replug
@ -80,19 +91,21 @@ impl UsbGadget {
/* 2 unbind / bind platform driver (dwc2/dwc3) */
Self::rebind_driver(&ctrl)?;
Self::wait_udc_present(&ctrl, 3_000)
.context("controller did not reappear after bind")?;
/* 3 reattach gadget */
info!("🔌 reattaching gadget to {ctrl}");
Self::write_attr(self.udc_file, &ctrl)?;
/* 4 toggle gadget */
/* 4 assert pullup */
let sc = format!("/sys/class/udc/{ctrl}/soft_connect");
// toggle 0 → 1 to force the controller to assert pullups
Self::write_attr(&sc, "0")?; // guarantee clean edge
thread::sleep(Duration::from_millis(50));
Self::write_attr(&sc, "1")?;
/* 4 wait for gadget */
/* 5 wait for host (but tolerate sleep) */
Self::wait_state(&ctrl, "configured", 6_000)
.or_else(|e| {
// If the host is physically absent (sleep / KVM paused)
@ -123,11 +136,11 @@ impl UsbGadget {
}
info!("🔧 unbinding UDC driver ({drv})");
Self::write_attr(format!("{root}/unbind"), ctrl)?;
thread::sleep(Duration::from_millis(300));
thread::sleep(Duration::from_millis(500));
info!("🔧 binding UDC driver ({drv})");
Self::write_attr(format!("{root}/bind"), ctrl)?;
thread::sleep(Duration::from_millis(100));
thread::sleep(Duration::from_millis(500));
return Ok(());
}
Err(anyhow::anyhow!("no dwc2/dwc3 driver nodes found"))