Merge branch 'endrift/steamosctl-cleanup' into 'master'

steamosctl cleanup

See merge request holo/steamos-manager!24
This commit is contained in:
Vicki Pfau 2024-05-15 01:05:17 +00:00
commit 80c598ce68
6 changed files with 243 additions and 151 deletions

View file

@ -9,9 +9,11 @@ use anyhow::Result;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use itertools::Itertools; use itertools::Itertools;
use std::ops::Deref; use std::ops::Deref;
use std::str::FromStr; use steamos_manager::cec::HdmiCecState;
use steamos_manager::hardware::FanControlState;
use steamos_manager::power::GPUPerformanceLevel;
use steamos_manager::proxy::ManagerProxy; use steamos_manager::proxy::ManagerProxy;
use steamos_manager::wifi::WifiBackend; use steamos_manager::wifi::{WifiBackend, WifiDebugMode, WifiPowerManagement};
use zbus::fdo::PropertiesProxy; use zbus::fdo::PropertiesProxy;
use zbus::names::InterfaceName; use zbus::names::InterfaceName;
use zbus::{zvariant, Connection}; use zbus::{zvariant, Connection};
@ -19,98 +21,122 @@ use zbus::{zvariant, Connection};
#[derive(Parser)] #[derive(Parser)]
#[command(version, about, long_about = None)] #[command(version, about, long_about = None)]
struct Args { struct Args {
/// Optionally get all properties
#[arg(short, long)]
all_properties: bool,
#[command(subcommand)] #[command(subcommand)]
command: Option<Commands>, command: Commands,
} }
#[derive(Subcommand)] #[derive(Subcommand)]
enum Commands { enum Commands {
GetAlsCalibrationGain {}, /// Get all properties
GetHardwareCurrentlySupported {}, GetAllProperties,
/// Get luminance sensor calibration gain
GetAlsCalibrationGain,
/// Get if the hardware is currently supported
GetHardwareCurrentlySupported,
/// Set the fan control state
SetFanControlState { SetFanControlState {
// Set the fan control state. /// Valid options are bios, os
// 0 - BIOS, 1 - OS state: FanControlState,
#[arg(short, long)]
value: u32,
}, },
GetFanControlState {}, /// Get the fan control state
GetFanControlState,
/// Set the GPU performance level
SetGPUPerformanceLevel { SetGPUPerformanceLevel {
// Set the gpu performance level /// Valid levels are auto, low, high, manual, peak_performance
// 0 = Auto, 1 = Low, 2 = High, 3 = Manual, 4 = Profile Peak level: GPUPerformanceLevel,
#[arg(short, long)]
value: u32,
}, },
GetGPUPerformanceLevel {}, /// Get the GPU performance level
GetGPUPerformanceLevel,
/// Set the GPU clock value manually. Only works when performance level is set to Manual
SetManualGPUClock { SetManualGPUClock {
// Set the GPU clock value manually /// GPU clock frequency in MHz
// Controls the GPU clock frequency in MHz when GPUPerformanceLevel is set to Manual freq: u32,
#[arg(short, long)]
value: u32,
}, },
GetManualGPUClock {}, /// Get the GPU clock frequency, in MHz. Only works when performance level is set to Manual
GetManualGPUClockMax {}, GetManualGPUClock,
GetManualGPUClockMin {},
/// Get the maximum allowed GPU clock frequency for the Manual performance level
GetManualGPUClockMax,
/// Get the minimum allowed GPU clock frequency for the Manual performance level
GetManualGPUClockMin,
/// Set the TDP limit
SetTDPLimit { SetTDPLimit {
// Set the TDP limit /// TDP limit, in W
#[arg(short, long)] limit: u32,
value: u32,
}, },
GetTDPLimit {}, /// Get the TDP limit
GetTDPLimitMax {}, GetTDPLimit,
GetTDPLimitMin {},
GetVersion {}, /// Get the maximum allowed TDP limit
GetTDPLimitMax,
/// Get the minimum allowed TDP limit
GetTDPLimitMin,
/// Get the current API version
GetVersion,
/// Set the wifi backend if possible
SetWifiBackend { SetWifiBackend {
// Set the wifi backend to given string if possible /// Supported backends are iwd, wpa_supplicant
// Supported values are iwd|wpa_supplicant backend: WifiBackend,
#[arg(short, long)]
backend: String,
}, },
GetWifiBackend {}, /// Get the wifi backend
GetWifiBackend,
/// Set wifi debug mode
SetWifiDebugMode { SetWifiDebugMode {
// Set wifi debug mode to given value /// Valid modes are on, off
// 1 for on, 0 for off currently mode: WifiDebugMode,
#[arg(short, long)] /// The size of the debug buffer, in bytes
mode: u32, #[arg(default_value_t = 20000)]
buffer: u32,
}, },
GetWifiDebugMode {}, /// Get wifi debug mode
GetWifiDebugMode,
/// Set the wifi power management state
SetWifiPowerManagementState { SetWifiPowerManagementState {
// Set the wifi power management state /// Valid modes are enabled, disabled
// 0 - disabled, 1 - enabled state: WifiPowerManagement,
#[arg(short, long)]
value: u32,
}, },
GetWifiPowerManagementState {}, /// Get the wifi power management state
GetWifiPowerManagementState,
GetHdmiCecState {}, /// Get the state of HDMI-CEC support
GetHdmiCecState,
/// Set the state of HDMI-CEC support
SetHdmiCecState { SetHdmiCecState {
// Set the state of HDMI-CEC support /// Valid modes are disabled, control-only, control-and-wake
// 0 - disabled, 1 - only controls, 2 - TV waking state: HdmiCecState,
#[arg(short, long)]
value: u32,
}, },
UpdateBios {}, /// Update the BIOS, if possible
UpdateDock {}, UpdateBios,
TrimDevices {},
FactoryReset {}, /// Update the dock, if possible
UpdateDock,
/// Trim applicable drives
TrimDevices,
/// Factory reset the device
FactoryReset,
} }
#[tokio::main] #[tokio::main]
@ -124,7 +150,9 @@ async fn main() -> Result<()> {
let conn = Connection::session().await?; let conn = Connection::session().await?;
let proxy = ManagerProxy::builder(&conn).build().await?; let proxy = ManagerProxy::builder(&conn).build().await?;
if args.all_properties { // Then process arguments
match &args.command {
Commands::GetAllProperties => {
let properties_proxy = PropertiesProxy::new( let properties_proxy = PropertiesProxy::new(
&conn, &conn,
"com.steampowered.SteamOSManager1", "com.steampowered.SteamOSManager1",
@ -141,112 +169,120 @@ async fn main() -> Result<()> {
println!("{key}: {val}"); println!("{key}: {val}");
} }
} }
Commands::GetAlsCalibrationGain => {
// Then process arguments
match &args.command {
Some(Commands::GetAlsCalibrationGain {}) => {
let gain = proxy.als_calibration_gain().await?; let gain = proxy.als_calibration_gain().await?;
println!("ALS calibration gain: {gain}"); println!("ALS calibration gain: {gain}");
} }
Some(Commands::GetHardwareCurrentlySupported {}) => { Commands::GetHardwareCurrentlySupported => {
let supported = proxy.hardware_currently_supported().await?; let supported = proxy.hardware_currently_supported().await?;
println!("Hardware currently supported: {supported}"); println!("Hardware currently supported: {supported}");
} }
Some(Commands::GetVersion {}) => { Commands::GetVersion => {
let version = proxy.version().await?; let version = proxy.version().await?;
println!("Version: {version}"); println!("Version: {version}");
} }
Some(Commands::SetFanControlState { value }) => { Commands::SetFanControlState { state } => {
proxy.set_fan_control_state(*value).await?; proxy.set_fan_control_state(*state as u32).await?;
} }
Some(Commands::SetGPUPerformanceLevel { value }) => { Commands::GetFanControlState => {
proxy.set_gpu_performance_level(*value).await?; let state = proxy.fan_control_state().await?;
match FanControlState::try_from(state) {
Ok(s) => println!("Fan control state: {}", s.to_string()),
Err(_) => println!("Got unknown value {state} from backend"),
} }
Some(Commands::GetGPUPerformanceLevel {}) => { }
Commands::SetGPUPerformanceLevel { level } => {
proxy.set_gpu_performance_level(*level as u32).await?;
}
Commands::GetGPUPerformanceLevel => {
let level = proxy.gpu_performance_level().await?; let level = proxy.gpu_performance_level().await?;
println!("GPU performance level: {level}"); match GPUPerformanceLevel::try_from(level) {
Ok(l) => println!("GPU performance level: {}", l.to_string()),
Err(_) => println!("Got unknown value {level} from backend"),
} }
Some(Commands::SetManualGPUClock { value }) => {
proxy.set_manual_gpu_clock(*value).await?;
} }
Some(Commands::GetManualGPUClock {}) => { Commands::SetManualGPUClock { freq } => {
proxy.set_manual_gpu_clock(*freq).await?;
}
Commands::GetManualGPUClock => {
let clock = proxy.manual_gpu_clock().await?; let clock = proxy.manual_gpu_clock().await?;
println!("Manual GPU Clock: {clock}"); println!("Manual GPU Clock: {clock}");
} }
Some(Commands::GetManualGPUClockMax {}) => { Commands::GetManualGPUClockMax => {
let value = proxy.manual_gpu_clock_max().await?; let value = proxy.manual_gpu_clock_max().await?;
println!("Manual GPU Clock Max: {value}"); println!("Manual GPU Clock Max: {value}");
} }
Some(Commands::GetManualGPUClockMin {}) => { Commands::GetManualGPUClockMin => {
let value = proxy.manual_gpu_clock_min().await?; let value = proxy.manual_gpu_clock_min().await?;
println!("Manual GPU Clock Min: {value}"); println!("Manual GPU Clock Min: {value}");
} }
Some(Commands::SetTDPLimit { value }) => { Commands::SetTDPLimit { limit } => {
proxy.set_tdp_limit(*value).await?; proxy.set_tdp_limit(*limit).await?;
} }
Some(Commands::GetTDPLimit {}) => { Commands::GetTDPLimit => {
let limit = proxy.tdp_limit().await?; let limit = proxy.tdp_limit().await?;
println!("TDP limit: {limit}"); println!("TDP limit: {limit}");
} }
Some(Commands::GetFanControlState {}) => { Commands::GetTDPLimitMax => {
let state = proxy.fan_control_state().await?;
println!("Fan control state: {state}");
}
Some(Commands::GetTDPLimitMax {}) => {
let value = proxy.tdp_limit_max().await?; let value = proxy.tdp_limit_max().await?;
println!("TDP limit max: {value}"); println!("TDP limit max: {value}");
} }
Some(Commands::GetTDPLimitMin {}) => { Commands::GetTDPLimitMin => {
let value = proxy.tdp_limit_min().await?; let value = proxy.tdp_limit_min().await?;
println!("TDP limit min: {value}"); println!("TDP limit min: {value}");
} }
Some(Commands::SetWifiBackend { backend }) => match WifiBackend::from_str(backend) { Commands::SetWifiBackend { backend } => {
Ok(b) => { proxy.set_wifi_backend(*backend as u32).await?;
proxy.set_wifi_backend(b as u32).await?;
}
Err(_) => {
println!("Unknown wifi backend {backend}");
}
}, },
Some(Commands::GetWifiBackend {}) => { Commands::GetWifiBackend => {
let backend = proxy.wifi_backend().await?; let backend = proxy.wifi_backend().await?;
let backend_string = WifiBackend::try_from(backend).unwrap().to_string(); match WifiBackend::try_from(backend) {
println!("Wifi backend: {backend_string}"); Ok(be) => println!("Wifi backend: {}", be.to_string()),
Err(_) => println!("Got unknown value {backend} from backend"),
} }
Some(Commands::SetWifiDebugMode { mode }) => {
proxy.set_wifi_debug_mode(*mode, 20000).await?;
} }
Some(Commands::GetWifiDebugMode {}) => { Commands::SetWifiDebugMode { mode, buffer } => {
proxy.set_wifi_debug_mode(*mode as u32, *buffer).await?;
}
Commands::GetWifiDebugMode => {
let mode = proxy.wifi_debug_mode_state().await?; let mode = proxy.wifi_debug_mode_state().await?;
println!("Wifi debug mode: {mode}"); match WifiDebugMode::try_from(mode) {
Ok(m) => println!("Wifi debug mode: {}", m.to_string()),
Err(_) => println!("Got unknown value {mode} from backend"),
} }
Some(Commands::SetWifiPowerManagementState { value }) => {
proxy.set_wifi_power_management_state(*value).await?;
} }
Some(Commands::GetWifiPowerManagementState {}) => { Commands::SetWifiPowerManagementState { state } => {
proxy.set_wifi_power_management_state(*state as u32).await?;
}
Commands::GetWifiPowerManagementState => {
let state = proxy.wifi_power_management_state().await?; let state = proxy.wifi_power_management_state().await?;
println!("Wifi power management state: {state}"); match WifiPowerManagement::try_from(state) {
Ok(s) => println!("Wifi power management state: {}", s.to_string()),
Err(_) => println!("Got unknown value {state} from backend"),
} }
Some(Commands::SetHdmiCecState { value }) => {
proxy.set_hdmi_cec_state(*value).await?;
} }
Some(Commands::GetHdmiCecState {}) => { Commands::SetHdmiCecState { state } => {
proxy.set_hdmi_cec_state(*state as u32).await?;
}
Commands::GetHdmiCecState => {
let state = proxy.hdmi_cec_state().await?; let state = proxy.hdmi_cec_state().await?;
println!("HDMI-CEC state: {state}"); match HdmiCecState::try_from(state) {
Ok(s) => println!("HDMI-CEC state: {}", s.to_human_readable()),
Err(_) => println!("Got unknown value {state} from backend"),
} }
Some(Commands::UpdateBios {}) => { }
Commands::UpdateBios => {
let _ = proxy.update_bios().await?; let _ = proxy.update_bios().await?;
} }
Some(Commands::UpdateDock {}) => { Commands::UpdateDock => {
let _ = proxy.update_dock().await?; let _ = proxy.update_dock().await?;
} }
Some(Commands::FactoryReset {}) => { Commands::FactoryReset => {
let _ = proxy.prepare_factory_reset().await?; let _ = proxy.prepare_factory_reset().await?;
} }
Some(Commands::TrimDevices {}) => { Commands::TrimDevices => {
let _ = proxy.trim_devices().await?; let _ = proxy.trim_devices().await?;
} }
None => {}
} }
Ok(()) Ok(())

View file

@ -6,8 +6,9 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
use anyhow::Result; use anyhow::{bail, Error, Result};
use std::fmt; use std::fmt;
use std::str::FromStr;
use zbus::Connection; use zbus::Connection;
use crate::systemd::{daemon_reload, EnableState, SystemdUnit}; use crate::systemd::{daemon_reload, EnableState, SystemdUnit};
@ -31,6 +32,18 @@ impl TryFrom<u32> for HdmiCecState {
} }
} }
impl FromStr for HdmiCecState {
type Err = Error;
fn from_str(input: &str) -> Result<HdmiCecState, Self::Err> {
Ok(match input {
"disable" | "disabled" | "off" => HdmiCecState::Disabled,
"control-only" | "ControlOnly" => HdmiCecState::ControlOnly,
"control-wake" | "control-and-wake" | "ControlAndWake" => HdmiCecState::ControlAndWake,
v => bail!("No enum match for value {v}"),
})
}
}
impl fmt::Display for HdmiCecState { impl fmt::Display for HdmiCecState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
@ -41,7 +54,17 @@ impl fmt::Display for HdmiCecState {
} }
} }
pub struct HdmiCecControl<'dbus> { impl HdmiCecState {
pub fn to_human_readable(&self) -> &'static str {
match self {
HdmiCecState::Disabled => "disabled",
HdmiCecState::ControlOnly => "control-only",
HdmiCecState::ControlAndWake => "control-and-wake",
}
}
}
pub(crate) struct HdmiCecControl<'dbus> {
plasma_rc_unit: SystemdUnit<'dbus>, plasma_rc_unit: SystemdUnit<'dbus>,
wakehook_unit: SystemdUnit<'dbus>, wakehook_unit: SystemdUnit<'dbus>,
connection: Connection, connection: Connection,

