From 4e32b051249edea6e674cd47fd32f870452b8b35 Mon Sep 17 00:00:00 2001 From: arounyf Date: Wed, 22 Jul 2026 04:54:18 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8DOTG=20gadget=E9=87=8D?= =?UTF-8?q?=E5=BB=BA=E5=90=8EHID=E5=90=8E=E7=AB=AF=E6=9C=AA=E9=87=8D?= =?UTF-8?q?=E8=BD=BD=E5=AF=BC=E8=87=B4=E9=94=AE=E9=BC=A0=E5=A4=B1=E6=95=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 当MSD或OTG网络配置变更导致gadget被重建时,新的/dev/hidg*设备 被创建但HID后端因'配置未变'跳过了reload,导致仍持有已删除设备 的旧文件描述符,键鼠操作无效。 修复: 在apply_usb_config中检测gadget是否因MSD/网络变更被重建, 若是且HID后端为OTG,强制reload HID以打开新的/dev/hidg*设备。 同时为MsdConfig添加PartialEq derive以支持变更检测。 --- src/config/schema/web.rs | 2 +- src/web/handlers/config/apply.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/config/schema/web.rs b/src/config/schema/web.rs index 6671855d..c3795c5c 100644 --- a/src/config/schema/web.rs +++ b/src/config/schema/web.rs @@ -44,7 +44,7 @@ impl Default for VideoConfig { } #[typeshare] -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(default)] pub struct MsdConfig { pub enabled: bool, diff --git a/src/web/handlers/config/apply.rs b/src/web/handlers/config/apply.rs index 65d59ef0..24e7a4dd 100644 --- a/src/web/handlers/config/apply.rs +++ b/src/web/handlers/config/apply.rs @@ -365,6 +365,10 @@ pub async fn apply_usb_config( let transitioning_away_from_otg = old_config.hid.backend == HidBackend::Otg && new_config.hid.backend != HidBackend::Otg; + let hid_unchanged = old_config.hid == new_config.hid; + let otg_gadget_rebuilt = + old_config.msd != new_config.msd || old_config.otg_network != new_config.otg_network; + if transitioning_away_from_otg { apply_hid_config( state, @@ -394,6 +398,19 @@ pub async fn apply_usb_config( .await?; } + // When the OTG gadget was rebuilt due to MSD or network config changes + // while HID config stayed the same, the /dev/hidg* devices are new and + // the HID backend must be reloaded to reopen them. + if hid_unchanged && otg_gadget_rebuilt && new_config.hid.backend == HidBackend::Otg { + tracing::info!("OTG gadget rebuilt, reloading HID backend for new devices"); + let hid_backend = hid_backend_type(&new_config.hid); + state + .hid + .reload(hid_backend) + .await + .map_err(|e| AppError::Config(format!("HID reload after gadget rebuild failed: {}", e)))?; + } + apply_msd_config( state, &old_config.msd,