mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-07-29 08:31:45 +08:00
116 lines
3.3 KiB
Rust
116 lines
3.3 KiB
Rust
use axum::{extract::State, Json};
|
|
use std::sync::Arc;
|
|
|
|
use crate::atx::AtxDriverType;
|
|
use crate::config::{AtxConfig, HidBackend, HidConfig};
|
|
use crate::error::{AppError, Result};
|
|
use crate::state::AppState;
|
|
|
|
use super::apply::{apply_atx_config, try_apply_lock};
|
|
use super::types::AtxConfigUpdate;
|
|
|
|
pub async fn get_atx_config(State(state): State<Arc<AppState>>) -> Json<AtxConfig> {
|
|
Json(state.config.get().atx.clone())
|
|
}
|
|
|
|
pub async fn update_atx_config(
|
|
State(state): State<Arc<AppState>>,
|
|
Json(req): Json<AtxConfigUpdate>,
|
|
) -> Result<Json<AtxConfig>> {
|
|
let current_config = state.config.get();
|
|
let old_atx_config = current_config.atx.clone();
|
|
|
|
req.validate_with_current(&old_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, ¤t_config.hid)?;
|
|
|
|
state
|
|
.config
|
|
.update(|config| {
|
|
req.apply_to(&mut config.atx);
|
|
})
|
|
.await?;
|
|
|
|
let new_atx_config = state.config.get().atx.clone();
|
|
|
|
apply_atx_config(&state, &old_atx_config, &new_atx_config).await?;
|
|
|
|
Ok(Json(new_atx_config))
|
|
}
|
|
|
|
fn validate_windows_atx_backends(atx: &AtxConfig) -> Result<()> {
|
|
if !cfg!(windows) {
|
|
return Ok(());
|
|
}
|
|
|
|
if !matches!(atx.driver, AtxDriverType::Serial | AtxDriverType::None) {
|
|
return Err(AppError::BadRequest(
|
|
"Windows ATX only supports serial relay or none".to_string(),
|
|
));
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
fn validate_serial_device_conflict(atx: &AtxConfig, hid: &HidConfig) -> Result<()> {
|
|
if hid.backend != HidBackend::Ch9329 {
|
|
return Ok(());
|
|
}
|
|
let reserved = hid.ch9329_port.trim();
|
|
if reserved.is_empty() {
|
|
return Ok(());
|
|
}
|
|
|
|
if atx.driver == AtxDriverType::Serial && atx.device.trim() == reserved {
|
|
return Err(AppError::BadRequest(format!(
|
|
"ATX serial device '{}' conflicts with HID CH9329 serial device",
|
|
reserved
|
|
)));
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_validate_serial_device_conflict_rejects_ch9329_overlap() {
|
|
let mut atx = AtxConfig::default();
|
|
atx.driver = AtxDriverType::Serial;
|
|
atx.device = "/dev/ttyUSB0".to_string();
|
|
|
|
let mut hid = HidConfig::default();
|
|
hid.backend = HidBackend::Ch9329;
|
|
hid.ch9329_port = "/dev/ttyUSB0".to_string();
|
|
|
|
assert!(validate_serial_device_conflict(&atx, &hid).is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_validate_serial_device_conflict_allows_non_ch9329_backend() {
|
|
let mut atx = AtxConfig::default();
|
|
atx.driver = AtxDriverType::Serial;
|
|
atx.device = "/dev/ttyUSB0".to_string();
|
|
|
|
let mut hid = HidConfig::default();
|
|
hid.backend = HidBackend::None;
|
|
hid.ch9329_port = "/dev/ttyUSB0".to_string();
|
|
|
|
assert!(validate_serial_device_conflict(&atx, &hid).is_ok());
|
|
}
|
|
|
|
#[test]
|
|
fn test_validate_windows_atx_backends_allows_serial() {
|
|
let mut atx = AtxConfig::default();
|
|
atx.driver = AtxDriverType::Serial;
|
|
|
|
assert!(validate_windows_atx_backends(&atx).is_ok());
|
|
}
|
|
}
|