feat: 初步增加 Windows 支持

This commit is contained in:
mofeng-git
2026-05-18 22:43:28 +08:00
parent 0b9d94f53f
commit 935fa823f2
163 changed files with 11419 additions and 7581 deletions

View File

@@ -39,12 +39,20 @@ fn hid_backend_type(config: &HidConfig) -> crate::hid::HidBackendType {
}
async fn reconcile_otg_from_store(state: &Arc<AppState>) -> Result<()> {
let config = state.config.get();
state
.otg_service
.apply_config(&config.hid, &config.msd)
.await
.map_err(|e| AppError::Config(format!("OTG reconcile failed: {}", e)))
#[cfg(not(unix))]
{
let _ = state;
Ok(())
}
#[cfg(unix)]
{
let config = state.config.get();
state
.otg_service
.apply_config(&config.hid, &config.msd)
.await
.map_err(|e| AppError::Config(format!("OTG reconcile failed: {}", e)))
}
}
pub async fn apply_video_config(
@@ -207,6 +215,7 @@ pub async fn apply_hid_config(
Ok(())
}
#[cfg(unix)]
pub async fn apply_msd_config(
state: &Arc<AppState>,
old_config: &MsdConfig,

View File

@@ -25,6 +25,7 @@ pub async fn update_atx_config(
let _apply_guard = try_apply_lock(&state.config_apply_locks.atx, "atx")?;
let mut merged_atx_config = old_atx_config.clone();
req.apply_to(&mut merged_atx_config);
validate_windows_atx_backends(&merged_atx_config)?;
validate_serial_device_conflict(&merged_atx_config, &current_config.hid)?;
state
@@ -41,6 +42,23 @@ pub async fn update_atx_config(
Ok(Json(new_atx_config))
}
fn validate_windows_atx_backends(atx: &AtxConfig) -> Result<()> {
if !cfg!(windows) {
return Ok(());
}
for (name, key) in [("power", &atx.power), ("reset", &atx.reset)] {
if !matches!(key.driver, AtxDriverType::Serial | AtxDriverType::None) {
return Err(AppError::BadRequest(format!(
"Windows ATX {} only supports serial relay or none",
name
)));
}
}
Ok(())
}
fn validate_serial_device_conflict(atx: &AtxConfig, hid: &HidConfig) -> Result<()> {
if hid.backend != HidBackend::Ch9329 {
return Ok(());
@@ -91,4 +109,13 @@ mod tests {
assert!(validate_serial_device_conflict(&atx, &hid).is_ok());
}
#[test]
fn test_validate_windows_atx_backends_allows_serial() {
let mut atx = AtxConfig::default();
atx.power.driver = AtxDriverType::Serial;
atx.reset.driver = AtxDriverType::None;
assert!(validate_windows_atx_backends(&atx).is_ok());
}
}

View File

@@ -5,6 +5,7 @@ mod atx;
mod audio;
mod auth;
mod hid;
#[cfg(unix)]
mod msd;
mod redfish;
mod rtsp;
@@ -17,6 +18,7 @@ pub use atx::{get_atx_config, update_atx_config};
pub use audio::{get_audio_config, update_audio_config};
pub use auth::{get_auth_config, update_auth_config};
pub use hid::{get_hid_config, update_hid_config};
#[cfg(unix)]
pub use msd::{get_msd_config, update_msd_config};
pub use redfish::{get_redfish_config, update_redfish_config};
pub use rtsp::{get_rtsp_config, get_rtsp_status, update_rtsp_config};

View File

@@ -77,11 +77,14 @@ pub async fn update_rustdesk_config(
let _apply_guard = try_apply_lock(&state.config_apply_locks.rustdesk, "rustdesk")?;
let old_config = state.config.get().rustdesk.clone();
let mut merged_config = old_config.clone();
req.apply_to(&mut merged_config);
req.validate_merged(&merged_config)?;
state
.config
.update(|config| {
req.apply_to(&mut config.rustdesk);
config.rustdesk = merged_config.clone();
})
.await?;

View File

@@ -4,6 +4,7 @@ use crate::rtsp::RtspServiceStatus;
use crate::rustdesk::config::RustDeskConfig;
use base64::{engine::general_purpose::STANDARD, Engine as _};
use serde::{Deserialize, Serialize};
#[cfg(unix)]
use std::path::Path;
use typeshare::typeshare;
@@ -358,12 +359,14 @@ impl HidConfigUpdate {
}
#[typeshare]
#[cfg(unix)]
#[derive(Debug, Deserialize)]
pub struct MsdConfigUpdate {
pub enabled: Option<bool>,
pub msd_dir: Option<String>,
}
#[cfg(unix)]
impl MsdConfigUpdate {
pub fn validate(&self) -> crate::error::Result<()> {
if let Some(ref dir) = self.msd_dir {
@@ -472,7 +475,8 @@ impl AtxConfigUpdate {
fn validate_key_config(key: &AtxKeyConfigUpdate, name: &str) -> crate::error::Result<()> {
if let Some(ref device) = key.device {
if !device.is_empty() && !std::path::Path::new(device).exists() {
if !device.trim().is_empty() && !cfg!(windows) && !std::path::Path::new(device).exists()
{
return Err(AppError::BadRequest(format!(
"{} device '{}' does not exist",
name, device
@@ -542,6 +546,12 @@ impl AtxConfigUpdate {
) -> crate::error::Result<()> {
match key.driver {
crate::atx::AtxDriverType::Serial => {
if key.device.trim().is_empty() {
return Err(AppError::BadRequest(format!(
"{} serial device cannot be empty",
name
)));
}
if key.pin == 0 {
return Err(AppError::BadRequest(format!(
"{} serial channel must be 1-based (>= 1)",
@@ -739,6 +749,15 @@ impl RustDeskConfigUpdate {
Ok(())
}
pub fn validate_merged(&self, config: &RustDeskConfig) -> crate::error::Result<()> {
if config.enabled && config.rendezvous_server.trim().is_empty() {
return Err(AppError::BadRequest(
"RustDesk ID server is required".into(),
));
}
Ok(())
}
pub fn apply_to(&self, config: &mut RustDeskConfig) {
if let Some(enabled) = self.enabled {
config.enabled = enabled;