diff --git a/Cargo.lock b/Cargo.lock index 1fbedd0..b413f27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + [[package]] name = "anstyle" version = "1.0.7" @@ -308,6 +317,17 @@ dependencies = [ "typenum", ] +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "digest" version = "0.10.7" @@ -761,6 +781,35 @@ dependencies = [ "getrandom", ] +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -1258,14 +1307,15 @@ dependencies = [ [[package]] name = "zbus" -version = "4.2.0" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aea58d1af0aaa8abf87f3d9ade9b8f46bf13727e5f9fb24bc31ee9d94a9b4ad" +checksum = "c9ff46f2a25abd690ed072054733e0bc3157e3d4c45f41bd183dce09c2ff8ab9" dependencies = [ "async-broadcast", "async-process", "async-recursion", "async-trait", + "derivative", "enumflags2", "event-listener 5.3.0", "futures-core", @@ -1291,13 +1341,14 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.2.0" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf2b496ec1e2d3c4a7878e351607f7a2bec1e1029b353683dfc28a22999e369" +checksum = "4e0e3852c93dcdb49c9462afe67a2a468f7bd464150d866e861eaf06208633e0" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", + "regex", "syn 1.0.109", "zvariant_utils", ] @@ -1328,9 +1379,9 @@ dependencies = [ [[package]] name = "zvariant" -version = "4.0.3" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e9282c6945d9e27742ba7ad7191325546636295de7b83f6735af73159b32ac7" +checksum = "2c1b3ca6db667bfada0f1ebfc94b2b1759ba25472ee5373d4551bb892616389a" dependencies = [ "endi", "enumflags2", @@ -1341,9 +1392,9 @@ dependencies = [ [[package]] name = "zvariant_derive" -version = "4.0.3" +version = "4.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0142549e559746ff09d194dd43d256a554299d286cc56460a082b8ae24652aa1" +checksum = "b7a4b236063316163b69039f77ce3117accb41a09567fd24c168e43491e521bc" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1354,9 +1405,9 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "1.1.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75fa7291bdd68cd13c4f97cc9d78cbf16d96305856dfc7ac942aeff4c2de7d5a" +checksum = "00bedb16a193cc12451873fee2a1bc6550225acece0e36f333e68326c73c8172" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 11b8855..55be959 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,4 +21,5 @@ tokio-stream = { version = "0.1", default-features = false } tokio-util = { version = "0.7", default-features = false } tracing = { version = "0.1", default-features = false } tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt"] } -zbus = { version = "4", default-features = false, features = ["tokio"] } +# pinning to 4.1.2 until a fix for https://github.com/dbus2/zbus/issues/764 gets released +zbus = { version = "4.1", default-features = false, features = ["tokio"] } diff --git a/src/bin/steamos-manager.rs b/src/bin/steamos-manager.rs new file mode 100644 index 0000000..b6d9303 --- /dev/null +++ b/src/bin/steamos-manager.rs @@ -0,0 +1,28 @@ +/* + * Copyright © 2023 Collabora Ltd. + * Copyright © 2024 Valve Software + * + * SPDX-License-Identifier: MIT + */ + +use anyhow::Result; +use clap::Parser; + +use steamos_manager::{RootDaemon, UserDaemon}; + +#[derive(Parser)] +struct Args { + /// Run the root manager daemon + #[arg(short, long)] + root: bool, +} + +#[tokio::main] +pub async fn main() -> Result<()> { + let args = Args::parse(); + if args.root { + RootDaemon().await + } else { + UserDaemon().await + } +} diff --git a/src/bin/steamosctl.rs b/src/bin/steamosctl.rs new file mode 100644 index 0000000..fc4983a --- /dev/null +++ b/src/bin/steamosctl.rs @@ -0,0 +1,89 @@ +/* + * Copyright © 2023 Collabora Ltd. + * Copyright © 2024 Valve Software + * + * SPDX-License-Identifier: MIT + */ + +use anyhow::Result; +use clap::{Parser, Subcommand}; +use std::ops::Deref; +use std::str::FromStr; +use steamos_manager::{ManagerProxy, WifiBackend}; +use zbus::fdo::PropertiesProxy; +use zbus::names::InterfaceName; +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, +} + +#[derive(Subcommand)] +enum Commands { + SetWifiBackend { + // Set the wifi backend to given string if possible + // Supported values are iwd|wpa_supplicant + #[arg(short, long)] + backend: String, + }, + + SetWifiDebugMode { + // Set wifi debug mode to given value + // 1 for on, 0 for off currently + #[arg(short, long)] + mode: u32, + }, +} + +#[tokio::main] +async fn main() -> Result<()> { + // This is a command-line utility that calls api using dbus + + // First set up which command line arguments we support + let args = Args::parse(); + + // Then get a connection to the service + let conn = Connection::system().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, value) in properties.iter() { + let val = value.deref(); + println!("{key}: {val}"); + } + } + + // Then process arguments + match &args.command { + Some(Commands::SetWifiBackend { backend }) => match WifiBackend::from_str(backend) { + Ok(b) => { + proxy.set_wifi_backend(b as u32).await?; + } + Err(_) => { + println!("Unknown wifi backend {backend}"); + } + }, + Some(Commands::SetWifiDebugMode { mode }) => { + proxy.set_wifi_debug_mode(*mode, 20000).await?; + } + None => {} + } + + Ok(()) +} diff --git a/src/main.rs b/src/lib.rs similarity index 94% rename from src/main.rs rename to src/lib.rs index b7e444c..670bcc5 100644 --- a/src/main.rs +++ b/src/lib.rs @@ -6,7 +6,6 @@ */ use anyhow::{anyhow, Result}; -use clap::Parser; use std::future::Future; use std::path::{Path, PathBuf}; use tokio::fs::File; @@ -22,6 +21,7 @@ mod hardware; mod manager; mod power; mod process; +mod proxy; mod root; mod sls; mod systemd; @@ -32,9 +32,14 @@ mod wifi; #[cfg(test)] mod testing; +pub use proxy::ManagerProxy; +pub use root::daemon as RootDaemon; +pub use user::daemon as UserDaemon; +pub use wifi::{WifiBackend, WifiDebugMode, WifiPowerManagement}; + const API_VERSION: u32 = 8; -trait Service +pub trait Service where Self: Sized + Send, { @@ -67,13 +72,6 @@ where } } -#[derive(Parser)] -struct Args { - /// Run the root manager daemon - #[arg(short, long)] - root: bool, -} - #[cfg(not(test))] pub fn path>(path: S) -> PathBuf { PathBuf::from(path.as_ref()) @@ -156,16 +154,6 @@ pub fn zbus_to_zbus_fdo(error: zbus::Error) -> zbus::fdo::Error { } } -#[tokio::main] -pub async fn main() -> Result<()> { - let args = Args::parse(); - if args.root { - root::daemon().await - } else { - user::daemon().await - } -} - #[cfg(test)] mod test { use crate::testing; diff --git a/src/proxy.rs b/src/proxy.rs new file mode 100644 index 0000000..02285f3 --- /dev/null +++ b/src/proxy.rs @@ -0,0 +1,140 @@ +//! # D-Bus interface proxy for: `com.steampowered.SteamOSManager1.Manager` +//! and `com.steampowered.SteamOSManager1.Subprocess` +//! +//! This code was generated by `zbus-xmlgen` `4.1.0` from D-Bus introspection data. +//! Source: `com.steampowered.SteamOSManager1.xml`. +//! +//! You may prefer to adapt it, instead of using it verbatim. +//! +//! More information can be found in the [Writing a client proxy] section of the zbus +//! documentation. +//! +//! +//! [Writing a client proxy]: https://dbus2.github.io/zbus/client.html +//! [D-Bus standard interfaces]: https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces, +use zbus::proxy; + +#[proxy( + default_service = "com.steampowered.SteamOSManager1", + default_path = "/com/steampowered/SteamOSManager1", + interface = "com.steampowered.SteamOSManager1.Manager" +)] +trait Manager { + /// FormatDevice method + fn format_device( + &self, + device: &str, + label: &str, + validate: bool, + ) -> zbus::Result; + + /// GetAlsIntegrationTimeFileDescriptor method + fn get_als_integration_time_file_descriptor(&self) -> zbus::Result; + + /// PrepareFactoryReset method + fn prepare_factory_reset(&self) -> zbus::Result; + + /// SetWifiDebugMode method + fn set_wifi_debug_mode(&self, mode: u32, buffer_size: u32) -> zbus::Result<()>; + + /// TrimDevices method + fn trim_devices(&self) -> zbus::Result; + + /// UpdateBIOS method + fn update_bios(&self) -> zbus::Result; + + /// UpdateDock method + fn update_dock(&self) -> zbus::Result; + + /// AlsCalibrationGain property + #[zbus(property)] + fn als_calibration_gain(&self) -> zbus::Result; + + /// FanControlState property + #[zbus(property)] + fn fan_control_state(&self) -> zbus::Result; + #[zbus(property)] + fn set_fan_control_state(&self, value: u32) -> zbus::Result<()>; + + /// GpuPerformanceLevel property + #[zbus(property)] + fn gpu_performance_level(&self) -> zbus::Result; + #[zbus(property)] + fn set_gpu_performance_level(&self, value: u32) -> zbus::Result<()>; + + /// HardwareCurrentlySupported property + #[zbus(property)] + fn hardware_currently_supported(&self) -> zbus::Result; + + /// ManualGpuClock property + #[zbus(property)] + fn manual_gpu_clock(&self) -> zbus::Result; + #[zbus(property)] + fn set_manual_gpu_clock(&self, value: u32) -> zbus::Result<()>; + + /// ManualGpuClockMax property + #[zbus(property)] + fn manual_gpu_clock_max(&self) -> zbus::Result; + + /// ManualGpuClockMin property + #[zbus(property)] + fn manual_gpu_clock_min(&self) -> zbus::Result; + + /// TdpLimit property + #[zbus(property)] + fn tdp_limit(&self) -> zbus::Result; + #[zbus(property)] + fn set_tdp_limit(&self, value: u32) -> zbus::Result<()>; + + /// TdpLimitMax property + #[zbus(property)] + fn tdp_limit_max(&self) -> zbus::Result; + + /// TdpLimitMin property + #[zbus(property)] + fn tdp_limit_min(&self) -> zbus::Result; + + /// Version property + #[zbus(property)] + fn version(&self) -> zbus::Result; + + /// WifiBackend property + #[zbus(property)] + fn wifi_backend(&self) -> zbus::Result; + #[zbus(property)] + fn set_wifi_backend(&self, value: u32) -> zbus::Result<()>; + + /// WifiDebugModeState property + #[zbus(property)] + fn wifi_debug_mode_state(&self) -> zbus::Result; + + /// WifiPowerManagementState property + #[zbus(property)] + fn wifi_power_management_state(&self) -> zbus::Result; + #[zbus(property)] + fn set_wifi_power_management_state(&self, value: u32) -> zbus::Result<()>; +} + +#[proxy( + interface = "com.steampowered.SteamOSManager1.SubProcess", + assume_defaults = true +)] +trait SubProcess { + /// Cancel method + fn cancel(&self) -> zbus::Result<()>; + + /// ExitCode method + fn exit_code(&self) -> zbus::Result; + + /// WaitForExitCode method + fn wait_for_exit_code(&self) -> zbus::Result; + + /// Kill method + fn kill(&self) -> zbus::Result<()>; + + /// Pause method + fn pause(&self) -> zbus::Result<()>; + + /// Resume method + fn resume(&self) -> zbus::Result<()>; +}