View file

@ -5,7 +5,7 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
use anyhow::{Error, Result}; use anyhow::{bail, Error, Result};
use std::fmt; use std::fmt;
use std::str::FromStr; use std::str::FromStr;
use tokio::fs; use tokio::fs;
@ -19,7 +19,7 @@ const BOARD_VENDOR_PATH: &str = "/sys/class/dmi/id/board_vendor";
const BOARD_NAME_PATH: &str = "/sys/class/dmi/id/board_name"; const BOARD_NAME_PATH: &str = "/sys/class/dmi/id/board_name";
#[derive(PartialEq, Debug, Copy, Clone)] #[derive(PartialEq, Debug, Copy, Clone)]
pub enum HardwareVariant { pub(crate) enum HardwareVariant {
Unknown, Unknown,
Jupiter, Jupiter,
Galileo, Galileo,
@ -27,7 +27,7 @@ pub enum HardwareVariant {
#[derive(PartialEq, Debug, Copy, Clone)] #[derive(PartialEq, Debug, Copy, Clone)]
#[repr(u32)] #[repr(u32)]
pub enum HardwareCurrentlySupported { pub(crate) enum HardwareCurrentlySupported {
Unsupported = 0, Unsupported = 0,
Supported = 1, Supported = 1,
} }
@ -85,6 +85,17 @@ impl TryFrom<u32> for FanControlState {
} }
} }
impl FromStr for FanControlState {
type Err = Error;
fn from_str(input: &str) -> Result<FanControlState, Self::Err> {
Ok(match input.to_lowercase().as_str() {
"bios" => FanControlState::Bios,
"os" => FanControlState::Os,
v => bail!("No enum match for value {v}"),
})
}
}
impl fmt::Display for FanControlState { impl fmt::Display for FanControlState {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
@ -94,7 +105,7 @@ impl fmt::Display for FanControlState {
} }
} }
pub async fn variant() -> Result<HardwareVariant> { pub(crate) async fn variant() -> Result<HardwareVariant> {
let board_vendor = fs::read_to_string(path(BOARD_VENDOR_PATH)).await?; let board_vendor = fs::read_to_string(path(BOARD_VENDOR_PATH)).await?;
if board_vendor.trim_end() != "Valve" { if board_vendor.trim_end() != "Valve" {
return Ok(HardwareVariant::Unknown); return Ok(HardwareVariant::Unknown);
@ -104,7 +115,7 @@ pub async fn variant() -> Result<HardwareVariant> {
HardwareVariant::from_str(board_name.trim_end()) HardwareVariant::from_str(board_name.trim_end())
} }
pub async fn check_support() -> Result<HardwareCurrentlySupported> { pub(crate) async fn check_support() -> Result<HardwareCurrentlySupported> {
// Run jupiter-check-support note this script does exit 1 for "Support: No" case // Run jupiter-check-support note this script does exit 1 for "Support: No" case
// so no need to parse output, etc. // so no need to parse output, etc.
let res = script_exit_code("/usr/bin/jupiter-check-support", &[] as &[String; 0]).await?; let res = script_exit_code("/usr/bin/jupiter-check-support", &[] as &[String; 0]).await?;
@ -115,7 +126,7 @@ pub async fn check_support() -> Result<HardwareCurrentlySupported> {
}) })
} }
pub struct FanControl { pub(crate) struct FanControl {
connection: Connection, connection: Connection,
} }

