diff --git a/src/main.rs b/src/main.rs index cad6be3..869504f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,7 @@ mod hardware; mod manager; mod process; mod sls; +mod wifi; #[cfg(test)] mod testing; diff --git a/src/manager.rs b/src/manager.rs index faf116c..cbf514b 100644 --- a/src/manager.rs +++ b/src/manager.rs @@ -6,40 +6,13 @@ */ use anyhow::{ensure, Result}; -use std::fmt; -use tokio::{fs, fs::File, io::AsyncWriteExt}; +use tokio::{fs::File, io::AsyncWriteExt}; use tracing::{error, warn}; use zbus::{interface, zvariant::Fd}; use crate::hardware::{variant, HardwareVariant}; -use crate::process::{run_script, script_output}; - -#[derive(PartialEq, Debug, Copy, Clone)] -#[repr(u32)] -enum WifiDebugMode { - Off, - On, -} - -impl TryFrom for WifiDebugMode { - type Error = &'static str; - fn try_from(v: u32) -> Result { - match v { - 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}"), - } - } -} - -impl fmt::Display for WifiDebugMode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - WifiDebugMode::Off => write!(f, "Off"), - WifiDebugMode::On => write!(f, "On"), - } - } -} +use crate::process::{run_script, script_output, SYSTEMCTL_PATH}; +use crate::wifi::{restart_iwd, setup_iwd_config, start_tracing, stop_tracing, WifiDebugMode}; pub struct SMManager { wifi_debug_mode: WifiDebugMode, @@ -57,15 +30,6 @@ impl SMManager { } } -const OVERRIDE_CONTENTS: &str = "[Service] -ExecStart= -ExecStart=/usr/lib/iwd/iwd -d -"; -const OVERRIDE_FOLDER: &str = "/etc/systemd/system/iwd.service.d"; -const OVERRIDE_PATH: &str = "/etc/systemd/system/iwd.service.d/override.conf"; -// Only use one path for output for now. If needed we can add a timestamp later -// to have multiple files, etc. -const OUTPUT_FILE: &str = "/var/log/wifitrace.dat"; 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"; @@ -76,69 +40,6 @@ 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"; -const SYSTEMCTL_PATH: &str = "/usr/bin/systemctl"; -const TRACE_CMD_PATH: &str = "/usr/bin/trace-cmd"; - -async fn setup_iwd_config(want_override: bool) -> std::io::Result<()> { - // Copy override.conf file into place or out of place depending - // on install value - - if want_override { - // Copy it in - // Make sure the folder exists - fs::create_dir_all(OVERRIDE_FOLDER).await?; - // Then write the contents into the file - fs::write(OVERRIDE_PATH, OVERRIDE_CONTENTS).await - } else { - // Delete it - fs::remove_file(OVERRIDE_PATH).await - } -} - -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 { - Ok(value) => { - if value { - // worked, now restart iwd - run_script("restart iwd", SYSTEMCTL_PATH, &["restart", "iwd"]).await - } else { - // reload failed - error!("restart_iwd: reload systemd failed with non-zero exit code"); - Ok(false) - } - } - Err(message) => { - error!("restart_iwd: reload systemd got an error: {message}"); - Err(message) - } - } -} - -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 - run_script( - "extract traces", - TRACE_CMD_PATH, - &["extract", "-o", OUTPUT_FILE], - ) - .await -} - -async fn start_tracing(buffer_size: u32) -> Result { - // Start tracing - let size_str = format!("{}", buffer_size); - run_script( - "start tracing", - TRACE_CMD_PATH, - &["start", "-e", "ath11k_wmi_diag", "-b", &size_str], - ) - .await -} - async fn set_gpu_performance_level(level: i32) -> Result<()> { // Set given GPU performance level // Levels are defined below diff --git a/src/process.rs b/src/process.rs index a5e6847..e38f15c 100644 --- a/src/process.rs +++ b/src/process.rs @@ -10,6 +10,8 @@ use std::ffi::OsStr; use tokio::process::Command; use tracing::warn; +pub const SYSTEMCTL_PATH: &str = "/usr/bin/systemctl"; + pub async fn script_exit_code(executable: &str, args: &[impl AsRef]) -> Result { // Run given script and return true on success let mut child = Command::new(executable).args(args).spawn()?; diff --git a/src/wifi.rs b/src/wifi.rs new file mode 100644 index 0000000..70c5600 --- /dev/null +++ b/src/wifi.rs @@ -0,0 +1,144 @@ +/* + * Copyright © 2023 Collabora Ltd. + * Copyright © 2024 Valve Software + * + * SPDX-License-Identifier: MIT + */ + +use anyhow::Result; +use std::fmt; +use tokio::fs; +use tracing::error; + +use crate::process::{run_script, SYSTEMCTL_PATH}; + +const OVERRIDE_CONTENTS: &str = "[Service] +ExecStart= +ExecStart=/usr/lib/iwd/iwd -d +"; +const OVERRIDE_FOLDER: &str = "/etc/systemd/system/iwd.service.d"; +const OVERRIDE_PATH: &str = "/etc/systemd/system/iwd.service.d/override.conf"; + +// Only use one path for output for now. If needed we can add a timestamp later +// to have multiple files, etc. +const OUTPUT_FILE: &str = "/var/log/wifitrace.dat"; +const TRACE_CMD_PATH: &str = "/usr/bin/trace-cmd"; + +#[derive(PartialEq, Debug, Copy, Clone)] +#[repr(u32)] +pub enum WifiDebugMode { + Off, + On, +} + +#[derive(PartialEq, Debug, Copy, Clone)] +#[repr(u32)] +pub enum WifiPowerManagement { + UnsupportedFeature = 0, + Disabled = 1, + Enabled = 2, +} + +impl TryFrom for WifiDebugMode { + type Error = &'static str; + fn try_from(v: u32) -> Result { + match v { + 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}"), + } + } +} + +impl fmt::Display for WifiDebugMode { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + WifiDebugMode::Off => write!(f, "Off"), + WifiDebugMode::On => write!(f, "On"), + } + } +} + +impl TryFrom for WifiPowerManagement { + type Error = &'static str; + fn try_from(v: u32) -> Result { + match v { + x if x == WifiPowerManagement::UnsupportedFeature as u32 => { + Ok(WifiPowerManagement::UnsupportedFeature) + } + x if x == WifiPowerManagement::Disabled as u32 => Ok(WifiPowerManagement::Disabled), + x if x == WifiPowerManagement::Enabled as u32 => Ok(WifiPowerManagement::Enabled), + _ => Err("No enum match for value {v}"), + } + } +} + +impl fmt::Display for WifiPowerManagement { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + WifiPowerManagement::UnsupportedFeature => write!(f, "Unsupported feature"), + WifiPowerManagement::Disabled => write!(f, "Disabled"), + WifiPowerManagement::Enabled => write!(f, "Enabled"), + } + } +} + +pub async fn setup_iwd_config(want_override: bool) -> std::io::Result<()> { + // Copy override.conf file into place or out of place depending + // on install value + + if want_override { + // Copy it in + // Make sure the folder exists + fs::create_dir_all(OVERRIDE_FOLDER).await?; + // Then write the contents into the file + fs::write(OVERRIDE_PATH, OVERRIDE_CONTENTS).await + } else { + // Delete it + fs::remove_file(OVERRIDE_PATH).await + } +} + +pub 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 { + Ok(value) => { + if value { + // worked, now restart iwd + run_script("restart iwd", SYSTEMCTL_PATH, &["restart", "iwd"]).await + } else { + // reload failed + error!("restart_iwd: reload systemd failed with non-zero exit code"); + Ok(false) + } + } + Err(message) => { + error!("restart_iwd: reload systemd got an error: {message}"); + Err(message) + } + } +} + +pub 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 + run_script( + "extract traces", + TRACE_CMD_PATH, + &["extract", "-o", OUTPUT_FILE], + ) + .await +} + +pub async fn start_tracing(buffer_size: u32) -> Result { + // Start tracing + let size_str = format!("{}", buffer_size); + run_script( + "start tracing", + TRACE_CMD_PATH, + &["start", "-e", "ath11k_wmi_diag", "-b", &size_str], + ) + .await +}