From bfcdf963015ea45844820f471f77082942d1a995 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 10 May 2024 17:10:43 -0700 Subject: [PATCH 01/11] steamosctl: Fix up documentation and remove extraneous flag syntax --- src/bin/steamosctl.rs | 110 +++++++++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 43 deletions(-) diff --git a/src/bin/steamosctl.rs b/src/bin/steamosctl.rs index 4454901..76cedf2 100644 --- a/src/bin/steamosctl.rs +++ b/src/bin/steamosctl.rs @@ -28,88 +28,112 @@ struct Args { #[derive(Subcommand)] enum Commands { + /// Get luminance sensor calibration gain GetAlsCalibrationGain {}, + + /// Get if the hardware is currently supported GetHardwareCurrentlySupported {}, + /// Set the fan control state SetFanControlState { - // Set the fan control state. - // 0 - BIOS, 1 - OS - #[arg(short, long)] - value: u32, + /// 0 - BIOS, 1 - OS + state: u32, }, + /// Get the fan control state GetFanControlState {}, + /// Set the GPU performance level SetGPUPerformanceLevel { - // Set the gpu performance level - // 0 = Auto, 1 = Low, 2 = High, 3 = Manual, 4 = Profile Peak - #[arg(short, long)] - value: u32, + /// 0 = Auto, 1 = Low, 2 = High, 3 = Manual, 4 = Profile Peak + level: u32, }, + /// Get the GPU performance level GetGPUPerformanceLevel {}, + /// Set the GPU clock value manually. Only works when performance level is set to Manual SetManualGPUClock { - // Set the GPU clock value manually - // Controls the GPU clock frequency in MHz when GPUPerformanceLevel is set to Manual - #[arg(short, long)] - value: u32, + /// GPU clock frequency in MHz + freq: u32, }, + /// Get the GPU clock frequency, in MHz. Only works when performance level is set to Manual GetManualGPUClock {}, + + /// 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 { - // Set the TDP limit - #[arg(short, long)] - value: u32, + /// TDP limit, in W + limit: u32, }, + /// Get the TDP limit GetTDPLimit {}, + + /// 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 { - // Set the wifi backend to given string if possible - // Supported values are iwd|wpa_supplicant - #[arg(short, long)] + /// Supported backends are iwd, wpa_supplicant backend: String, }, + /// Get the wifi backend GetWifiBackend {}, + /// Set wifi debug mode SetWifiDebugMode { - // Set wifi debug mode to given value - // 1 for on, 0 for off currently - #[arg(short, long)] + /// 1 for on, 0 for off mode: u32, + /// The size of the debug buffer, in bytes + #[arg(default_value_t = 20000)] + buffer: u32, }, + /// Get wifi debug mode GetWifiDebugMode {}, + /// Set the wifi power management state SetWifiPowerManagementState { - // Set the wifi power management state - // 0 - disabled, 1 - enabled - #[arg(short, long)] - value: u32, + /// 0 - disabled, 1 - enabled + state: u32, }, + /// Get the wifi power management state GetWifiPowerManagementState {}, + /// Get the state of HDMI-CEC support GetHdmiCecState {}, + + /// Set the state of HDMI-CEC support SetHdmiCecState { - // Set the state of HDMI-CEC support - // 0 - disabled, 1 - only controls, 2 - TV waking - #[arg(short, long)] - value: u32, + /// 0 - disabled, 1 - only controls, 2 - Controls and TV waking + state: u32, }, + /// Update the BIOS, if possible UpdateBios {}, + + /// Update the dock, if possible UpdateDock {}, + + /// Trim applicable drives TrimDevices {}, + + /// Factory reset the device FactoryReset {}, } @@ -156,18 +180,18 @@ async fn main() -> Result<()> { let version = proxy.version().await?; println!("Version: {version}"); } - Some(Commands::SetFanControlState { value }) => { - proxy.set_fan_control_state(*value).await?; + Some(Commands::SetFanControlState { state }) => { + proxy.set_fan_control_state(*state).await?; } - Some(Commands::SetGPUPerformanceLevel { value }) => { - proxy.set_gpu_performance_level(*value).await?; + Some(Commands::SetGPUPerformanceLevel { level }) => { + proxy.set_gpu_performance_level(*level).await?; } Some(Commands::GetGPUPerformanceLevel {}) => { let level = proxy.gpu_performance_level().await?; println!("GPU performance level: {level}"); } - Some(Commands::SetManualGPUClock { value }) => { - proxy.set_manual_gpu_clock(*value).await?; + Some(Commands::SetManualGPUClock { freq }) => { + proxy.set_manual_gpu_clock(*freq).await?; } Some(Commands::GetManualGPUClock {}) => { let clock = proxy.manual_gpu_clock().await?; @@ -181,8 +205,8 @@ async fn main() -> Result<()> { let value = proxy.manual_gpu_clock_min().await?; println!("Manual GPU Clock Min: {value}"); } - Some(Commands::SetTDPLimit { value }) => { - proxy.set_tdp_limit(*value).await?; + Some(Commands::SetTDPLimit { limit }) => { + proxy.set_tdp_limit(*limit).await?; } Some(Commands::GetTDPLimit {}) => { let limit = proxy.tdp_limit().await?; @@ -213,22 +237,22 @@ async fn main() -> Result<()> { let backend_string = WifiBackend::try_from(backend).unwrap().to_string(); println!("Wifi backend: {backend_string}"); } - Some(Commands::SetWifiDebugMode { mode }) => { - proxy.set_wifi_debug_mode(*mode, 20000).await?; + Some(Commands::SetWifiDebugMode { mode, buffer }) => { + proxy.set_wifi_debug_mode(*mode, *buffer).await?; } Some(Commands::GetWifiDebugMode {}) => { let mode = proxy.wifi_debug_mode_state().await?; println!("Wifi debug mode: {mode}"); } - Some(Commands::SetWifiPowerManagementState { value }) => { - proxy.set_wifi_power_management_state(*value).await?; + Some(Commands::SetWifiPowerManagementState { state }) => { + proxy.set_wifi_power_management_state(*state).await?; } Some(Commands::GetWifiPowerManagementState {}) => { let state = proxy.wifi_power_management_state().await?; println!("Wifi power management state: {state}"); } - Some(Commands::SetHdmiCecState { value }) => { - proxy.set_hdmi_cec_state(*value).await?; + Some(Commands::SetHdmiCecState { state }) => { + proxy.set_hdmi_cec_state(*state).await?; } Some(Commands::GetHdmiCecState {}) => { let state = proxy.hdmi_cec_state().await?; From 01b50984a4dea7a53542c02cc48605d79f40c22e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 10 May 2024 17:18:45 -0700 Subject: [PATCH 02/11] steamosctl: Remove unneeded empty variants --- src/bin/steamosctl.rs | 76 +++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/bin/steamosctl.rs b/src/bin/steamosctl.rs index 76cedf2..c9fe436 100644 --- a/src/bin/steamosctl.rs +++ b/src/bin/steamosctl.rs @@ -29,10 +29,10 @@ struct Args { #[derive(Subcommand)] enum Commands { /// Get luminance sensor calibration gain - GetAlsCalibrationGain {}, + GetAlsCalibrationGain, /// Get if the hardware is currently supported - GetHardwareCurrentlySupported {}, + GetHardwareCurrentlySupported, /// Set the fan control state SetFanControlState { @@ -41,7 +41,7 @@ enum Commands { }, /// Get the fan control state - GetFanControlState {}, + GetFanControlState, /// Set the GPU performance level SetGPUPerformanceLevel { @@ -50,7 +50,7 @@ enum Commands { }, /// Get the GPU performance level - GetGPUPerformanceLevel {}, + GetGPUPerformanceLevel, /// Set the GPU clock value manually. Only works when performance level is set to Manual SetManualGPUClock { @@ -59,13 +59,13 @@ enum Commands { }, /// Get the GPU clock frequency, in MHz. Only works when performance level is set to Manual - GetManualGPUClock {}, + GetManualGPUClock, /// Get the maximum allowed GPU clock frequency for the Manual performance level - GetManualGPUClockMax {}, + GetManualGPUClockMax, /// Get the minimum allowed GPU clock frequency for the Manual performance level - GetManualGPUClockMin {}, + GetManualGPUClockMin, /// Set the TDP limit SetTDPLimit { @@ -74,16 +74,16 @@ enum Commands { }, /// Get the TDP limit - GetTDPLimit {}, + GetTDPLimit, /// Get the maximum allowed TDP limit - GetTDPLimitMax {}, + GetTDPLimitMax, /// Get the minimum allowed TDP limit - GetTDPLimitMin {}, + GetTDPLimitMin, /// Get the current API version - GetVersion {}, + GetVersion, /// Set the wifi backend if possible SetWifiBackend { @@ -92,7 +92,7 @@ enum Commands { }, /// Get the wifi backend - GetWifiBackend {}, + GetWifiBackend, /// Set wifi debug mode SetWifiDebugMode { @@ -104,7 +104,7 @@ enum Commands { }, /// Get wifi debug mode - GetWifiDebugMode {}, + GetWifiDebugMode, /// Set the wifi power management state SetWifiPowerManagementState { @@ -113,10 +113,10 @@ enum Commands { }, /// Get the wifi power management state - GetWifiPowerManagementState {}, + GetWifiPowerManagementState, /// Get the state of HDMI-CEC support - GetHdmiCecState {}, + GetHdmiCecState, /// Set the state of HDMI-CEC support SetHdmiCecState { @@ -125,16 +125,16 @@ enum Commands { }, /// Update the BIOS, if possible - UpdateBios {}, + UpdateBios, /// Update the dock, if possible - UpdateDock {}, + UpdateDock, /// Trim applicable drives - TrimDevices {}, + TrimDevices, /// Factory reset the device - FactoryReset {}, + FactoryReset, } #[tokio::main] @@ -168,15 +168,15 @@ async fn main() -> Result<()> { // Then process arguments match &args.command { - Some(Commands::GetAlsCalibrationGain {}) => { + Some(Commands::GetAlsCalibrationGain) => { let gain = proxy.als_calibration_gain().await?; println!("ALS calibration gain: {gain}"); } - Some(Commands::GetHardwareCurrentlySupported {}) => { + Some(Commands::GetHardwareCurrentlySupported) => { let supported = proxy.hardware_currently_supported().await?; println!("Hardware currently supported: {supported}"); } - Some(Commands::GetVersion {}) => { + Some(Commands::GetVersion) => { let version = proxy.version().await?; println!("Version: {version}"); } @@ -186,41 +186,41 @@ async fn main() -> Result<()> { Some(Commands::SetGPUPerformanceLevel { level }) => { proxy.set_gpu_performance_level(*level).await?; } - Some(Commands::GetGPUPerformanceLevel {}) => { + Some(Commands::GetGPUPerformanceLevel) => { let level = proxy.gpu_performance_level().await?; println!("GPU performance level: {level}"); } Some(Commands::SetManualGPUClock { freq }) => { proxy.set_manual_gpu_clock(*freq).await?; } - Some(Commands::GetManualGPUClock {}) => { + Some(Commands::GetManualGPUClock) => { let clock = proxy.manual_gpu_clock().await?; println!("Manual GPU Clock: {clock}"); } - Some(Commands::GetManualGPUClockMax {}) => { + Some(Commands::GetManualGPUClockMax) => { let value = proxy.manual_gpu_clock_max().await?; println!("Manual GPU Clock Max: {value}"); } - Some(Commands::GetManualGPUClockMin {}) => { + Some(Commands::GetManualGPUClockMin) => { let value = proxy.manual_gpu_clock_min().await?; println!("Manual GPU Clock Min: {value}"); } Some(Commands::SetTDPLimit { limit }) => { proxy.set_tdp_limit(*limit).await?; } - Some(Commands::GetTDPLimit {}) => { + Some(Commands::GetTDPLimit) => { let limit = proxy.tdp_limit().await?; println!("TDP limit: {limit}"); } - Some(Commands::GetFanControlState {}) => { + Some(Commands::GetFanControlState) => { let state = proxy.fan_control_state().await?; println!("Fan control state: {state}"); } - Some(Commands::GetTDPLimitMax {}) => { + Some(Commands::GetTDPLimitMax) => { let value = proxy.tdp_limit_max().await?; println!("TDP limit max: {value}"); } - Some(Commands::GetTDPLimitMin {}) => { + Some(Commands::GetTDPLimitMin) => { let value = proxy.tdp_limit_min().await?; println!("TDP limit min: {value}"); } @@ -232,7 +232,7 @@ async fn main() -> Result<()> { println!("Unknown wifi backend {backend}"); } }, - Some(Commands::GetWifiBackend {}) => { + Some(Commands::GetWifiBackend) => { let backend = proxy.wifi_backend().await?; let backend_string = WifiBackend::try_from(backend).unwrap().to_string(); println!("Wifi backend: {backend_string}"); @@ -240,34 +240,34 @@ async fn main() -> Result<()> { Some(Commands::SetWifiDebugMode { mode, buffer }) => { proxy.set_wifi_debug_mode(*mode, *buffer).await?; } - Some(Commands::GetWifiDebugMode {}) => { + Some(Commands::GetWifiDebugMode) => { let mode = proxy.wifi_debug_mode_state().await?; println!("Wifi debug mode: {mode}"); } Some(Commands::SetWifiPowerManagementState { state }) => { proxy.set_wifi_power_management_state(*state).await?; } - Some(Commands::GetWifiPowerManagementState {}) => { + Some(Commands::GetWifiPowerManagementState) => { let state = proxy.wifi_power_management_state().await?; println!("Wifi power management state: {state}"); } Some(Commands::SetHdmiCecState { state }) => { proxy.set_hdmi_cec_state(*state).await?; } - Some(Commands::GetHdmiCecState {}) => { + Some(Commands::GetHdmiCecState) => { let state = proxy.hdmi_cec_state().await?; println!("HDMI-CEC state: {state}"); } - Some(Commands::UpdateBios {}) => { + Some(Commands::UpdateBios) => { let _ = proxy.update_bios().await?; } - Some(Commands::UpdateDock {}) => { + Some(Commands::UpdateDock) => { let _ = proxy.update_dock().await?; } - Some(Commands::FactoryReset {}) => { + Some(Commands::FactoryReset) => { let _ = proxy.prepare_factory_reset().await?; } - Some(Commands::TrimDevices {}) => { + Some(Commands::TrimDevices) => { let _ = proxy.trim_devices().await?; } None => {} From fa80c861ad2ded00dbe424d0ce0ad6d748aaa35e Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 10 May 2024 17:23:47 -0700 Subject: [PATCH 03/11] steamosctl: Make -a into get-all-properties command instead of a flag --- src/bin/steamosctl.rs | 98 +++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/src/bin/steamosctl.rs b/src/bin/steamosctl.rs index c9fe436..cf75a21 100644 --- a/src/bin/steamosctl.rs +++ b/src/bin/steamosctl.rs @@ -19,15 +19,15 @@ use zbus::{zvariant, Connection}; #[derive(Parser)] #[command(version, about, long_about = None)] struct Args { - /// Optionally get all properties - #[arg(short, long)] - all_properties: bool, #[command(subcommand)] - command: Option, + command: Commands, } #[derive(Subcommand)] enum Commands { + /// Get all properties + GetAllProperties, + /// Get luminance sensor calibration gain GetAlsCalibrationGain, @@ -148,83 +148,82 @@ async fn main() -> Result<()> { let conn = Connection::session().await?; let proxy = ManagerProxy::builder(&conn).build().await?; - if args.all_properties { - let properties_proxy = PropertiesProxy::new( - &conn, - "com.steampowered.SteamOSManager1", - "/com/steampowered/SteamOSManager1", - ) - .await?; - let name = InterfaceName::try_from("com.steampowered.SteamOSManager1.Manager")?; - let properties = properties_proxy - .get_all(zvariant::Optional::from(Some(name))) - .await?; - for key in properties.keys().sorted() { - let value = &properties[key]; - let val = value.deref(); - println!("{key}: {val}"); - } - } - // Then process arguments match &args.command { - Some(Commands::GetAlsCalibrationGain) => { + Commands::GetAllProperties => { + let properties_proxy = PropertiesProxy::new( + &conn, + "com.steampowered.SteamOSManager1", + "/com/steampowered/SteamOSManager1", + ) + .await?; + let name = InterfaceName::try_from("com.steampowered.SteamOSManager1.Manager")?; + let properties = properties_proxy + .get_all(zvariant::Optional::from(Some(name))) + .await?; + for key in properties.keys().sorted() { + let value = &properties[key]; + let val = value.deref(); + println!("{key}: {val}"); + } + } + Commands::GetAlsCalibrationGain => { let gain = proxy.als_calibration_gain().await?; println!("ALS calibration gain: {gain}"); } - Some(Commands::GetHardwareCurrentlySupported) => { + Commands::GetHardwareCurrentlySupported => { let supported = proxy.hardware_currently_supported().await?; println!("Hardware currently supported: {supported}"); } - Some(Commands::GetVersion) => { + Commands::GetVersion => { let version = proxy.version().await?; println!("Version: {version}"); } - Some(Commands::SetFanControlState { state }) => { + Commands::SetFanControlState { state } => { proxy.set_fan_control_state(*state).await?; } - Some(Commands::SetGPUPerformanceLevel { level }) => { + Commands::SetGPUPerformanceLevel { level } => { proxy.set_gpu_performance_level(*level).await?; } - Some(Commands::GetGPUPerformanceLevel) => { + Commands::GetGPUPerformanceLevel => { let level = proxy.gpu_performance_level().await?; println!("GPU performance level: {level}"); } - Some(Commands::SetManualGPUClock { freq }) => { + Commands::SetManualGPUClock { freq } => { proxy.set_manual_gpu_clock(*freq).await?; } - Some(Commands::GetManualGPUClock) => { + Commands::GetManualGPUClock => { let clock = proxy.manual_gpu_clock().await?; println!("Manual GPU Clock: {clock}"); } - Some(Commands::GetManualGPUClockMax) => { + Commands::GetManualGPUClockMax => { let value = proxy.manual_gpu_clock_max().await?; println!("Manual GPU Clock Max: {value}"); } - Some(Commands::GetManualGPUClockMin) => { + Commands::GetManualGPUClockMin => { let value = proxy.manual_gpu_clock_min().await?; println!("Manual GPU Clock Min: {value}"); } - Some(Commands::SetTDPLimit { limit }) => { + Commands::SetTDPLimit { limit } => { proxy.set_tdp_limit(*limit).await?; } - Some(Commands::GetTDPLimit) => { + Commands::GetTDPLimit => { let limit = proxy.tdp_limit().await?; println!("TDP limit: {limit}"); } - Some(Commands::GetFanControlState) => { + Commands::GetFanControlState => { let state = proxy.fan_control_state().await?; println!("Fan control state: {state}"); } - Some(Commands::GetTDPLimitMax) => { + Commands::GetTDPLimitMax => { let value = proxy.tdp_limit_max().await?; println!("TDP limit max: {value}"); } - Some(Commands::GetTDPLimitMin) => { + Commands::GetTDPLimitMin => { let value = proxy.tdp_limit_min().await?; println!("TDP limit min: {value}"); } - Some(Commands::SetWifiBackend { backend }) => match WifiBackend::from_str(backend) { + Commands::SetWifiBackend { backend } => match WifiBackend::from_str(backend) { Ok(b) => { proxy.set_wifi_backend(b as u32).await?; } @@ -232,45 +231,44 @@ async fn main() -> Result<()> { println!("Unknown wifi backend {backend}"); } }, - Some(Commands::GetWifiBackend) => { + Commands::GetWifiBackend => { let backend = proxy.wifi_backend().await?; let backend_string = WifiBackend::try_from(backend).unwrap().to_string(); println!("Wifi backend: {backend_string}"); } - Some(Commands::SetWifiDebugMode { mode, buffer }) => { + Commands::SetWifiDebugMode { mode, buffer } => { proxy.set_wifi_debug_mode(*mode, *buffer).await?; } - Some(Commands::GetWifiDebugMode) => { + Commands::GetWifiDebugMode => { let mode = proxy.wifi_debug_mode_state().await?; println!("Wifi debug mode: {mode}"); } - Some(Commands::SetWifiPowerManagementState { state }) => { + Commands::SetWifiPowerManagementState { state } => { proxy.set_wifi_power_management_state(*state).await?; } - Some(Commands::GetWifiPowerManagementState) => { + Commands::GetWifiPowerManagementState => { let state = proxy.wifi_power_management_state().await?; println!("Wifi power management state: {state}"); } - Some(Commands::SetHdmiCecState { state }) => { + Commands::SetHdmiCecState { state } => { proxy.set_hdmi_cec_state(*state).await?; } - Some(Commands::GetHdmiCecState) => { + Commands::GetHdmiCecState => { let state = proxy.hdmi_cec_state().await?; println!("HDMI-CEC state: {state}"); } - Some(Commands::UpdateBios) => { + Commands::UpdateBios => { let _ = proxy.update_bios().await?; } - Some(Commands::UpdateDock) => { + Commands::UpdateDock => { let _ = proxy.update_dock().await?; } - Some(Commands::FactoryReset) => { + Commands::FactoryReset => { let _ = proxy.prepare_factory_reset().await?; } - Some(Commands::TrimDevices) => { + Commands::TrimDevices => { let _ = proxy.trim_devices().await?; } - None => {} } Ok(()) From d8cbf1d1c4e7d6e8f81520e642191c401d697d67 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 10 May 2024 17:29:07 -0700 Subject: [PATCH 04/11] steamosctl: Use WifiBackend as the argument type directly --- src/bin/steamosctl.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/bin/steamosctl.rs b/src/bin/steamosctl.rs index cf75a21..8f8f6ae 100644 --- a/src/bin/steamosctl.rs +++ b/src/bin/steamosctl.rs @@ -9,7 +9,6 @@ use anyhow::Result; use clap::{Parser, Subcommand}; use itertools::Itertools; use std::ops::Deref; -use std::str::FromStr; use steamos_manager::proxy::ManagerProxy; use steamos_manager::wifi::WifiBackend; use zbus::fdo::PropertiesProxy; @@ -88,7 +87,7 @@ enum Commands { /// Set the wifi backend if possible SetWifiBackend { /// Supported backends are iwd, wpa_supplicant - backend: String, + backend: WifiBackend, }, /// Get the wifi backend @@ -223,13 +222,8 @@ async fn main() -> Result<()> { let value = proxy.tdp_limit_min().await?; println!("TDP limit min: {value}"); } - Commands::SetWifiBackend { backend } => match WifiBackend::from_str(backend) { - Ok(b) => { - proxy.set_wifi_backend(b as u32).await?; - } - Err(_) => { - println!("Unknown wifi backend {backend}"); - } + Commands::SetWifiBackend { backend } => { + proxy.set_wifi_backend(*backend as u32).await?; }, Commands::GetWifiBackend => { let backend = proxy.wifi_backend().await?; From e25b1a7ca7ff02a574fb44321472367b7bff5e25 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Fri, 10 May 2024 17:43:14 -0700 Subject: [PATCH 05/11] steamosctl: Use GPUPerformanceLevel where applicable --- src/bin/steamosctl.rs | 12 ++++++++---- src/lib.rs | 2 +- src/power.rs | 14 +++++++------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/bin/steamosctl.rs b/src/bin/steamosctl.rs index 8f8f6ae..f697b2b 100644 --- a/src/bin/steamosctl.rs +++ b/src/bin/steamosctl.rs @@ -9,6 +9,7 @@ use anyhow::Result; use clap::{Parser, Subcommand}; use itertools::Itertools; use std::ops::Deref; +use steamos_manager::power::GPUPerformanceLevel; use steamos_manager::proxy::ManagerProxy; use steamos_manager::wifi::WifiBackend; use zbus::fdo::PropertiesProxy; @@ -44,8 +45,8 @@ enum Commands { /// Set the GPU performance level SetGPUPerformanceLevel { - /// 0 = Auto, 1 = Low, 2 = High, 3 = Manual, 4 = Profile Peak - level: u32, + /// Allowed levels are auto, low, high, manual, peak_performance + level: GPUPerformanceLevel, }, /// Get the GPU performance level @@ -182,11 +183,14 @@ async fn main() -> Result<()> { proxy.set_fan_control_state(*state).await?; } Commands::SetGPUPerformanceLevel { level } => { - proxy.set_gpu_performance_level(*level).await?; + proxy.set_gpu_performance_level(*level as u32).await?; } Commands::GetGPUPerformanceLevel => { 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"), + } } Commands::SetManualGPUClock { freq } => { proxy.set_manual_gpu_clock(*freq).await?; diff --git a/src/lib.rs b/src/lib.rs index 5eb2206..d8dcb60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,12 +19,12 @@ mod ds_inhibit; mod error; mod hardware; mod manager; -mod power; mod process; mod sls; mod systemd; pub mod daemon; +pub mod power; pub mod proxy; pub mod wifi; diff --git a/src/power.rs b/src/power.rs index 03cd43c..a514c75 100644 --- a/src/power.rs +++ b/src/power.rs @@ -75,7 +75,7 @@ impl ToString for GPUPerformanceLevel { } } -pub async fn get_gpu_performance_level() -> Result { +pub(crate) async fn get_gpu_performance_level() -> Result { let base = find_hwmon().await?; let level = fs::read_to_string(base.join(GPU_PERFORMANCE_LEVEL_SUFFIX)) .await @@ -84,7 +84,7 @@ pub async fn get_gpu_performance_level() -> Result { 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 base = find_hwmon().await?; 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}")) } -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 // Only used when GPU Performance Level is manual, but write whenever called. ensure!((200..=1600).contains(&clocks), "Invalid clocks"); @@ -125,7 +125,7 @@ pub async fn set_gpu_clocks(clocks: u32) -> Result<()> { Ok(()) } -pub async fn get_gpu_clocks() -> Result { +pub(crate) async fn get_gpu_clocks() -> Result { let base = find_hwmon().await?; let clocks_file = File::open(base.join(GPU_CLOCKS_SUFFIX)).await?; let mut reader = BufReader::new(clocks_file); @@ -170,14 +170,14 @@ async fn find_hwmon() -> Result { } } -pub async fn get_tdp_limit() -> Result { +pub(crate) async fn get_tdp_limit() -> Result { let base = find_hwmon().await?; let power1cap = fs::read_to_string(base.join(TDP_LIMIT1)).await?; let power1cap: u32 = power1cap.trim_end().parse()?; 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) // Returns false on error or out of range ensure!((3..=15).contains(&limit), "Invalid limit"); @@ -201,7 +201,7 @@ pub async fn set_tdp_limit(limit: u32) -> Result<()> { } #[cfg(test)] -pub mod test { +pub(crate) mod test { use super::*; use crate::testing; use anyhow::anyhow; From d7b391b43221156a06ca8010627b1f8717496543 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 13 May 2024 16:43:42 -0700 Subject: [PATCH 06/11] cec: Add HdmiCecState::from_str --- src/cec.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/cec.rs b/src/cec.rs index 9372f35..8d4c875 100644 --- a/src/cec.rs +++ b/src/cec.rs @@ -6,8 +6,9 @@ * SPDX-License-Identifier: MIT */ -use anyhow::Result; +use anyhow::{bail, Error, Result}; use std::fmt; +use std::str::FromStr; use zbus::Connection; use crate::systemd::{daemon_reload, EnableState, SystemdUnit}; @@ -31,6 +32,18 @@ impl TryFrom for HdmiCecState { } } +impl FromStr for HdmiCecState { + type Err = Error; + fn from_str(input: &str) -> Result { + 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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -41,7 +54,7 @@ impl fmt::Display for HdmiCecState { } } -pub struct HdmiCecControl<'dbus> { +pub(crate) struct HdmiCecControl<'dbus> { plasma_rc_unit: SystemdUnit<'dbus>, wakehook_unit: SystemdUnit<'dbus>, connection: Connection, From fbfb07e684b084c4600effbc1e4ba0650a4673c7 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 13 May 2024 16:44:07 -0700 Subject: [PATCH 07/11] hardware: Add FanControlState::from_str --- src/hardware.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/hardware.rs b/src/hardware.rs index 03a0a24..09f8dc8 100644 --- a/src/hardware.rs +++ b/src/hardware.rs @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -use anyhow::{Error, Result}; +use anyhow::{bail, Error, Result}; use std::fmt; use std::str::FromStr; 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"; #[derive(PartialEq, Debug, Copy, Clone)] -pub enum HardwareVariant { +pub(crate) enum HardwareVariant { Unknown, Jupiter, Galileo, @@ -27,7 +27,7 @@ pub enum HardwareVariant { #[derive(PartialEq, Debug, Copy, Clone)] #[repr(u32)] -pub enum HardwareCurrentlySupported { +pub(crate) enum HardwareCurrentlySupported { Unsupported = 0, Supported = 1, } @@ -85,6 +85,17 @@ impl TryFrom for FanControlState { } } +impl FromStr for FanControlState { + type Err = Error; + fn from_str(input: &str) -> Result { + 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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -94,7 +105,7 @@ impl fmt::Display for FanControlState { } } -pub async fn variant() -> Result { +pub(crate) async fn variant() -> Result { let board_vendor = fs::read_to_string(path(BOARD_VENDOR_PATH)).await?; if board_vendor.trim_end() != "Valve" { return Ok(HardwareVariant::Unknown); @@ -104,7 +115,7 @@ pub async fn variant() -> Result { HardwareVariant::from_str(board_name.trim_end()) } -pub async fn check_support() -> Result { +pub(crate) async fn check_support() -> Result { // Run jupiter-check-support note this script does exit 1 for "Support: No" case // so no need to parse output, etc. let res = script_exit_code("/usr/bin/jupiter-check-support", &[] as &[String; 0]).await?; @@ -115,7 +126,7 @@ pub async fn check_support() -> Result { }) } -pub struct FanControl { +pub(crate) struct FanControl { connection: Connection, } From 20227416e11eadbe156f5370c7557bb11335c11c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 13 May 2024 16:44:39 -0700 Subject: [PATCH 08/11] power: Make GPUPerformanceLevel::from_str implementation consistent with others --- src/power.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/power.rs b/src/power.rs index a514c75..8c3f1de 100644 --- a/src/power.rs +++ b/src/power.rs @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -use anyhow::{anyhow, bail, ensure, Error, Result}; +use anyhow::{bail, ensure, Error, Result}; use std::path::PathBuf; use std::str::FromStr; use tokio::fs::{self, File}; @@ -52,14 +52,14 @@ impl TryFrom for GPUPerformanceLevel { impl FromStr for GPUPerformanceLevel { type Err = Error; fn from_str(input: &str) -> Result { - match input { - "auto" => Ok(GPUPerformanceLevel::Auto), - "low" => Ok(GPUPerformanceLevel::Low), - "high" => Ok(GPUPerformanceLevel::High), - "manual" => Ok(GPUPerformanceLevel::Manual), - "peak_performance" => Ok(GPUPerformanceLevel::ProfilePeak), - v => Err(anyhow!("No enum match for value {v}")), - } + Ok(match input { + "auto" => GPUPerformanceLevel::Auto, + "low" => GPUPerformanceLevel::Low, + "high" => GPUPerformanceLevel::High, + "manual" => GPUPerformanceLevel::Manual, + "peak_performance" => GPUPerformanceLevel::ProfilePeak, + v => bail!("No enum match for value {v}"), + }) } } From 936bdb220ca75cd490addb788326797a5702cfe0 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 13 May 2024 16:44:57 -0700 Subject: [PATCH 09/11] wifi: Add WifiDebugMode::from_str and WifiPowerManagement::from_str --- src/wifi.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/wifi.rs b/src/wifi.rs index 523a3a9..33af2ae 100644 --- a/src/wifi.rs +++ b/src/wifi.rs @@ -64,6 +64,17 @@ impl TryFrom for WifiDebugMode { } } +impl FromStr for WifiDebugMode { + type Err = Error; + fn from_str(input: &str) -> Result { + 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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { @@ -84,6 +95,17 @@ impl TryFrom for WifiPowerManagement { } } +impl FromStr for WifiPowerManagement { + type Err = Error; + fn from_str(input: &str) -> Result { + 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 { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { From d027445d9dce1f3b6461b6c4f252c97e1f53d955 Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 13 May 2024 16:45:46 -0700 Subject: [PATCH 10/11] steamosctl: Use more enums instead of u32 where applicable --- src/bin/steamosctl.rs | 30 ++++++++++++++++-------------- src/lib.rs | 4 ++-- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/bin/steamosctl.rs b/src/bin/steamosctl.rs index f697b2b..994816f 100644 --- a/src/bin/steamosctl.rs +++ b/src/bin/steamosctl.rs @@ -9,9 +9,11 @@ use anyhow::Result; use clap::{Parser, Subcommand}; use itertools::Itertools; use std::ops::Deref; +use steamos_manager::cec::HdmiCecState; +use steamos_manager::hardware::FanControlState; use steamos_manager::power::GPUPerformanceLevel; use steamos_manager::proxy::ManagerProxy; -use steamos_manager::wifi::WifiBackend; +use steamos_manager::wifi::{WifiBackend, WifiDebugMode, WifiPowerManagement}; use zbus::fdo::PropertiesProxy; use zbus::names::InterfaceName; use zbus::{zvariant, Connection}; @@ -36,8 +38,8 @@ enum Commands { /// Set the fan control state SetFanControlState { - /// 0 - BIOS, 1 - OS - state: u32, + /// Valid options are bios, os + state: FanControlState, }, /// Get the fan control state @@ -45,7 +47,7 @@ enum Commands { /// Set the GPU performance level SetGPUPerformanceLevel { - /// Allowed levels are auto, low, high, manual, peak_performance + /// Valid levels are auto, low, high, manual, peak_performance level: GPUPerformanceLevel, }, @@ -96,8 +98,8 @@ enum Commands { /// Set wifi debug mode SetWifiDebugMode { - /// 1 for on, 0 for off - mode: u32, + /// Valid modes are on, off + mode: WifiDebugMode, /// The size of the debug buffer, in bytes #[arg(default_value_t = 20000)] buffer: u32, @@ -108,8 +110,8 @@ enum Commands { /// Set the wifi power management state SetWifiPowerManagementState { - /// 0 - disabled, 1 - enabled - state: u32, + /// Valid modes are enabled, disabled + state: WifiPowerManagement, }, /// Get the wifi power management state @@ -120,8 +122,8 @@ enum Commands { /// Set the state of HDMI-CEC support SetHdmiCecState { - /// 0 - disabled, 1 - only controls, 2 - Controls and TV waking - state: u32, + /// Valid modes are disabled, control-only, control-and-wake + state: HdmiCecState, }, /// Update the BIOS, if possible @@ -180,7 +182,7 @@ async fn main() -> Result<()> { println!("Version: {version}"); } Commands::SetFanControlState { state } => { - proxy.set_fan_control_state(*state).await?; + proxy.set_fan_control_state(*state as u32).await?; } Commands::SetGPUPerformanceLevel { level } => { proxy.set_gpu_performance_level(*level as u32).await?; @@ -235,21 +237,21 @@ async fn main() -> Result<()> { println!("Wifi backend: {backend_string}"); } Commands::SetWifiDebugMode { mode, buffer } => { - proxy.set_wifi_debug_mode(*mode, *buffer).await?; + proxy.set_wifi_debug_mode(*mode as u32, *buffer).await?; } Commands::GetWifiDebugMode => { let mode = proxy.wifi_debug_mode_state().await?; println!("Wifi debug mode: {mode}"); } Commands::SetWifiPowerManagementState { state } => { - proxy.set_wifi_power_management_state(*state).await?; + proxy.set_wifi_power_management_state(*state as u32).await?; } Commands::GetWifiPowerManagementState => { let state = proxy.wifi_power_management_state().await?; println!("Wifi power management state: {state}"); } Commands::SetHdmiCecState { state } => { - proxy.set_hdmi_cec_state(*state).await?; + proxy.set_hdmi_cec_state(*state as u32).await?; } Commands::GetHdmiCecState => { let state = proxy.hdmi_cec_state().await?; diff --git a/src/lib.rs b/src/lib.rs index d8dcb60..8de732d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,16 +14,16 @@ use tokio::signal::unix::{signal, SignalKind}; use tokio_util::sync::CancellationToken; use tracing::{info, warn}; -mod cec; mod ds_inhibit; mod error; -mod hardware; mod manager; mod process; mod sls; mod systemd; +pub mod cec; pub mod daemon; +pub mod hardware; pub mod power; pub mod proxy; pub mod wifi; From 4f84b482259d85ed38af43ff81998a6d14f3bbec Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Mon, 13 May 2024 18:33:47 -0700 Subject: [PATCH 11/11] steamosctl: Give human-readable results for property names --- src/bin/steamosctl.rs | 32 +++++++++++++++++++++++--------- src/cec.rs | 10 ++++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/bin/steamosctl.rs b/src/bin/steamosctl.rs index 994816f..a449787 100644 --- a/src/bin/steamosctl.rs +++ b/src/bin/steamosctl.rs @@ -184,6 +184,13 @@ async fn main() -> Result<()> { Commands::SetFanControlState { state } => { proxy.set_fan_control_state(*state as u32).await?; } + Commands::GetFanControlState => { + 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"), + } + } Commands::SetGPUPerformanceLevel { level } => { proxy.set_gpu_performance_level(*level as u32).await?; } @@ -216,10 +223,6 @@ async fn main() -> Result<()> { let limit = proxy.tdp_limit().await?; println!("TDP limit: {limit}"); } - Commands::GetFanControlState => { - let state = proxy.fan_control_state().await?; - println!("Fan control state: {state}"); - } Commands::GetTDPLimitMax => { let value = proxy.tdp_limit_max().await?; println!("TDP limit max: {value}"); @@ -233,29 +236,40 @@ async fn main() -> Result<()> { }, Commands::GetWifiBackend => { let backend = proxy.wifi_backend().await?; - let backend_string = WifiBackend::try_from(backend).unwrap().to_string(); - println!("Wifi backend: {backend_string}"); + match WifiBackend::try_from(backend) { + Ok(be) => println!("Wifi backend: {}", be.to_string()), + Err(_) => println!("Got unknown value {backend} from backend"), + } } Commands::SetWifiDebugMode { mode, buffer } => { proxy.set_wifi_debug_mode(*mode as u32, *buffer).await?; } Commands::GetWifiDebugMode => { 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"), + } } Commands::SetWifiPowerManagementState { state } => { proxy.set_wifi_power_management_state(*state as u32).await?; } Commands::GetWifiPowerManagementState => { 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"), + } } Commands::SetHdmiCecState { state } => { proxy.set_hdmi_cec_state(*state as u32).await?; } Commands::GetHdmiCecState => { 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"), + } } Commands::UpdateBios => { let _ = proxy.update_bios().await?; diff --git a/src/cec.rs b/src/cec.rs index 8d4c875..1637fba 100644 --- a/src/cec.rs +++ b/src/cec.rs @@ -54,6 +54,16 @@ impl fmt::Display for HdmiCecState { } } +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>, wakehook_unit: SystemdUnit<'dbus>,