diff --git a/com.steampowered.SteamOSManager1.Manager.xml b/com.steampowered.SteamOSManager1.Manager.xml
index 437b22d..e7badba 100644
--- a/com.steampowered.SteamOSManager1.Manager.xml
+++ b/com.steampowered.SteamOSManager1.Manager.xml
@@ -138,27 +138,6 @@
-->
-
-
-
-
-
-
diff --git a/src/bin/steamosctl.rs b/src/bin/steamosctl.rs
index eb05bd0..09df163 100644
--- a/src/bin/steamosctl.rs
+++ b/src/bin/steamosctl.rs
@@ -14,8 +14,8 @@ use steamos_manager::hardware::FanControlState;
use steamos_manager::power::{CPUScalingGovernor, GPUPerformanceLevel, GPUPowerProfile};
use steamos_manager::proxy::{
AmbientLightSensor1Proxy, CpuScaling1Proxy, FactoryReset1Proxy, FanControl1Proxy,
- HdmiCec1Proxy, Manager2Proxy, ManagerProxy, Storage1Proxy, UpdateBios1Proxy, UpdateDock1Proxy,
- WifiPowerManagement1Proxy,
+ GpuPowerProfile1Proxy, HdmiCec1Proxy, Manager2Proxy, ManagerProxy, Storage1Proxy,
+ UpdateBios1Proxy, UpdateDock1Proxy, WifiPowerManagement1Proxy,
};
use steamos_manager::wifi::{WifiBackend, WifiDebugMode, WifiPowerManagement};
use zbus::fdo::PropertiesProxy;
@@ -62,7 +62,7 @@ enum Commands {
},
/// Get the GPU power profiles supported on this device
- GetGPUPowerProfiles,
+ GetAvailableGPUPowerProfiles,
/// Get the current GPU power profile
GetGPUPowerProfile,
@@ -250,17 +250,18 @@ async fn main() -> Result<()> {
.set_cpu_scaling_governor(governor.to_string().as_str())
.await?;
}
- Commands::GetGPUPowerProfiles => {
- let profiles = proxy.gpu_power_profiles().await?;
+ Commands::GetAvailableGPUPowerProfiles => {
+ let proxy = GpuPowerProfile1Proxy::new(&conn).await?;
+ let profiles = proxy.available_gpu_power_profiles().await?;
println!("Profiles:\n");
- for key in profiles.keys().sorted() {
- let name = &profiles[key];
- println!("{key}: {name}");
+ for name in profiles.into_iter().sorted() {
+ println!("- {name}");
}
}
Commands::GetGPUPowerProfile => {
+ let proxy = GpuPowerProfile1Proxy::new(&conn).await?;
let profile = proxy.gpu_power_profile().await?;
- let profile_type = GPUPowerProfile::try_from(profile);
+ let profile_type = GPUPowerProfile::try_from(profile.as_str());
match profile_type {
Ok(t) => {
let name = t.to_string();
@@ -272,7 +273,10 @@ async fn main() -> Result<()> {
}
}
Commands::SetGPUPowerProfile { profile } => {
- proxy.set_gpu_power_profile(*profile as u32).await?;
+ let proxy = GpuPowerProfile1Proxy::new(&conn).await?;
+ proxy
+ .set_gpu_power_profile(profile.to_string().as_str())
+ .await?;
}
Commands::SetGPUPerformanceLevel { level } => {
proxy.set_gpu_performance_level(*level as u32).await?;
diff --git a/src/manager/root.rs b/src/manager/root.rs
index 5498c1b..037d071 100644
--- a/src/manager/root.rs
+++ b/src/manager/root.rs
@@ -184,7 +184,7 @@ impl SteamOSManager {
.await
}
- async fn set_gpu_power_profile(&self, value: u32) -> fdo::Result<()> {
+ async fn set_gpu_power_profile(&self, value: &str) -> fdo::Result<()> {
let profile = GPUPowerProfile::try_from(value).map_err(to_zbus_fdo_error)?;
set_gpu_power_profile(profile)
.await
diff --git a/src/manager/user.rs b/src/manager/user.rs
index 7631357..b43fcfa 100644
--- a/src/manager/user.rs
+++ b/src/manager/user.rs
@@ -7,7 +7,6 @@
*/
use anyhow::Result;
-use std::collections::HashMap;
use tokio::sync::mpsc::{Sender, UnboundedSender};
use tokio::sync::oneshot;
use tracing::error;
@@ -22,9 +21,9 @@ use crate::error::{to_zbus_error, to_zbus_fdo_error, zbus_to_zbus_fdo};
use crate::hardware::{check_support, HardwareCurrentlySupported};
use crate::job::JobManagerCommand;
use crate::power::{
- get_available_cpu_scaling_governors, get_cpu_scaling_governor, get_gpu_clocks,
- get_gpu_clocks_range, get_gpu_performance_level, get_gpu_power_profile, get_gpu_power_profiles,
- get_tdp_limit,
+ get_available_cpu_scaling_governors, get_available_gpu_power_profiles,
+ get_cpu_scaling_governor, get_gpu_clocks, get_gpu_clocks_range, get_gpu_performance_level,
+ get_gpu_power_profile, get_tdp_limit,
};
use crate::wifi::{get_wifi_backend, get_wifi_power_management_state};
use crate::API_VERSION;
@@ -111,6 +110,10 @@ struct FanControl1 {
proxy: Proxy<'static>,
}
+struct GpuPowerProfile1 {
+ proxy: Proxy<'static>,
+}
+
struct HdmiCec1 {
hdmi_cec: HdmiCecControl<'static>,
}
@@ -157,30 +160,6 @@ impl SteamOSManager {
API_VERSION
}
- #[zbus(property(emits_changed_signal = "false"))]
- async fn gpu_power_profiles(&self) -> fdo::Result> {
- get_gpu_power_profiles().await.map_err(to_zbus_fdo_error)
- }
-
- #[zbus(property(emits_changed_signal = "false"))]
- async fn gpu_power_profile(&self) -> fdo::Result {
- match get_gpu_power_profile().await {
- Ok(profile) => Ok(profile as u32),
- Err(e) => {
- error!("Error getting GPU power profile: {e}");
- Err(to_zbus_fdo_error(e))
- }
- }
- }
-
- #[zbus(property)]
- async fn set_gpu_power_profile(&self, profile: u32) -> zbus::Result<()> {
- self.proxy
- .call("SetGpuPowerProfile", &(profile))
- .await
- .map_err(to_zbus_error)
- }
-
#[zbus(property(emits_changed_signal = "false"))]
async fn gpu_performance_level(&self) -> fdo::Result {
match get_gpu_performance_level().await {
@@ -354,6 +333,38 @@ impl FanControl1 {
}
}
+#[interface(name = "com.steampowered.SteamOSManager1.GpuPowerProfile1")]
+impl GpuPowerProfile1 {
+ #[zbus(property(emits_changed_signal = "false"))]
+ async fn available_gpu_power_profiles(&self) -> fdo::Result> {
+ let (_, names): (Vec, Vec) = get_available_gpu_power_profiles()
+ .await
+ .map_err(to_zbus_fdo_error)?
+ .into_iter()
+ .unzip();
+ Ok(names)
+ }
+
+ #[zbus(property(emits_changed_signal = "false"))]
+ async fn gpu_power_profile(&self) -> fdo::Result {
+ match get_gpu_power_profile().await {
+ Ok(profile) => Ok(profile.to_string()),
+ Err(e) => {
+ error!("Error getting GPU power profile: {e}");
+ Err(to_zbus_fdo_error(e))
+ }
+ }
+ }
+
+ #[zbus(property)]
+ async fn set_gpu_power_profile(&self, profile: &str) -> zbus::Result<()> {
+ self.proxy
+ .call("SetGpuPowerProfile", &(profile))
+ .await
+ .map_err(to_zbus_error)
+ }
+}
+
impl HdmiCec1 {
async fn new(connection: &Connection) -> Result {
let hdmi_cec = HdmiCecControl::new(connection).await?;
@@ -482,6 +493,9 @@ pub(crate) async fn create_interfaces(
let fan_control = FanControl1 {
proxy: proxy.clone(),
};
+ let gpu_power_profile = GpuPowerProfile1 {
+ proxy: proxy.clone(),
+ };
let hdmi_cec = HdmiCec1::new(&session).await?;
let manager2 = Manager2 {
proxy: proxy.clone(),
@@ -509,6 +523,7 @@ pub(crate) async fn create_interfaces(
object_server.at(MANAGER_PATH, cpu_scaling).await?;
object_server.at(MANAGER_PATH, factory_reset).await?;
object_server.at(MANAGER_PATH, fan_control).await?;
+ object_server.at(MANAGER_PATH, gpu_power_profile).await?;
object_server.at(MANAGER_PATH, hdmi_cec).await?;
object_server.at(MANAGER_PATH, manager2).await?;
object_server.at(MANAGER_PATH, storage).await?;
@@ -621,6 +636,15 @@ mod test {
.unwrap());
}
+ #[tokio::test]
+ async fn interface_matches_gpu_power_profile1() {
+ let test = start().await.expect("start");
+
+ assert!(test_interface_matches::(&test.connection)
+ .await
+ .unwrap());
+ }
+
#[tokio::test]
async fn interface_matches_hdmi_cec1() {
let test = start().await.expect("start");
diff --git a/src/power.rs b/src/power.rs
index 747e514..11d4cd5 100644
--- a/src/power.rs
+++ b/src/power.rs
@@ -8,7 +8,6 @@
use anyhow::{anyhow, bail, ensure, Result};
use lazy_static::lazy_static;
use regex::Regex;
-use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use strum::{Display, EnumString};
@@ -195,11 +194,11 @@ pub(crate) async fn get_gpu_power_profile() -> Result {
bail!("Unable to determine current GPU power profile");
}
-pub(crate) async fn get_gpu_power_profiles() -> Result> {
+pub(crate) async fn get_available_gpu_power_profiles() -> Result> {
let contents = read_gpu_sysfs_contents(GPU_POWER_PROFILE_SUFFIX).await?;
let deck = is_deck().await?;
- let mut map = HashMap::new();
+ let mut map = Vec::new();
let lines = contents.lines();
for line in lines {
let caps = GPU_POWER_PROFILE_REGEX.captures(line);
@@ -216,13 +215,13 @@ pub(crate) async fn get_gpu_power_profiles() -> Result> {
// the other profiles aren't correctly tuned for the hardware.
if value == GPUPowerProfile::Capped as u32 || value == GPUPowerProfile::Uncapped as u32
{
- map.insert(value, name.to_string());
+ map.push((value, name.to_string()));
} else {
// Got unsupported value, so don't include it
}
} else {
// Do basic validation to ensure our enum is up to date?
- map.insert(value, name.to_string());
+ map.push((value, name.to_string()));
}
}
Ok(map)
@@ -774,10 +773,10 @@ CCLK_RANGE in Core0:
.await
.expect("fake_model");
- let profiles = get_gpu_power_profiles().await.expect("get");
+ let profiles = get_available_gpu_power_profiles().await.expect("get");
assert_eq!(
profiles,
- HashMap::from([
+ &[
(
GPUPowerProfile::FullScreen as u32,
String::from("3D_FULL_SCREEN")
@@ -788,20 +787,20 @@ CCLK_RANGE in Core0:
(GPUPowerProfile::Custom as u32, String::from("CUSTOM")),
(GPUPowerProfile::Capped as u32, String::from("CAPPED")),
(GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED"))
- ])
+ ]
);
fake_model(HardwareVariant::Jupiter)
.await
.expect("fake_model");
- let profiles = get_gpu_power_profiles().await.expect("get");
+ let profiles = get_available_gpu_power_profiles().await.expect("get");
assert_eq!(
profiles,
- HashMap::from([
+ &[
(GPUPowerProfile::Capped as u32, String::from("CAPPED")),
(GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED"))
- ])
+ ]
);
}
@@ -831,35 +830,35 @@ CCLK_RANGE in Core0:
.await
.expect("fake_model");
- let profiles = get_gpu_power_profiles().await.expect("get");
+ let profiles = get_available_gpu_power_profiles().await.expect("get");
assert_eq!(
profiles,
- HashMap::from([
- (2, String::from("CGA")),
+ &[
(
GPUPowerProfile::FullScreen as u32,
String::from("3D_FULL_SCREEN")
),
+ (2, String::from("CGA")),
(GPUPowerProfile::Video as u32, String::from("VIDEO")),
(GPUPowerProfile::VR as u32, String::from("VR")),
(GPUPowerProfile::Compute as u32, String::from("COMPUTE")),
(GPUPowerProfile::Custom as u32, String::from("CUSTOM")),
(GPUPowerProfile::Capped as u32, String::from("CAPPED")),
(GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED"))
- ])
+ ]
);
fake_model(HardwareVariant::Jupiter)
.await
.expect("fake_model");
- let profiles = get_gpu_power_profiles().await.expect("get");
+ let profiles = get_available_gpu_power_profiles().await.expect("get");
assert_eq!(
profiles,
- HashMap::from([
+ &[
(GPUPowerProfile::Capped as u32, String::from("CAPPED")),
(GPUPowerProfile::Uncapped as u32, String::from("UNCAPPED"))
- ])
+ ]
);
}
diff --git a/src/proxy/manager.rs b/src/proxy/manager.rs
index 68b02f0..d6f22a7 100644
--- a/src/proxy/manager.rs
+++ b/src/proxy/manager.rs
@@ -28,16 +28,6 @@ trait Manager {
#[zbus(property)]
fn set_gpu_performance_level(&self, value: u32) -> zbus::Result<()>;
- /// GpuPowerProfile property
- #[zbus(property)]
- fn gpu_power_profile(&self) -> zbus::Result;
- #[zbus(property)]
- fn set_gpu_power_profile(&self, value: u32) -> zbus::Result<()>;
-
- /// GpuPowerProfiles property
- #[zbus(property)]
- fn gpu_power_profiles(&self) -> zbus::Result>;
-
/// ManualGpuClock property
#[zbus(property)]
fn manual_gpu_clock(&self) -> zbus::Result;