server udc fix

This commit is contained in:
Brad Stein 2025-06-26 01:59:53 -05:00
parent 4419b5ce73
commit b63e04ff95

View File

@ -164,25 +164,44 @@ impl UsbGadget {
for drv in cand {
let root = format!("/sys/bus/platform/drivers/{drv}");
if !Path::new(&root).exists() { continue }
/*----------- unbind ------------------------------------------------*/
info!("🔧 unbinding UDC driver ({drv})");
let _ = Self::write_attr(format!("{root}/unbind"), ctrl); // ignore EINVAL
thread::sleep(Duration::from_millis(300));
for attempt in 1..=20 {
match Self::write_attr(format!("{root}/unbind"), ctrl) {
Ok(_) => break,
Err(err) if attempt < 20 && Self::is_still_detaching(&err) => {
trace!("unbind inprogress (#{attempt}) waiting…");
thread::sleep(Duration::from_millis(100));
}
Err(err) => return Err(err)
.context("UDC unbind failed irrecoverably"),
}
}
thread::sleep(Duration::from_millis(150)); // let the core quiesce
/*----------- bind --------------------------------------------------*/
info!("🔧 binding UDC driver ({drv})");
for attempt in 1..=10 {
for attempt in 1..=20 {
match Self::write_attr(format!("{root}/bind"), ctrl) {
Ok(_) => return Ok(()),
Err(e) if attempt < 10 => {
Ok(_) => return Ok(()), // success 🎉
Err(err) if attempt < 20 && Self::is_still_detaching(&err) => {
trace!("bind busy (#{attempt}) retrying…");
thread::sleep(Duration::from_millis(100));
continue;
}
Err(e) => return Err(e)
.context(format!("bind failed after {attempt} tries")),
Err(err) => return Err(err)
.context("UDC bind failed irrecoverably"),
}
}
}
Err(anyhow::anyhow!("no dwc2/dwc3 driver nodes found"))
}
fn is_still_detaching(err: &anyhow::Error) -> bool {
err.downcast_ref::<std::io::Error>()
.and_then(|io| io.raw_os_error())
.map_or(false, |code| {
matches!(code, libc::EBUSY | libc::ENOENT | libc::ENODEV)
})
}
}