mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-09-13 02:54:26 +08:00
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
¤t,
|
||||
"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(
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user