Merge pull request #278 from mofeng-git/dev

Dev
This commit is contained in:
SilentWind
2026-07-19 21:50:59 +08:00
committed by GitHub
330 changed files with 15896 additions and 13600 deletions

View File

@@ -83,6 +83,10 @@ pub trait HidBackend: Send + Sync {
async fn reset(&self) -> Result<()>;
async fn prepare_rebuild(&self) -> Result<()> {
self.shutdown().await
}
async fn shutdown(&self) -> Result<()>;
fn runtime_snapshot(&self) -> HidBackendRuntimeSnapshot;

View File

@@ -234,6 +234,30 @@ impl HidController {
Ok(())
}
pub async fn prepare_otg_rebuild(&self) -> Result<()> {
if !matches!(*self.backend_type.read().await, HidBackendType::Otg) {
return Ok(());
}
info!("Preparing OTG HID backend for gadget rebuild");
self.backend_available.store(false, Ordering::Release);
self.stop_runtime_worker().await;
if let Some(backend) = self.backend.write().await.take() {
backend.prepare_rebuild().await?;
}
let current = self.runtime_state.read().await.clone();
let rebuilding_state = HidRuntimeState::with_error(
&HidBackendType::Otg,
&current,
"OTG gadget is rebuilding",
"rebuilding",
);
self.apply_runtime_state(rebuilding_state).await;
Ok(())
}
pub async fn send_keyboard(&self, event: KeyboardEvent) -> Result<()> {
if !self.backend_available.load(Ordering::Acquire) {
return Err(AppError::BadRequest(

View File

@@ -903,6 +903,19 @@ impl HidBackend for OtgBackend {
Ok(())
}
async fn prepare_rebuild(&self) -> Result<()> {
self.stop_runtime_worker();
*self.keyboard_dev.lock() = None;
*self.mouse_rel_dev.lock() = None;
*self.mouse_abs_dev.lock() = None;
*self.consumer_dev.lock() = None;
self.initialized.store(false, Ordering::Relaxed);
self.online.store(false, Ordering::Relaxed);
self.notify_runtime_changed();
info!("OTG backend prepared for gadget rebuild");
Ok(())
}
async fn shutdown(&self) -> Result<()> {
self.stop_runtime_worker();
@@ -957,6 +970,7 @@ impl Drop for OtgBackend {
#[cfg(test)]
mod tests {
use super::*;
use std::io::{Seek, SeekFrom, Write};
#[test]
fn test_led_state() {
@@ -973,4 +987,22 @@ mod tests {
let kb_report = KeyboardReport::default();
assert_eq!(kb_report.to_bytes().len(), 8);
}
#[tokio::test]
async fn prepare_rebuild_closes_devices_without_writing_reset_reports() {
let mut file = tempfile::tempfile().unwrap();
file.write_all(b"sentinel").unwrap();
file.seek(SeekFrom::Start(0)).unwrap();
let backend = OtgBackend::from_handles(HidDevicePaths::default()).unwrap();
*backend.keyboard_dev.lock() = Some(file);
backend.initialized.store(true, Ordering::Relaxed);
backend.online.store(true, Ordering::Relaxed);
backend.prepare_rebuild().await.unwrap();
assert!(backend.keyboard_dev.lock().is_none());
assert!(!backend.initialized.load(Ordering::Relaxed));
assert!(!backend.online.load(Ordering::Relaxed));
}
}