View file

@ -14,17 +14,17 @@ use tokio::signal::unix::{signal, SignalKind};
use tokio_util::sync::CancellationToken; use tokio_util::sync::CancellationToken;
use tracing::{info, warn}; use tracing::{info, warn};
mod cec;
mod ds_inhibit; mod ds_inhibit;
mod error; mod error;
mod hardware;
mod manager; mod manager;
mod power;
mod process; mod process;
mod sls; mod sls;
mod systemd; mod systemd;
pub mod cec;
pub mod daemon; pub mod daemon;
pub mod hardware;
pub mod power;
pub mod proxy; pub mod proxy;
pub mod wifi; pub mod wifi;

View file

@ -5,7 +5,7 @@
* SPDX-License-Identifier: MIT * SPDX-License-Identifier: MIT
*/ */
use anyhow::{anyhow, bail, ensure, Error, Result}; use anyhow::{bail, ensure, Error, Result};
use std::path::PathBuf; use std::path::PathBuf;
use std::str::FromStr; use std::str::FromStr;
use tokio::fs::{self, File}; use tokio::fs::{self, File};
@ -52,14 +52,14 @@ impl TryFrom<u32> for GPUPerformanceLevel {
impl FromStr for GPUPerformanceLevel { impl FromStr for GPUPerformanceLevel {
type Err = Error; type Err = Error;
fn from_str(input: &str) -> Result<GPUPerformanceLevel, Self::Err> { fn from_str(input: &str) -> Result<GPUPerformanceLevel, Self::Err> {
match input { Ok(match input {
"auto" => Ok(GPUPerformanceLevel::Auto), "auto" => GPUPerformanceLevel::Auto,
"low" => Ok(GPUPerformanceLevel::Low), "low" => GPUPerformanceLevel::Low,
"high" => Ok(GPUPerformanceLevel::High), "high" => GPUPerformanceLevel::High,
"manual" => Ok(GPUPerformanceLevel::Manual), "manual" => GPUPerformanceLevel::Manual,
"peak_performance" => Ok(GPUPerformanceLevel::ProfilePeak), "peak_performance" => GPUPerformanceLevel::ProfilePeak,
v => Err(anyhow!("No enum match for value {v}")), v => bail!("No enum match for value {v}"),
} })
} }
} }
@ -75,7 +75,7 @@ impl ToString for GPUPerformanceLevel {
} }
} }
pub async fn get_gpu_performance_level() -> Result<GPUPerformanceLevel> { pub(crate) async fn get_gpu_performance_level() -> Result<GPUPerformanceLevel> {
let base = find_hwmon().await?; let base = find_hwmon().await?;
let level = fs::read_to_string(base.join(GPU_PERFORMANCE_LEVEL_SUFFIX)) let level = fs::read_to_string(base.join(GPU_PERFORMANCE_LEVEL_SUFFIX))
.await .await
@ -84,7 +84,7 @@ pub async fn get_gpu_performance_level() -> Result<GPUPerformanceLevel> {
GPUPerformanceLevel::from_str(level.trim()) GPUPerformanceLevel::from_str(level.trim())
} }
pub async fn set_gpu_performance_level(level: GPUPerformanceLevel) -> Result<()> { pub(crate) async fn set_gpu_performance_level(level: GPUPerformanceLevel) -> Result<()> {
let level: String = level.to_string(); let level: String = level.to_string();
let base = find_hwmon().await?; let base = find_hwmon().await?;
write_synced(base.join(GPU_PERFORMANCE_LEVEL_SUFFIX), level.as_bytes()) write_synced(base.join(GPU_PERFORMANCE_LEVEL_SUFFIX), level.as_bytes())
@ -92,7 +92,7 @@ pub async fn set_gpu_performance_level(level: GPUPerformanceLevel) -> Result<()>
.inspect_err(|message| error!("Error writing to sysfs file: {message}")) .inspect_err(|message| error!("Error writing to sysfs file: {message}"))
} }
pub async fn set_gpu_clocks(clocks: u32) -> Result<()> { pub(crate) async fn set_gpu_clocks(clocks: u32) -> Result<()> {
// Set GPU clocks to given value valid between 200 - 1600 // Set GPU clocks to given value valid between 200 - 1600
// Only used when GPU Performance Level is manual, but write whenever called. // Only used when GPU Performance Level is manual, but write whenever called.
ensure!((200..=1600).contains(&clocks), "Invalid clocks"); ensure!((200..=1600).contains(&clocks), "Invalid clocks");
@ -125,7 +125,7 @@ pub async fn set_gpu_clocks(clocks: u32) -> Result<()> {
Ok(()) Ok(())
} }
pub async fn get_gpu_clocks() -> Result<u32> { pub(crate) async fn get_gpu_clocks() -> Result<u32> {
let base = find_hwmon().await?; let base = find_hwmon().await?;
let clocks_file = File::open(base.join(GPU_CLOCKS_SUFFIX)).await?; let clocks_file = File::open(base.join(GPU_CLOCKS_SUFFIX)).await?;
let mut reader = BufReader::new(clocks_file); let mut reader = BufReader::new(clocks_file);
@ -170,14 +170,14 @@ async fn find_hwmon() -> Result<PathBuf> {
} }
} }
pub async fn get_tdp_limit() -> Result<u32> { pub(crate) async fn get_tdp_limit() -> Result<u32> {
let base = find_hwmon().await?; let base = find_hwmon().await?;
let power1cap = fs::read_to_string(base.join(TDP_LIMIT1)).await?; let power1cap = fs::read_to_string(base.join(TDP_LIMIT1)).await?;
let power1cap: u32 = power1cap.trim_end().parse()?; let power1cap: u32 = power1cap.trim_end().parse()?;
Ok(power1cap / 1000000) Ok(power1cap / 1000000)
} }
pub async fn set_tdp_limit(limit: u32) -> Result<()> { pub(crate) async fn set_tdp_limit(limit: u32) -> Result<()> {
// Set TDP limit given if within range (3-15) // Set TDP limit given if within range (3-15)
// Returns false on error or out of range // Returns false on error or out of range
ensure!((3..=15).contains(&limit), "Invalid limit"); ensure!((3..=15).contains(&limit), "Invalid limit");
@ -201,7 +201,7 @@ pub async fn set_tdp_limit(limit: u32) -> Result<()> {
} }
#[cfg(test)] #[cfg(test)]
pub mod test { pub(crate) mod test {
use super::*; use super::*;
use crate::testing; use crate::testing;
use anyhow::anyhow; use anyhow::anyhow;

View file

@ -64,6 +64,17 @@ impl TryFrom<u32> for WifiDebugMode {
} }
} }
impl FromStr for WifiDebugMode {
type Err = Error;
fn from_str(input: &str) -> Result<WifiDebugMode, Self::Err> {
Ok(match input {
"enable" | "enabled" | "on" | "1" => WifiDebugMode::On,
"disable" | "disabled" | "off" | "0" => WifiDebugMode::Off,
v => bail!("No enum match for value {v}"),
})
}
}
impl fmt::Display for WifiDebugMode { impl fmt::Display for WifiDebugMode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {
@ -84,6 +95,17 @@ impl TryFrom<u32> for WifiPowerManagement {
} }
} }
impl FromStr for WifiPowerManagement {
type Err = Error;
fn from_str(input: &str) -> Result<WifiPowerManagement, Self::Err> {
Ok(match input {
"enable" | "enabled" | "on" | "1" => WifiPowerManagement::Enabled,
"disable" | "disabled" | "off" | "0" => WifiPowerManagement::Disabled,
v => bail!("No enum match for value {v}"),
})
}
}
impl fmt::Display for WifiPowerManagement { impl fmt::Display for WifiPowerManagement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self { match self {