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

@@ -11,20 +11,14 @@ use super::led::LedSensor;
use super::types::{AtxAction, AtxKeyConfig, AtxLedConfig, AtxState, PowerStatus};
use crate::error::{AppError, Result};
/// ATX power control configuration
#[derive(Debug, Clone, Default)]
pub struct AtxControllerConfig {
/// Whether ATX is enabled
pub enabled: bool,
/// Power button configuration (used for both short and long press)
pub power: AtxKeyConfig,
/// Reset button configuration
pub reset: AtxKeyConfig,
/// LED sensing configuration
pub led: AtxLedConfig,
}
/// Internal state holding all ATX components
/// Grouped together to reduce lock acquisitions
struct AtxInner {
config: AtxControllerConfig,
@@ -33,12 +27,9 @@ struct AtxInner {
led_sensor: Option<LedSensor>,
}
/// ATX Controller
///
/// Manages ATX power control through independent executors for each action.
/// Supports hot-reload of configuration.
pub struct AtxController {
/// Single lock for all internal state to reduce lock contention
inner: RwLock<AtxInner>,
}
@@ -53,6 +44,24 @@ impl AtxController {
&& power.baud_rate == reset.baud_rate
}
async fn init_key_executor(
warn_label: &str,
info_label: &str,
config: AtxKeyConfig,
mut executor: AtxKeyExecutor,
) -> Option<AtxKeyExecutor> {
if let Err(e) = executor.init().await {
warn!("Failed to initialize {} executor: {}", warn_label, e);
return None;
}
info!(
"{} executor initialized: {:?} on {} pin {}",
info_label, config.driver, config.device, config.pin
);
Some(executor)
}
async fn init_components(inner: &mut AtxInner) {
if Self::should_share_serial_device(&inner.config.power, &inner.config.reset) {
match AtxKeyExecutor::open_shared_serial(
@@ -60,36 +69,28 @@ impl AtxController {
inner.config.power.baud_rate,
) {
Ok(shared_serial) => {
let mut power_executor = AtxKeyExecutor::new_with_shared_serial(
inner.config.power.clone(),
shared_serial.clone(),
);
if let Err(e) = power_executor.init().await {
warn!("Failed to initialize power executor: {}", e);
} else {
info!(
"Power executor initialized: {:?} on {} pin {}",
inner.config.power.driver,
inner.config.power.device,
inner.config.power.pin
for (slot, warn_label, info_label, config, serial) in [
(
&mut inner.power_executor,
"power",
"Power",
inner.config.power.clone(),
shared_serial.clone(),
),
(
&mut inner.reset_executor,
"reset",
"Reset",
inner.config.reset.clone(),
shared_serial,
),
] {
let executor = AtxKeyExecutor::new_with_shared_serial(
config.clone(),
serial,
);
inner.power_executor = Some(power_executor);
}
let mut reset_executor = AtxKeyExecutor::new_with_shared_serial(
inner.config.reset.clone(),
shared_serial,
);
if let Err(e) = reset_executor.init().await {
warn!("Failed to initialize reset executor: {}", e);
} else {
info!(
"Reset executor initialized: {:?} on {} pin {}",
inner.config.reset.driver,
inner.config.reset.device,
inner.config.reset.pin
);
inner.reset_executor = Some(reset_executor);
*slot = Self::init_key_executor(warn_label, info_label, config, executor)
.await;
}
}
Err(e) => {
@@ -100,40 +101,18 @@ impl AtxController {
}
}
} else {
// Initialize power executor
if inner.config.power.is_configured() {
let mut executor = AtxKeyExecutor::new(inner.config.power.clone());
if let Err(e) = executor.init().await {
warn!("Failed to initialize power executor: {}", e);
} else {
info!(
"Power executor initialized: {:?} on {} pin {}",
inner.config.power.driver,
inner.config.power.device,
inner.config.power.pin
);
inner.power_executor = Some(executor);
}
}
// Initialize reset executor
if inner.config.reset.is_configured() {
let mut executor = AtxKeyExecutor::new(inner.config.reset.clone());
if let Err(e) = executor.init().await {
warn!("Failed to initialize reset executor: {}", e);
} else {
info!(
"Reset executor initialized: {:?} on {} pin {}",
inner.config.reset.driver,
inner.config.reset.device,
inner.config.reset.pin
);
inner.reset_executor = Some(executor);
for (slot, warn_label, info_label, config) in [
(&mut inner.power_executor, "power", "Power", inner.config.power.clone()),
(&mut inner.reset_executor, "reset", "Reset", inner.config.reset.clone()),
] {
if config.is_configured() {
let executor = AtxKeyExecutor::new(config.clone());
*slot = Self::init_key_executor(warn_label, info_label, config, executor)
.await;
}
}
}
// Initialize LED sensor
if inner.config.led.is_configured() {
let mut sensor = LedSensor::new(inner.config.led.clone());
if let Err(e) = sensor.init().await {
@@ -149,19 +128,17 @@ impl AtxController {
}
async fn shutdown_components(inner: &mut AtxInner) {
if let Some(executor) = inner.power_executor.as_mut() {
if let Err(e) = executor.shutdown().await {
warn!("Failed to shutdown power executor: {}", e);
for (slot, label) in [
(&mut inner.power_executor, "power"),
(&mut inner.reset_executor, "reset"),
] {
if let Some(executor) = slot.as_mut() {
if let Err(e) = executor.shutdown().await {
warn!("Failed to shutdown {} executor: {}", label, e);
}
}
*slot = None;
}
inner.power_executor = None;
if let Some(executor) = inner.reset_executor.as_mut() {
if let Err(e) = executor.shutdown().await {
warn!("Failed to shutdown reset executor: {}", e);
}
}
inner.reset_executor = None;
if let Some(sensor) = inner.led_sensor.as_mut() {
if let Err(e) = sensor.shutdown().await {
@@ -171,7 +148,20 @@ impl AtxController {
inner.led_sensor = None;
}
/// Create a new ATX controller with the specified configuration
async fn read_power_status(sensor: Option<&LedSensor>) -> PowerStatus {
let Some(sensor) = sensor else {
return PowerStatus::Unknown;
};
match sensor.read().await {
Ok(status) => status,
Err(e) => {
debug!("Failed to read ATX LED sensor: {}", e);
PowerStatus::Unknown
}
}
}
pub fn new(config: AtxControllerConfig) -> Self {
Self {
inner: RwLock::new(AtxInner {
@@ -183,12 +173,10 @@ impl AtxController {
}
}
/// Create a disabled ATX controller
pub fn disabled() -> Self {
Self::new(AtxControllerConfig::default())
}
/// Initialize the ATX controller and its executors
pub async fn init(&self) -> Result<()> {
let mut inner = self.inner.write().await;
@@ -204,7 +192,6 @@ impl AtxController {
Ok(())
}
/// Reload ATX controller configuration
pub async fn reload(&self, config: AtxControllerConfig) -> Result<()> {
let mut inner = self.inner.write().await;
@@ -225,7 +212,6 @@ impl AtxController {
Ok(())
}
/// Shutdown ATX controller and release all resources
pub async fn shutdown(&self) -> Result<()> {
let mut inner = self.inner.write().await;
Self::shutdown_components(&mut inner).await;
@@ -233,86 +219,48 @@ impl AtxController {
Ok(())
}
/// Trigger a power action (short/long/reset)
pub async fn trigger_power_action(&self, action: AtxAction) -> Result<()> {
let inner = self.inner.read().await;
match action {
AtxAction::Short | AtxAction::Long => {
if let Some(executor) = &inner.power_executor {
let duration = match action {
AtxAction::Short => timing::SHORT_PRESS,
AtxAction::Long => timing::LONG_PRESS,
_ => unreachable!(),
};
executor.pulse(duration).await?;
} else {
return Err(AppError::Config(
"Power button not configured for ATX controller".to_string(),
));
}
}
AtxAction::Reset => {
if let Some(executor) = &inner.reset_executor {
executor.pulse(timing::RESET_PRESS).await?;
} else {
return Err(AppError::Config(
"Reset button not configured for ATX controller".to_string(),
));
}
}
}
let (executor, duration) = match action {
AtxAction::Short => (inner.power_executor.as_ref(), timing::SHORT_PRESS),
AtxAction::Long => (inner.power_executor.as_ref(), timing::LONG_PRESS),
AtxAction::Reset => (inner.reset_executor.as_ref(), timing::RESET_PRESS),
};
let Some(executor) = executor else {
return Err(AppError::Config(match action {
AtxAction::Reset => "Reset button not configured for ATX controller",
_ => "Power button not configured for ATX controller",
}
.to_string()));
};
executor.pulse(duration).await?;
Ok(())
}
/// Trigger a short power button press
pub async fn power_short(&self) -> Result<()> {
self.trigger_power_action(AtxAction::Short).await
}
/// Trigger a long power button press
pub async fn power_long(&self) -> Result<()> {
self.trigger_power_action(AtxAction::Long).await
}
/// Trigger a reset button press
pub async fn reset(&self) -> Result<()> {
self.trigger_power_action(AtxAction::Reset).await
}
/// Get the current power status using the LED sensor (if configured)
pub async fn power_status(&self) -> PowerStatus {
let inner = self.inner.read().await;
if let Some(sensor) = &inner.led_sensor {
match sensor.read().await {
Ok(status) => status,
Err(e) => {
debug!("Failed to read ATX LED sensor: {}", e);
PowerStatus::Unknown
}
}
} else {
PowerStatus::Unknown
}
Self::read_power_status(inner.led_sensor.as_ref()).await
}
/// Get a snapshot of the ATX state for API responses
pub async fn state(&self) -> AtxState {
let inner = self.inner.read().await;
let power_status = if let Some(sensor) = &inner.led_sensor {
match sensor.read().await {
Ok(status) => status,
Err(e) => {
debug!("Failed to read ATX LED sensor: {}", e);
PowerStatus::Unknown
}
}
} else {
PowerStatus::Unknown
};
let power_status = Self::read_power_status(inner.led_sensor.as_ref()).await;
AtxState {
available: inner.config.enabled,