diff --git a/src/hardware.rs b/src/hardware.rs index 5c19b06..7c07912 100644 --- a/src/hardware.rs +++ b/src/hardware.rs @@ -6,10 +6,12 @@ */ use anyhow::{Error, Result}; +use std::fmt; use std::str::FromStr; use tokio::fs; use crate::path; +use crate::process::run_script; const BOARD_VENDOR_PATH: &str = "/sys/class/dmi/id/board_vendor"; const BOARD_NAME_PATH: &str = "/sys/class/dmi/id/board_name"; @@ -21,6 +23,14 @@ pub enum HardwareVariant { Galileo, } +#[derive(PartialEq, Debug, Copy, Clone)] +#[repr(u32)] +pub enum HardwareCurrentlySupported { + UnsupportedFeature = 0, + Unsupported = 1, + Supported = 2, +} + impl FromStr for HardwareVariant { type Err = Error; fn from_str(input: &str) -> Result { @@ -32,6 +42,34 @@ impl FromStr for HardwareVariant { } } +impl TryFrom for HardwareCurrentlySupported { + type Error = &'static str; + fn try_from(v: u32) -> Result { + match v { + x if x == HardwareCurrentlySupported::UnsupportedFeature as u32 => { + Ok(HardwareCurrentlySupported::UnsupportedFeature) + } + x if x == HardwareCurrentlySupported::Unsupported as u32 => { + Ok(HardwareCurrentlySupported::Unsupported) + } + x if x == HardwareCurrentlySupported::Supported as u32 => { + Ok(HardwareCurrentlySupported::Supported) + } + _ => Err("No enum match for value {v}"), + } + } +} + +impl fmt::Display for HardwareCurrentlySupported { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + HardwareCurrentlySupported::UnsupportedFeature => write!(f, "Unsupported feature"), + HardwareCurrentlySupported::Unsupported => write!(f, "Unsupported"), + HardwareCurrentlySupported::Supported => write!(f, "Supported"), + } + } +} + pub async fn variant() -> Result { let board_vendor = fs::read_to_string(path(BOARD_VENDOR_PATH)).await?; if board_vendor.trim_end() != "Valve" { @@ -81,3 +119,19 @@ mod test { assert_eq!(variant().await.unwrap(), HardwareVariant::Unknown); } } + +pub 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 = run_script( + "check hardware support", + "/usr/bin/jupiter-check-support", + &[""], + ) + .await?; + + Ok(match res { + true => HardwareCurrentlySupported::Supported, + false => HardwareCurrentlySupported::Unsupported, + }) +} diff --git a/src/main.rs b/src/main.rs index 12242eb..01b6d20 100644 --- a/src/main.rs +++ b/src/main.rs @@ -124,10 +124,10 @@ async fn reload() -> Result<()> { } async fn create_connection() -> Result { - let manager = manager::SMManager::new().await?; + let manager = manager::SteamOSManager::new().await?; ConnectionBuilder::system()? - .name("com.steampowered.SteamOSManager1")? + .name("com.steampowered.SteamOSManager1.Manager")? .serve_at("/com/steampowered/SteamOSManager1", manager)? .build() .await diff --git a/src/manager.rs b/src/manager.rs index a4664f5..4078f54 100644 --- a/src/manager.rs +++ b/src/manager.rs @@ -6,99 +6,180 @@ */ use anyhow::Result; +use std::fmt; use tokio::fs::File; -use tracing::{error, warn}; +use tracing::error; use zbus::{interface, zvariant::Fd}; -use crate::hardware::{variant, HardwareVariant}; -use crate::power::{set_gpu_clocks, set_gpu_performance_level, set_tdp_limit}; +use crate::hardware::{check_support, variant, HardwareCurrentlySupported, HardwareVariant}; +use crate::power::{ + get_gpu_performance_level, set_gpu_clocks, set_gpu_performance_level, set_tdp_limit, + GPUPerformanceLevel, +}; use crate::process::{run_script, script_output, SYSTEMCTL_PATH}; -use crate::wifi::{restart_iwd, setup_iwd_config, start_tracing, stop_tracing, WifiDebugMode}; +use crate::wifi::{set_wifi_debug_mode, WifiDebugMode, WifiPowerManagement}; -pub struct SMManager { +#[derive(PartialEq, Debug, Copy, Clone)] +#[repr(u32)] +enum PrepareFactoryReset { + Unknown = 0, + RebootRequired = 1, +} + +#[derive(PartialEq, Debug, Copy, Clone)] +#[repr(u32)] +enum FanControl { + UnsupportedFeature = 0, + BIOS = 1, + OS = 2, +} + +impl TryFrom for FanControl { + type Error = &'static str; + fn try_from(v: u32) -> Result { + match v { + x if x == FanControl::UnsupportedFeature as u32 => Ok(FanControl::UnsupportedFeature), + x if x == FanControl::BIOS as u32 => Ok(FanControl::BIOS), + x if x == FanControl::OS as u32 => Ok(FanControl::BIOS), + _ => Err("No enum match for value {v}"), + } + } +} + +impl fmt::Display for FanControl { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + FanControl::UnsupportedFeature => write!(f, "Unsupported feature"), + FanControl::BIOS => write!(f, "BIOS"), + FanControl::OS => write!(f, "OS"), + } + } +} + +pub struct SteamOSManager { wifi_debug_mode: WifiDebugMode, // Whether we should use trace-cmd or not. // True on galileo devices, false otherwise should_trace: bool, } -impl SMManager { +impl SteamOSManager { pub async fn new() -> Result { - Ok(SMManager { + Ok(SteamOSManager { wifi_debug_mode: WifiDebugMode::Off, should_trace: variant().await? == HardwareVariant::Galileo, }) } } -const MIN_BUFFER_SIZE: u32 = 100; - const ALS_INTEGRATION_PATH: &str = "/sys/devices/platform/AMDI0010:00/i2c-0/i2c-PRP0001:01/iio:device0/in_illuminance_integration_time"; -#[interface(name = "com.steampowered.SteamOSManager1")] -impl SMManager { - const API_VERSION: u32 = 1; +#[interface(name = "com.steampowered.SteamOSManager1.Manager")] +impl SteamOSManager { + const API_VERSION: u32 = 7; - async fn say_hello(&self, name: &str) -> String { - format!("Hello {}!", name) - } - - async fn factory_reset(&self) -> bool { + async fn prepare_factory_reset(&self) -> u32 { // Run steamos factory reset script and return true on success - run_script( + let res = run_script( "factory reset", "/usr/bin/steamos-factory-reset-config", &[""], ) .await - .unwrap_or(false) - } - - async fn disable_wifi_power_management(&self) -> bool { - // Run polkit helper script and return true on success - run_script( - "disable wifi power management", - "/usr/bin/steamos-polkit-helpers/steamos-disable-wireless-power-management", - &[""], - ) - .await - .unwrap_or(false) - } - - async fn enable_fan_control(&self, enable: bool) -> bool { - // Run what steamos-polkit-helpers/jupiter-fan-control does - if enable { - run_script( - "enable fan control", - SYSTEMCTL_PATH, - &["start", "jupiter-fan-control-service"], - ) - .await - .unwrap_or(false) - } else { - run_script( - "disable fan control", - SYSTEMCTL_PATH, - &["stop", "jupiter-fan-control.service"], - ) - .await - .unwrap_or(false) + .unwrap_or(false); + match res { + true => PrepareFactoryReset::RebootRequired as u32, + false => PrepareFactoryReset::Unknown as u32, } } - async fn hardware_check_support(&self) -> bool { - // Run jupiter-check-support note this script does exit 1 for "Support: No" case - // so no need to parse output, etc. - run_script( - "check hardware support", - "/usr/bin/jupiter-check-support", - &[""], - ) - .await - .unwrap_or(false) + #[zbus(property)] + fn wifi_power_management_state(&self) -> u32 { + WifiPowerManagement::UnsupportedFeature as u32 // TODO } - async fn read_als_calibration(&self) -> f32 { + #[zbus(property)] + async fn set_wifi_power_management_state(&self, state: u32) -> zbus::Result<()> { + let state = match WifiPowerManagement::try_from(state) { + Ok(state) => state, + Err(err) => return Err(zbus::fdo::Error::InvalidArgs(err.to_string()).into()), + }; + let state = match state { + WifiPowerManagement::Disabled => "off", + WifiPowerManagement::Enabled => "on", + WifiPowerManagement::UnsupportedFeature => { + return Err(zbus::fdo::Error::InvalidArgs(String::from( + "Can't set state to unsupported", + )) + .into()) + } + }; + + let res = run_script( + "set wifi power management", + "/usr/bin/iwconfig", + &["wlan0", "power", state], + ) + .await; + + match res { + Ok(true) => Ok(()), + Ok(false) => Err(zbus::Error::Failure(String::from( + "iwconfig returned non-zero", + ))), + Err(e) => Err(zbus::Error::Failure(e.to_string())), + } + } + + #[zbus(property)] + fn fan_control_state(&self) -> u32 { + FanControl::UnsupportedFeature as u32 // TODO + } + + #[zbus(property)] + async fn set_fan_control_state(&self, state: u32) -> zbus::Result<()> { + let state = match FanControl::try_from(state) { + Ok(state) => state, + Err(err) => return Err(zbus::fdo::Error::InvalidArgs(err.to_string()).into()), + }; + let state = match state { + FanControl::OS => "stop", + FanControl::BIOS => "start", + FanControl::UnsupportedFeature => { + return Err(zbus::fdo::Error::InvalidArgs(String::from( + "Can't set state to unsupported", + )) + .into()) + } + }; + + // Run what steamos-polkit-helpers/jupiter-fan-control does + let res = run_script( + "enable fan control", + SYSTEMCTL_PATH, + &[state, "jupiter-fan-control-service"], + ) + .await; + + match res { + Ok(true) => Ok(()), + Ok(false) => Err(zbus::Error::Failure(String::from( + "systemctl returned non-zero", + ))), + Err(e) => Err(zbus::Error::Failure(format!("{e}"))), + } + } + + #[zbus(property)] + async fn hardware_currently_supported(&self) -> u32 { + match check_support().await { + Ok(res) => res as u32, + Err(_) => HardwareCurrentlySupported::UnsupportedFeature as u32, + } + } + + #[zbus(property)] + async fn als_calibration_gain(&self) -> f64 { // Run script to get calibration value let result = script_output( "/usr/bin/steamos-polkit-helpers/jupiter-get-als-gain", @@ -114,40 +195,61 @@ impl SMManager { } } - async fn update_bios(&self) -> bool { + async fn get_als_integration_time_file_descriptor(&self) -> Result { + // Get the file descriptor for the als integration time sysfs path + let result = File::create(ALS_INTEGRATION_PATH).await; + match result { + Ok(f) => Ok(Fd::Owned(std::os::fd::OwnedFd::from(f.into_std().await))), + Err(message) => { + error!("Error opening sysfs file for giving file descriptor: {message}"); + Err(zbus::fdo::Error::IOError(message.to_string())) + } + } + } + + async fn update_bios(&self) -> Result<(), zbus::fdo::Error> { // Update the bios as needed - // Return true if the script was successful (though that might mean no update was needed), false otherwise - run_script( + let res = run_script( "update bios", "/usr/bin/steamos-potlkit-helpers/jupiter-biosupdate", &["--auto"], ) - .await - .unwrap_or(false) + .await; + + match res { + Ok(_) => Ok(()), + Err(e) => Err(zbus::fdo::Error::Failed(e.to_string())), + } } - async fn update_dock(&self) -> bool { + async fn update_dock(&self) -> Result<(), zbus::fdo::Error> { // Update the dock firmware as needed - // Retur true if successful, false otherwise - run_script( + let res = run_script( "update dock firmware", "/usr/bin/steamos-polkit-helpers/jupiter-dock-updater", &[""], ) - .await - .unwrap_or(false) + .await; + + match res { + Ok(_) => Ok(()), + Err(e) => Err(zbus::fdo::Error::Failed(e.to_string())), + } } - async fn trim_devices(&self) -> bool { + async fn trim_devices(&self) -> Result<(), zbus::fdo::Error> { // Run steamos-trim-devices script - // return true on success, false otherwise - run_script( + let res = run_script( "trim devices", "/usr/bin/steamos-polkit-helpers/steamos-trim-devices", &[""], ) - .await - .unwrap_or(false) + .await; + + match res { + Ok(_) => Ok(()), + Err(e) => Err(zbus::fdo::Error::Failed(e.to_string())), + } } async fn format_sdcard(&self) -> bool { @@ -162,8 +264,23 @@ impl SMManager { .unwrap_or(false) } - async fn set_gpu_performance_level(&self, level: i32) -> bool { - set_gpu_performance_level(level).await.is_ok() + #[zbus(property)] + async fn gpu_performance_level(&self) -> u32 { + match get_gpu_performance_level().await { + Ok(level) => level as u32, + Err(_) => GPUPerformanceLevel::UnsupportedFeature as u32, + } + } + + #[zbus(property)] + async fn set_gpu_performance_level(&self, level: u32) -> zbus::Result<()> { + let level = match GPUPerformanceLevel::try_from(level) { + Ok(level) => level, + Err(e) => return Err(zbus::Error::Failure(e.to_string())), + }; + set_gpu_performance_level(level) + .await + .map_err(|e| zbus::Error::Failure(e.to_string())) } async fn set_gpu_clocks(&self, clocks: i32) -> bool { @@ -174,121 +291,43 @@ impl SMManager { set_tdp_limit(limit).await.is_ok() } - async fn get_als_integration_time_file_descriptor(&self) -> Result { - // Get the file descriptor for the als integration time sysfs path - let result = File::create(ALS_INTEGRATION_PATH).await; - match result { - Ok(f) => Ok(Fd::Owned(std::os::fd::OwnedFd::from(f.into_std().await))), - Err(message) => { - error!("Error opening sysfs file for giving file descriptor: {message}"); - Err(zbus::fdo::Error::IOError(message.to_string())) - } - } - } - - async fn get_wifi_debug_mode(&mut self) -> u32 { + #[zbus(property)] + async fn wifi_debug_mode_state(&self) -> u32 { // Get the wifi debug mode self.wifi_debug_mode as u32 } - async fn set_wifi_debug_mode(&mut self, mode: u32, buffer_size: u32) -> bool { + async fn set_wifi_debug_mode( + &mut self, + mode: u32, + buffer_size: u32, + ) -> Result<(), zbus::fdo::Error> { // Set the wifi debug mode to mode, using an int for flexibility going forward but only // doing things on 0 or 1 for now // Return false on error - let wanted_mode = WifiDebugMode::try_from(mode); - match wanted_mode { - Ok(WifiDebugMode::Off) => { - // If mode is 0 disable wifi debug mode - // Stop any existing trace and flush to disk. - if self.should_trace { - let result = match stop_tracing().await { - Ok(result) => result, - Err(message) => { - error!("stop_tracing command got an error: {message}"); - return false; - } - }; - if !result { - error!("stop_tracing command returned non-zero"); - return false; - } - } - // Stop_tracing was successful - if let Err(message) = setup_iwd_config(false).await { - error!("setup_iwd_config false got an error: {message}"); - return false; - } - // setup_iwd_config false worked - let value = match restart_iwd().await { - Ok(value) => value, - Err(message) => { - error!("restart_iwd got an error: {message}"); - return false; - } - }; - if value { - // restart iwd worked - self.wifi_debug_mode = WifiDebugMode::Off; - } else { - // restart_iwd failed - error!("restart_iwd failed, check log above"); - return false; - } + let wanted_mode = match WifiDebugMode::try_from(mode) { + Ok(WifiDebugMode::UnsupportedFeature) => { + return Err(zbus::fdo::Error::InvalidArgs(String::from("Invalid mode"))) } - Ok(WifiDebugMode::On) => { - // If mode is 1 enable wifi debug mode - if buffer_size < MIN_BUFFER_SIZE { - return false; - } - - if let Err(message) = setup_iwd_config(true).await { - error!("setup_iwd_config true got an error: {message}"); - return false; - } - // setup_iwd_config worked - let value = match restart_iwd().await { - Ok(value) => value, - Err(message) => { - error!("restart_iwd got an error: {message}"); - return false; - } - }; - if !value { - error!("restart_iwd failed"); - return false; - } - // restart_iwd worked - if self.should_trace { - let value = match start_tracing(buffer_size).await { - Ok(value) => value, - Err(message) => { - error!("start_tracing got an error: {message}"); - return false; - } - }; - if !value { - // start_tracing failed - error!("start_tracing failed"); - return false; - } - } - // start_tracing worked - self.wifi_debug_mode = WifiDebugMode::On; + Ok(mode) => mode, + Err(e) => return Err(zbus::fdo::Error::InvalidArgs(e.to_string())), + }; + match set_wifi_debug_mode(wanted_mode, buffer_size, self.should_trace).await { + Ok(()) => { + self.wifi_debug_mode = wanted_mode; + Ok(()) } - Err(_) => { - // Invalid mode requested, more coming later, but add this catch-all for now - warn!("Invalid wifi debug mode {mode} requested"); - return false; + Err(e) => { + error!("Setting wifi debug mode failed: {e}"); + Err(zbus::fdo::Error::Failed(e.to_string())) } } - - true } /// A version property. #[zbus(property)] async fn version(&self) -> u32 { - SMManager::API_VERSION + SteamOSManager::API_VERSION } } diff --git a/src/power.rs b/src/power.rs index 363a00c..cff8a49 100644 --- a/src/power.rs +++ b/src/power.rs @@ -5,7 +5,8 @@ * SPDX-License-Identifier: MIT */ -use anyhow::{bail, ensure, Result}; +use anyhow::{anyhow, bail, ensure, Error, Result}; +use std::str::FromStr; use tokio::fs::{self, File}; use tokio::io::AsyncWriteExt; use tracing::error; @@ -18,22 +19,81 @@ const GPU_PERFORMANCE_LEVEL_PATH: &str = "/sys/class/drm/card0/device/power_dpm_force_performance_level"; const GPU_CLOCKS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; -pub async fn set_gpu_performance_level(level: i32) -> Result<()> { - // Set given GPU performance level - // Levels are defined below - // return true if able to write, false otherwise or if level is out of range, etc. - let levels = ["auto", "low", "high", "manual", "peak_performance"]; - ensure!( - level >= 0 && level < levels.len() as i32, - "Invalid performance level" - ); +#[derive(PartialEq, Debug, Copy, Clone)] +#[repr(u32)] +pub enum GPUPerformanceLevel { + UnsupportedFeature = 0, + Auto = 1, + Low = 2, + High = 3, + Manual = 4, + ProfilePeak = 5, +} +impl TryFrom for GPUPerformanceLevel { + type Error = &'static str; + fn try_from(v: u32) -> Result { + match v { + x if x == GPUPerformanceLevel::UnsupportedFeature as u32 => { + Ok(GPUPerformanceLevel::UnsupportedFeature) + } + x if x == GPUPerformanceLevel::Auto as u32 => Ok(GPUPerformanceLevel::Auto), + x if x == GPUPerformanceLevel::Low as u32 => Ok(GPUPerformanceLevel::Low), + x if x == GPUPerformanceLevel::High as u32 => Ok(GPUPerformanceLevel::High), + x if x == GPUPerformanceLevel::Manual as u32 => Ok(GPUPerformanceLevel::Manual), + x if x == GPUPerformanceLevel::ProfilePeak as u32 => { + Ok(GPUPerformanceLevel::ProfilePeak) + } + _ => Err("No enum match for value {v}"), + } + } +} + +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}")), + } + } +} + +impl TryInto for GPUPerformanceLevel { + type Error = Error; + fn try_into(self) -> Result { + Ok(String::from(match self { + GPUPerformanceLevel::Auto => "auto", + GPUPerformanceLevel::Low => "low", + GPUPerformanceLevel::High => "high", + GPUPerformanceLevel::Manual => "manual", + GPUPerformanceLevel::ProfilePeak => "peak_performance", + GPUPerformanceLevel::UnsupportedFeature => bail!("No valid string representation"), + })) + } +} + +pub async fn get_gpu_performance_level() -> Result { + let level = fs::read_to_string(GPU_PERFORMANCE_LEVEL_PATH) + .await + .inspect_err(|message| error!("Error opening sysfs file for reading: {message}"))?; + + GPUPerformanceLevel::from_str(level.as_ref()) +} + +pub async fn set_gpu_performance_level(level: GPUPerformanceLevel) -> Result<()> { let mut myfile = File::create(GPU_PERFORMANCE_LEVEL_PATH) .await .inspect_err(|message| error!("Error opening sysfs file for writing: {message}"))?; + let level: String = level.try_into()?; + myfile - .write_all(levels[level as usize].as_bytes()) + .write_all(level.as_bytes()) .await .inspect_err(|message| error!("Error writing to sysfs file: {message}"))?; Ok(()) diff --git a/src/wifi.rs b/src/wifi.rs index 70c5600..210b13f 100644 --- a/src/wifi.rs +++ b/src/wifi.rs @@ -5,7 +5,7 @@ * SPDX-License-Identifier: MIT */ -use anyhow::Result; +use anyhow::{bail, ensure, Result}; use std::fmt; use tokio::fs; use tracing::error; @@ -24,11 +24,14 @@ const OVERRIDE_PATH: &str = "/etc/systemd/system/iwd.service.d/override.conf"; const OUTPUT_FILE: &str = "/var/log/wifitrace.dat"; const TRACE_CMD_PATH: &str = "/usr/bin/trace-cmd"; +const MIN_BUFFER_SIZE: u32 = 100; + #[derive(PartialEq, Debug, Copy, Clone)] #[repr(u32)] pub enum WifiDebugMode { - Off, - On, + UnsupportedFeature = 0, + Off = 1, + On = 2, } #[derive(PartialEq, Debug, Copy, Clone)] @@ -43,6 +46,9 @@ impl TryFrom for WifiDebugMode { type Error = &'static str; fn try_from(v: u32) -> Result { match v { + x if x == WifiDebugMode::UnsupportedFeature as u32 => { + Ok(WifiDebugMode::UnsupportedFeature) + } x if x == WifiDebugMode::Off as u32 => Ok(WifiDebugMode::Off), x if x == WifiDebugMode::On as u32 => Ok(WifiDebugMode::On), _ => Err("No enum match for value {v}"), @@ -53,6 +59,7 @@ impl TryFrom for WifiDebugMode { impl fmt::Display for WifiDebugMode { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { + WifiDebugMode::UnsupportedFeature => write!(f, "Unsupported feature"), WifiDebugMode::Off => write!(f, "Off"), WifiDebugMode::On => write!(f, "On"), } @@ -99,7 +106,7 @@ pub async fn setup_iwd_config(want_override: bool) -> std::io::Result<()> { } } -pub async fn restart_iwd() -> Result { +async fn restart_iwd() -> Result { // First reload systemd since we modified the config most likely // otherwise we wouldn't be restarting iwd. match run_script("reload systemd", SYSTEMCTL_PATH, &["daemon-reload"]).await { @@ -120,7 +127,7 @@ pub async fn restart_iwd() -> Result { } } -pub async fn stop_tracing() -> Result { +async fn stop_tracing() -> Result { // Stop tracing and extract ring buffer to disk for capture run_script("stop tracing", TRACE_CMD_PATH, &["stop"]).await?; // stop tracing worked @@ -132,7 +139,7 @@ pub async fn stop_tracing() -> Result { .await } -pub async fn start_tracing(buffer_size: u32) -> Result { +async fn start_tracing(buffer_size: u32) -> Result { // Start tracing let size_str = format!("{}", buffer_size); run_script( @@ -142,3 +149,66 @@ pub async fn start_tracing(buffer_size: u32) -> Result { ) .await } + +pub async fn set_wifi_debug_mode( + mode: WifiDebugMode, + buffer_size: u32, + should_trace: bool, +) -> Result<()> { + // Set the wifi debug mode to mode, using an int for flexibility going forward but only + // doing things on 0 or 1 for now + // Return false on error + + match mode { + WifiDebugMode::Off => { + // If mode is 0 disable wifi debug mode + // Stop any existing trace and flush to disk. + if should_trace { + let result = match stop_tracing().await { + Ok(result) => result, + Err(message) => bail!("stop_tracing command got an error: {message}"), + }; + ensure!(result, "stop_tracing command returned non-zero"); + } + // Stop_tracing was successful + if let Err(message) = setup_iwd_config(false).await { + bail!("setup_iwd_config false got an error: {message}"); + } + // setup_iwd_config false worked + let value = match restart_iwd().await { + Ok(value) => value, + Err(message) => { + bail!("restart_iwd got an error: {message}"); + } + }; + // restart_iwd failed + ensure!(value, "restart_iwd failed, check log above"); + } + WifiDebugMode::On => { + ensure!(buffer_size > MIN_BUFFER_SIZE, "Buffer size too small"); + + if let Err(message) = setup_iwd_config(true).await { + bail!("setup_iwd_config true got an error: {message}"); + } + // setup_iwd_config worked + let value = match restart_iwd().await { + Ok(value) => value, + Err(message) => bail!("restart_iwd got an error: {message}"), + }; + ensure!(value, "restart_iwd failed"); + // restart_iwd worked + if should_trace { + let value = match start_tracing(buffer_size).await { + Ok(value) => value, + Err(message) => bail!("start_tracing got an error: {message}"), + }; + ensure!(value, "start_tracing failed"); + } + } + mode => { + // Invalid mode requested, more coming later, but add this catch-all for now + bail!("Invalid wifi debug mode {mode} requested"); + } + } + Ok(()) +}