feat: 增加 OTG HID 远程唤醒和 OTG MSD 设备名称配置

- 在补丁内核上启用 HID 写入唤醒及 USB 远程唤醒描述符
  - 支持全局配置 Flash 和 CD-ROM INQUIRY 字符串
  - 兼容普通内核的通用 INQUIRY 属性
  - 调整 OTG 功能布局并更新大容量 DVD 镜像提示
This commit is contained in:
mofeng-git
2026-07-29 13:56:52 +08:00
parent e0bddc2faa
commit 887f29096f
12 changed files with 347 additions and 67 deletions

View File

@@ -49,18 +49,51 @@ impl Default for VideoConfig {
pub struct MsdConfig {
pub enabled: bool,
pub msd_dir: String,
pub flash_inquiry_string: String,
pub cdrom_inquiry_string: String,
}
pub const DEFAULT_FLASH_INQUIRY_STRING: &str = "One-KVM Virtual Flash";
pub const DEFAULT_CDROM_INQUIRY_STRING: &str = "One-KVM Virtual CD-ROM";
pub const MAX_INQUIRY_STRING_BYTES: usize = 28;
impl Default for MsdConfig {
fn default() -> Self {
Self {
enabled: true,
msd_dir: String::new(),
flash_inquiry_string: DEFAULT_FLASH_INQUIRY_STRING.to_string(),
cdrom_inquiry_string: DEFAULT_CDROM_INQUIRY_STRING.to_string(),
}
}
}
impl MsdConfig {
pub fn validate(&self) -> crate::error::Result<()> {
Self::validate_inquiry_string("Flash", &self.flash_inquiry_string)?;
Self::validate_inquiry_string("CD-ROM", &self.cdrom_inquiry_string)
}
pub fn validate_inquiry_string(kind: &str, value: &str) -> crate::error::Result<()> {
let value = value.trim();
if value.is_empty() {
return Err(crate::error::AppError::BadRequest(format!(
"MSD {kind} inquiry string cannot be empty"
)));
}
if value.len() > MAX_INQUIRY_STRING_BYTES {
return Err(crate::error::AppError::BadRequest(format!(
"MSD {kind} inquiry string must be at most {MAX_INQUIRY_STRING_BYTES} bytes"
)));
}
if !value.bytes().all(|byte| (0x20..=0x7e).contains(&byte)) {
return Err(crate::error::AppError::BadRequest(format!(
"MSD {kind} inquiry string must contain printable ASCII characters only"
)));
}
Ok(())
}
pub fn msd_dir_path(&self) -> std::path::PathBuf {
std::path::PathBuf::from(&self.msd_dir)
}
@@ -123,3 +156,18 @@ impl Default for WebConfig {
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn msd_inquiry_strings_default_and_validate() {
assert!(MsdConfig::default().validate().is_ok());
assert!(MsdConfig::validate_inquiry_string("Flash", " Custom Drive ").is_ok());
assert!(MsdConfig::validate_inquiry_string("Flash", "").is_err());
assert!(MsdConfig::validate_inquiry_string("Flash", &"x".repeat(29)).is_err());
assert!(MsdConfig::validate_inquiry_string("CD-ROM", "虚拟光驱").is_err());
assert!(MsdConfig::validate_inquiry_string("CD-ROM", "bad\tname").is_err());
}
}