From e3ce1853e91825b5550196a3c02364469788b78c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Tue, 10 Jun 2025 19:49:41 -0700 Subject: [PATCH] platform: Split out DeviceConfig from PlatformConfig --- Makefile | 4 +- data/devices/jupiter.toml | 16 ++ .../legion-go-series.toml | 0 .../rog-ally-series.toml | 0 .../zotac-gaming-zone.toml | 0 .../{platforms/jupiter.toml => platform.toml} | 17 -- src/hardware.rs | 18 +- src/manager/root.rs | 4 +- src/manager/user.rs | 258 +++++++++++------- src/platform.rs | 63 +++-- src/power.rs | 64 ++--- src/testing.rs | 4 +- 12 files changed, 269 insertions(+), 179 deletions(-) create mode 100644 data/devices/jupiter.toml rename data/{platforms => devices}/legion-go-series.toml (100%) rename data/{platforms => devices}/rog-ally-series.toml (100%) rename data/{platforms => devices}/zotac-gaming-zone.toml (100%) rename data/{platforms/jupiter.toml => platform.toml} (75%) diff --git a/Makefile b/Makefile index f463645..a274747 100644 --- a/Makefile +++ b/Makefile @@ -24,9 +24,11 @@ install: target/release/steamos-manager target/release/steamosctl install -Ds -m755 "target/release/steamos-manager" "$(DESTDIR)/usr/lib/steamos-manager" install -D -m755 "target/release/steamosctl" "$(DESTDIR)/usr/bin/steamosctl" - install -D -m644 -t "$(DESTDIR)/usr/share/steamos-manager/platforms" "data/platforms/"* + install -D -m644 -t "$(DESTDIR)/usr/share/steamos-manager/devices" "data/devices/"* install -D -m644 LICENSE "$(DESTDIR)/usr/share/licenses/steamos-manager/LICENSE" + install -m644 "data/platform.toml" "$(DESTDIR)/usr/share/steamos-manager/" + install -m644 "data/system/com.steampowered.SteamOSManager1.service" "$(DESTDIR)/usr/share/dbus-1/system-services/" install -m644 "data/system/com.steampowered.SteamOSManager1.conf" "$(DESTDIR)/usr/share/dbus-1/system.d/" install -m644 "data/system/steamos-manager.service" "$(DESTDIR)/usr/lib/systemd/system/" diff --git a/data/devices/jupiter.toml b/data/devices/jupiter.toml new file mode 100644 index 0000000..6e7d81d --- /dev/null +++ b/data/devices/jupiter.toml @@ -0,0 +1,16 @@ +[tdp_limit] +method = "gpu_hwmon" +download_mode_limit = 6 + +[tdp_limit.range] +min = 3 +max = 15 + +[gpu_clocks] +min = 200 +max = 1600 + +[battery_charge_limit] +suggested_minimum_limit = 10 +hwmon_name = "steamdeck_hwmon" +attribute = "max_battery_charge_level" diff --git a/data/platforms/legion-go-series.toml b/data/devices/legion-go-series.toml similarity index 100% rename from data/platforms/legion-go-series.toml rename to data/devices/legion-go-series.toml diff --git a/data/platforms/rog-ally-series.toml b/data/devices/rog-ally-series.toml similarity index 100% rename from data/platforms/rog-ally-series.toml rename to data/devices/rog-ally-series.toml diff --git a/data/platforms/zotac-gaming-zone.toml b/data/devices/zotac-gaming-zone.toml similarity index 100% rename from data/platforms/zotac-gaming-zone.toml rename to data/devices/zotac-gaming-zone.toml diff --git a/data/platforms/jupiter.toml b/data/platform.toml similarity index 75% rename from data/platforms/jupiter.toml rename to data/platform.toml index 881ebb8..ddab3e5 100644 --- a/data/platforms/jupiter.toml +++ b/data/platform.toml @@ -28,20 +28,3 @@ no_validate_flag = "--skip-validation" [fan_control] systemd = "jupiter-fan-control.service" - -[tdp_limit] -method = "gpu_hwmon" -download_mode_limit = 6 - -[tdp_limit.range] -min = 3 -max = 15 - -[gpu_clocks] -min = 200 -max = 1600 - -[battery_charge_limit] -suggested_minimum_limit = 10 -hwmon_name = "steamdeck_hwmon" -attribute = "max_battery_charge_level" diff --git a/src/hardware.rs b/src/hardware.rs index 0ffc691..e6fb8dd 100644 --- a/src/hardware.rs +++ b/src/hardware.rs @@ -483,19 +483,11 @@ pub mod test { sleep(Duration::from_millis(10)).await; - h.test.platform_config.replace(Some(PlatformConfig { - factory_reset: None, - update_bios: None, - update_dock: None, - storage: None, - fan_control: Some(ServiceConfig::Systemd(String::from( - "jupiter-fan-control.service", - ))), - tdp_limit: None, - gpu_clocks: None, - battery_charge_limit: None, - performance_profile: None, - })); + let mut platform_config = PlatformConfig::default(); + platform_config.fan_control = Some(ServiceConfig::Systemd(String::from( + "jupiter-fan-control.service", + ))); + h.test.platform_config.replace(Some(platform_config)); let fan_control = FanControl::new(connection); assert_eq!( diff --git a/src/manager/root.rs b/src/manager/root.rs index 9971811..171ec07 100644 --- a/src/manager/root.rs +++ b/src/manager/root.rs @@ -24,7 +24,7 @@ use crate::hardware::{ steam_deck_variant, FactoryResetKind, FanControl, FanControlState, SteamDeckVariant, }; use crate::job::JobManager; -use crate::platform::platform_config; +use crate::platform::{device_config, platform_config}; use crate::power::{ set_cpu_scaling_governor, set_gpu_clocks, set_gpu_performance_level, set_gpu_power_profile, set_max_charge_level, set_platform_profile, tdp_limit_manager, CPUScalingGovernor, @@ -450,7 +450,7 @@ impl SteamOSManager { } async fn set_performance_profile(&self, profile: &str) -> fdo::Result<()> { - let config = platform_config().await.map_err(to_zbus_fdo_error)?; + let config = device_config().await.map_err(to_zbus_fdo_error)?; let config = config .as_ref() .and_then(|config| config.performance_profile.as_ref()) diff --git a/src/manager/user.rs b/src/manager/user.rs index 1c2f3af..f4d5654 100644 --- a/src/manager/user.rs +++ b/src/manager/user.rs @@ -24,7 +24,7 @@ use crate::hardware::{ device_type, device_variant, steam_deck_variant, DeviceType, SteamDeckVariant, }; use crate::job::JobManagerCommand; -use crate::platform::platform_config; +use crate::platform::{device_config, platform_config}; use crate::power::{ get_available_cpu_scaling_governors, get_available_gpu_performance_levels, get_available_gpu_power_profiles, get_available_platform_profiles, get_cpu_scaling_governor, @@ -286,7 +286,7 @@ impl BatteryChargeLimit1 { #[zbus(property(emits_changed_signal = "const"))] async fn suggested_minimum_limit(&self) -> i32 { - let Ok(Some(ref config)) = platform_config().await else { + let Ok(Some(ref config)) = device_config().await else { return BatteryChargeLimit1::DEFAULT_SUGGESTED_MINIMUM_LIMIT; }; let Some(ref config) = config.battery_charge_limit else { @@ -552,7 +552,7 @@ impl Manager2 { impl PerformanceProfile1 { #[zbus(property(emits_changed_signal = "const"))] async fn available_performance_profiles(&self) -> fdo::Result> { - let config = platform_config().await.map_err(to_zbus_fdo_error)?; + let config = device_config().await.map_err(to_zbus_fdo_error)?; let config = config .as_ref() .and_then(|config| config.performance_profile.as_ref()) @@ -566,7 +566,7 @@ impl PerformanceProfile1 { #[zbus(property)] async fn performance_profile(&self) -> fdo::Result { - let config = platform_config().await.map_err(to_zbus_fdo_error)?; + let config = device_config().await.map_err(to_zbus_fdo_error)?; let config = config .as_ref() .and_then(|config| config.performance_profile.as_ref()) @@ -614,7 +614,7 @@ impl PerformanceProfile1 { #[zbus(property(emits_changed_signal = "const"))] async fn suggested_default_performance_profile(&self) -> fdo::Result { - let config = platform_config().await.map_err(to_zbus_fdo_error)?; + let config = device_config().await.map_err(to_zbus_fdo_error)?; let config = config .as_ref() .and_then(|config| config.performance_profile.as_ref()) @@ -852,12 +852,11 @@ impl WifiPowerManagement1 { } } -async fn create_config_interfaces( +async fn create_platform_interfaces( proxy: &Proxy<'static>, object_server: &ObjectServer, connection: &Connection, job_manager: &UnboundedSender, - tdp_manager: Option>, ) -> Result<()> { let Some(config) = platform_config().await? else { return Ok(()); @@ -869,10 +868,6 @@ async fn create_config_interfaces( let fan_control = FanControl1 { proxy: proxy.clone(), }; - let performance_profile = PerformanceProfile1 { - proxy: proxy.clone(), - tdp_limit_manager: tdp_manager.clone(), - }; let storage = Storage1 { proxy: proxy.clone(), job_manager: job_manager.clone(), @@ -906,41 +901,6 @@ async fn create_config_interfaces( } } - if let Some(manager) = tdp_manager { - let low_power_mode = LowPowerMode1 { - manager: manager.clone(), - }; - if config - .tdp_limit - .as_ref() - .and_then(|config| config.download_mode_limit) - .is_some() - { - object_server.at(MANAGER_PATH, low_power_mode).await?; - } - - let object_server = object_server.clone(); - tokio::spawn(async move { - let (tx, rx) = oneshot::channel(); - manager.send(TdpManagerCommand::IsActive(tx))?; - if rx.await?? { - let tdp_limit = TdpLimit1 { manager }; - object_server.at(MANAGER_PATH, tdp_limit).await?; - } - Ok::<(), Error>(()) - }); - } - - if let Some(config) = config.performance_profile.as_ref() { - if !get_available_platform_profiles(&config.platform_profile_name) - .await - .unwrap_or_default() - .is_empty() - { - object_server.at(MANAGER_PATH, performance_profile).await?; - } - } - if let Some(config) = config.storage.as_ref() { match config.is_valid(true).await { Ok(true) => { @@ -974,7 +934,58 @@ async fn create_config_interfaces( Ok(()) } -#[allow(clippy::too_many_lines)] +async fn create_device_interfaces( + proxy: &Proxy<'static>, + object_server: &ObjectServer, + tdp_manager: Option>, +) -> Result<()> { + let Some(config) = device_config().await? else { + return Ok(()); + }; + + let performance_profile = PerformanceProfile1 { + proxy: proxy.clone(), + tdp_limit_manager: tdp_manager.clone(), + }; + + if let Some(manager) = tdp_manager { + let low_power_mode = LowPowerMode1 { + manager: manager.clone(), + }; + if config + .tdp_limit + .as_ref() + .and_then(|config| config.download_mode_limit) + .is_some() + { + object_server.at(MANAGER_PATH, low_power_mode).await?; + } + + let object_server = object_server.clone(); + tokio::spawn(async move { + let (tx, rx) = oneshot::channel(); + manager.send(TdpManagerCommand::IsActive(tx))?; + if rx.await?? { + let tdp_limit = TdpLimit1 { manager }; + object_server.at(MANAGER_PATH, tdp_limit).await?; + } + Ok::<(), Error>(()) + }); + } + + if let Some(config) = config.performance_profile.as_ref() { + if !get_available_platform_profiles(&config.platform_profile_name) + .await + .unwrap_or_default() + .is_empty() + { + object_server.at(MANAGER_PATH, performance_profile).await?; + } + } + + Ok(()) +} + pub(crate) async fn create_interfaces( session: Connection, system: Connection, @@ -1026,7 +1037,8 @@ pub(crate) async fn create_interfaces( let object_server = session.object_server(); object_server.at(MANAGER_PATH, manager).await?; - create_config_interfaces(&proxy, object_server, &system, &job_manager, tdp_manager).await?; + create_device_interfaces(&proxy, object_server, tdp_manager).await?; + create_platform_interfaces(&proxy, object_server, &system, &job_manager).await?; if device_type().await.unwrap_or_default() == DeviceType::SteamDeck { object_server.at(MANAGER_PATH, als).await?; @@ -1088,8 +1100,9 @@ mod test { use crate::hardware::test::fake_model; use crate::hardware::SteamDeckVariant; use crate::platform::{ - BatteryChargeLimitConfig, FormatDeviceConfig, PerformanceProfileConfig, PlatformConfig, - RangeConfig, ResetConfig, ScriptConfig, ServiceConfig, StorageConfig, TdpLimitConfig, + BatteryChargeLimitConfig, DeviceConfig, FormatDeviceConfig, PerformanceProfileConfig, + PlatformConfig, RangeConfig, ResetConfig, ScriptConfig, ServiceConfig, StorageConfig, + TdpLimitConfig, }; use crate::power::TdpLimitingMethod; use crate::systemd::test::{MockManager, MockUnit}; @@ -1112,7 +1125,7 @@ mod test { rx_tdp: Option>, } - fn all_config() -> Option { + fn all_platform_config() -> Option { Some(PlatformConfig { factory_reset: Some(ResetConfig::default()), update_bios: Some(ScriptConfig::default()), @@ -1121,6 +1134,11 @@ mod test { fan_control: Some(ServiceConfig::Systemd(String::from( "jupiter-fan-control.service", ))), + }) + } + + fn all_device_config() -> Option { + Some(DeviceConfig { tdp_limit: Some(TdpLimitConfig { method: TdpLimitingMethod::GpuHwmon, range: Some(RangeConfig::new(3, 15)), @@ -1140,12 +1158,15 @@ mod test { }) } - async fn start(mut platform_config: Option) -> Result { + async fn start( + mut platform_config: Option, + device_config: Option, + ) -> Result { let mut handle = testing::start(); let (tx_ctx, _rx_ctx) = channel::(); let (tx_job, rx_job) = unbounded_channel::(); let (tx_tdp, rx_tdp) = { - if platform_config + if device_config .as_ref() .and_then(|config| config.tdp_limit.as_ref()) .is_some() @@ -1162,6 +1183,7 @@ mod test { } handle.test.platform_config.replace(platform_config); + handle.test.device_config.replace(device_config); let connection = handle.new_dbus().await?; connection.request_name("org.freedesktop.systemd1").await?; sleep(Duration::from_millis(10)).await; @@ -1212,7 +1234,7 @@ mod test { #[tokio::test] async fn interface_matches() { - let test = start(None).await.expect("start"); + let test = start(None, None).await.expect("start"); let remote = testing::InterfaceIntrospection::from_remote::( &test.connection, @@ -1248,7 +1270,9 @@ mod test { #[tokio::test] async fn interface_matches_ambient_light_sensor1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!( test_interface_matches::(&test.connection) @@ -1259,7 +1283,9 @@ mod test { #[tokio::test] async fn interface_matches_battery_charge_limit() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!( test_interface_matches::(&test.connection) @@ -1270,7 +1296,9 @@ mod test { #[tokio::test] async fn interface_matches_cpu_scaling1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await @@ -1279,7 +1307,9 @@ mod test { #[tokio::test] async fn interface_matches_factory_reset1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await @@ -1288,50 +1318,52 @@ mod test { #[tokio::test] async fn interface_missing_factory_reset1() { - let test = start(None).await.expect("start"); + let test = start(None, None).await.expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_missing_invalid_all_factory_reset1() { - let mut config = all_config().unwrap(); + let mut config = all_platform_config().unwrap(); config.factory_reset.as_mut().unwrap().all = ScriptConfig { script: PathBuf::from("oxo"), script_args: Vec::new(), }; - let test = start(Some(config)).await.expect("start"); + let test = start(Some(config), None).await.expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_missing_invalid_os_factory_reset1() { - let mut config = all_config().unwrap(); + let mut config = all_platform_config().unwrap(); config.factory_reset.as_mut().unwrap().os = ScriptConfig { script: PathBuf::from("oxo"), script_args: Vec::new(), }; - let test = start(Some(config)).await.expect("start"); + let test = start(Some(config), None).await.expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_missing_invalid_user_factory_reset1() { - let mut config = all_config().unwrap(); + let mut config = all_platform_config().unwrap(); config.factory_reset.as_mut().unwrap().user = ScriptConfig { script: PathBuf::from("oxo"), script_args: Vec::new(), }; - let test = start(Some(config)).await.expect("start"); + let test = start(Some(config), None).await.expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_matches_fan_control1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await @@ -1340,14 +1372,16 @@ mod test { #[tokio::test] async fn interface_missing_fan_control1() { - let test = start(None).await.expect("start"); + let test = start(None, None).await.expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_matches_gpu_performance_level1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!( test_interface_matches::(&test.connection) @@ -1358,7 +1392,9 @@ mod test { #[tokio::test] async fn interface_matches_gpu_power_profile1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await @@ -1367,7 +1403,9 @@ mod test { #[tokio::test] async fn interface_matches_tdp_limit1() { - let mut test = start(all_config()).await.expect("start"); + let mut test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); let TdpManagerCommand::IsActive(reply) = test.rx_tdp.as_mut().unwrap().recv().await.unwrap() @@ -1384,14 +1422,16 @@ mod test { #[tokio::test] async fn interface_missing_tdp_limit1() { - let test = start(None).await.expect("start"); + let test = start(None, None).await.expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_inactive_tdp_limit1() { - let mut test = start(all_config()).await.expect("start"); + let mut test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); let TdpManagerCommand::IsActive(reply) = test.rx_tdp.as_mut().unwrap().recv().await.unwrap() @@ -1406,7 +1446,9 @@ mod test { #[tokio::test] async fn interface_matches_hdmi_cec1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await @@ -1415,7 +1457,9 @@ mod test { #[tokio::test] async fn interface_matches_low_power_mode1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await @@ -1424,14 +1468,16 @@ mod test { #[tokio::test] async fn interface_missing_low_power_mode1() { - let test = start(None).await.expect("start"); + let test = start(None, None).await.expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_matches_manager2() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await @@ -1440,7 +1486,9 @@ mod test { #[tokio::test] async fn interface_matches_performance_profile1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!( test_interface_matches::(&test.connection) @@ -1451,14 +1499,16 @@ mod test { #[tokio::test] async fn interface_missing_performance_profile1() { - let test = start(None).await.expect("start"); + let test = start(None, None).await.expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_matches_storage1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await @@ -1467,37 +1517,43 @@ mod test { #[tokio::test] async fn interface_missing_storage1() { - let test = start(None).await.expect("start"); + let test = start(None, None).await.expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_missing_invalid_trim_storage1() { - let mut config = all_config().unwrap(); + let mut config = all_platform_config().unwrap(); config.storage.as_mut().unwrap().trim_devices = ScriptConfig { script: PathBuf::from("oxo"), script_args: Vec::new(), }; - let test = start(Some(config)).await.expect("start"); + let test = start(Some(config), all_device_config()) + .await + .expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_missing_invalid_format_storage1() { - let mut config = all_config().unwrap(); + let mut config = all_platform_config().unwrap(); let mut format_config = FormatDeviceConfig::default(); format_config.script = PathBuf::from("oxo"); config.storage.as_mut().unwrap().format_device = format_config; - let test = start(Some(config)).await.expect("start"); + let test = start(Some(config), all_device_config()) + .await + .expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_matches_update_bios1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await @@ -1506,26 +1562,30 @@ mod test { #[tokio::test] async fn interface_missing_update_bios1() { - let test = start(None).await.expect("start"); + let test = start(None, None).await.expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_missing_invalid_update_bios1() { - let mut config = all_config().unwrap(); + let mut config = all_platform_config().unwrap(); config.update_bios = Some(ScriptConfig { script: PathBuf::from("oxo"), script_args: Vec::new(), }); - let test = start(Some(config)).await.expect("start"); + let test = start(Some(config), all_device_config()) + .await + .expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_matches_update_dock1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await @@ -1534,26 +1594,30 @@ mod test { #[tokio::test] async fn interface_missing_update_dock1() { - let test = start(None).await.expect("start"); + let test = start(None, None).await.expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_missing_invalid_update_dock1() { - let mut config = all_config().unwrap(); + let mut config = all_platform_config().unwrap(); config.update_dock = Some(ScriptConfig { script: PathBuf::from("oxo"), script_args: Vec::new(), }); - let test = start(Some(config)).await.expect("start"); + let test = start(Some(config), all_device_config()) + .await + .expect("start"); assert!(test_interface_missing::(&test.connection).await); } #[tokio::test] async fn interface_matches_wifi_power_management1() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!( test_interface_matches::(&test.connection) @@ -1564,7 +1628,9 @@ mod test { #[tokio::test] async fn interface_matches_wifi_debug() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await @@ -1573,7 +1639,9 @@ mod test { #[tokio::test] async fn interface_matches_wifi_debug_dump() { - let test = start(all_config()).await.expect("start"); + let test = start(all_platform_config(), all_device_config()) + .await + .expect("start"); assert!(test_interface_matches::(&test.connection) .await diff --git a/src/platform.rs b/src/platform.rs index bea68be..f094d89 100644 --- a/src/platform.rs +++ b/src/platform.rs @@ -23,11 +23,15 @@ use zbus::Connection; #[cfg(not(test))] use crate::hardware::{device_type, DeviceType}; +#[cfg(test)] +use crate::path; use crate::power::TdpLimitingMethod; use crate::systemd::SystemdUnit; #[cfg(not(test))] -static CONFIG: OnceCell> = OnceCell::const_new(); +static PLATFORM_CONFIG: OnceCell> = OnceCell::const_new(); +#[cfg(not(test))] +static DEVICE_CONFIG: OnceCell> = OnceCell::const_new(); #[derive(Clone, Default, Deserialize, Debug)] #[serde(default)] @@ -37,6 +41,11 @@ pub(crate) struct PlatformConfig { pub update_dock: Option, pub storage: Option, pub fan_control: Option, +} + +#[derive(Clone, Default, Deserialize, Debug)] +#[serde(default)] +pub(crate) struct DeviceConfig { pub tdp_limit: Option, pub gpu_clocks: Option>, pub battery_charge_limit: Option, @@ -224,26 +233,12 @@ impl RangeConfig { impl PlatformConfig { #[cfg(not(test))] async fn load() -> Result> { - let platform = match device_type().await? { - DeviceType::SteamDeck => "jupiter", - DeviceType::LegionGo => "legion-go-series", - DeviceType::LegionGoS => "legion-go-series", - DeviceType::RogAlly => "rog-ally-series", - DeviceType::RogAllyX => "rog-ally-series", - DeviceType::ZotacGamingZone => "zotac-gaming-zone", - _ => return Ok(None), - }; - let config = read_to_string(format!( - "/usr/share/steamos-manager/platforms/{platform}.toml" - )) - .await?; + let config = read_to_string("/usr/share/steamos-manager/platform.toml").await?; Ok(Some(toml::from_str(config.as_ref())?)) } #[cfg(test)] pub(crate) fn set_test_paths(&mut self) { - use crate::path; - if let Some(ref mut factory_reset) = self.factory_reset { if factory_reset.all.script.as_os_str().is_empty() { factory_reset.all.script = path("exe"); @@ -276,6 +271,26 @@ impl PlatformConfig { } } +impl DeviceConfig { + #[cfg(not(test))] + async fn load() -> Result> { + let platform = match device_type().await? { + DeviceType::SteamDeck => "jupiter", + DeviceType::LegionGo => "legion-go-series", + DeviceType::LegionGoS => "legion-go-series", + DeviceType::RogAlly => "rog-ally-series", + DeviceType::RogAllyX => "rog-ally-series", + DeviceType::ZotacGamingZone => "zotac-gaming-zone", + _ => return Ok(None), + }; + let config = read_to_string(format!( + "/usr/share/steamos-manager/devices/{platform}.toml" + )) + .await?; + Ok(Some(toml::from_str(config.as_ref())?)) + } +} + fn de_tdp_limiter_method<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, @@ -288,7 +303,12 @@ where #[cfg(not(test))] pub(crate) async fn platform_config() -> Result<&'static Option> { - CONFIG.get_or_try_init(PlatformConfig::load).await + PLATFORM_CONFIG.get_or_try_init(PlatformConfig::load).await +} + +#[cfg(not(test))] +pub(crate) async fn device_config() -> Result<&'static Option> { + DEVICE_CONFIG.get_or_try_init(DeviceConfig::load).await } #[cfg(test)] @@ -298,6 +318,13 @@ pub(crate) async fn platform_config() -> Result> { Ok(config) } +#[cfg(test)] +pub(crate) async fn device_config() -> Result> { + let test = crate::testing::current(); + let config = test.device_config.borrow().clone(); + Ok(config) +} + #[cfg(test)] mod test { use super::*; @@ -411,7 +438,7 @@ mod test { #[tokio::test] async fn jupiter_valid() { - let config = read_to_string("data/platforms/jupiter.toml") + let config = read_to_string("data/devices/jupiter.toml") .await .expect("read_to_string"); let res = toml::from_str::(config.as_ref()); diff --git a/src/power.rs b/src/power.rs index d026f8d..9a09974 100644 --- a/src/power.rs +++ b/src/power.rs @@ -30,7 +30,7 @@ use zbus::Connection; use crate::hardware::{device_type, DeviceType}; use crate::manager::root::RootManagerProxy; use crate::manager::user::{TdpLimit1, MANAGER_PATH}; -use crate::platform::platform_config; +use crate::platform::device_config; use crate::Service; use crate::{path, write_synced}; @@ -128,7 +128,7 @@ pub(crate) trait TdpLimitManager: Send + Sync { } pub(crate) async fn tdp_limit_manager() -> Result> { - let config = platform_config().await?; + let config = device_config().await?; let config = config .as_ref() .and_then(|config| config.tdp_limit.as_ref()) @@ -340,7 +340,7 @@ pub(crate) async fn set_cpu_scaling_governor(governor: CPUScalingGovernor) -> Re } pub(crate) async fn get_gpu_clocks_range() -> Result> { - if let Some(range) = platform_config() + if let Some(range) = device_config() .await? .as_ref() .and_then(|config| config.gpu_clocks) @@ -490,7 +490,7 @@ impl TdpLimitManager for GpuHwmonTdpLimitManager { } async fn get_tdp_limit_range(&self) -> Result> { - let config = platform_config().await?; + let config = device_config().await?; let config = config .as_ref() .and_then(|config| config.tdp_limit.as_ref()) @@ -578,7 +578,7 @@ impl TdpLimitManager for FirmwareAttributeLimitManager { let Some(ref performance_profile) = self.performance_profile else { return Ok(true); }; - let config = platform_config().await?; + let config = device_config().await?; if let Some(config) = config .as_ref() .and_then(|config| config.performance_profile.as_ref()) @@ -591,7 +591,7 @@ impl TdpLimitManager for FirmwareAttributeLimitManager { } pub(crate) async fn get_max_charge_level() -> Result { - let config = platform_config().await?; + let config = device_config().await?; let config = config .as_ref() .and_then(|config| config.battery_charge_limit.as_ref()) @@ -609,7 +609,7 @@ pub(crate) async fn get_max_charge_level() -> Result { pub(crate) async fn set_max_charge_level(limit: i32) -> Result<()> { ensure!((0..=100).contains(&limit), "Invalid limit"); let data = limit.to_string(); - let config = platform_config().await?; + let config = device_config().await?; let config = config .as_ref() .and_then(|config| config.battery_charge_limit.as_ref()) @@ -654,7 +654,7 @@ impl TdpManagerService { system: &Connection, session: &Connection, ) -> Result { - let config = platform_config().await?; + let config = device_config().await?; let config = config .as_ref() .and_then(|config| config.tdp_limit.as_ref()) @@ -858,8 +858,8 @@ pub(crate) mod test { use crate::hardware::test::fake_model; use crate::hardware::SteamDeckVariant; use crate::platform::{ - BatteryChargeLimitConfig, FirmwareAttributeConfig, PerformanceProfileConfig, - PlatformConfig, RangeConfig, TdpLimitConfig, + BatteryChargeLimitConfig, DeviceConfig, FirmwareAttributeConfig, PerformanceProfileConfig, + RangeConfig, TdpLimitConfig, }; use crate::{enum_roundtrip, testing}; use anyhow::anyhow; @@ -1041,14 +1041,14 @@ CCLK_RANGE in Core0: async fn test_gpu_hwmon_get_tdp_limit() { let handle = testing::start(); - let mut platform_config = PlatformConfig::default(); - platform_config.tdp_limit = Some(TdpLimitConfig { + let mut config = DeviceConfig::default(); + config.tdp_limit = Some(TdpLimitConfig { method: TdpLimitingMethod::GpuHwmon, range: Some(RangeConfig { min: 3, max: 15 }), download_mode_limit: None, firmware_attribute: None, }); - handle.test.platform_config.replace(Some(platform_config)); + handle.test.device_config.replace(Some(config)); let manager = tdp_limit_manager().await.unwrap(); setup().await.expect("setup"); @@ -1066,14 +1066,14 @@ CCLK_RANGE in Core0: async fn test_gpu_hwmon_set_tdp_limit() { let handle = testing::start(); - let mut platform_config = PlatformConfig::default(); - platform_config.tdp_limit = Some(TdpLimitConfig { + let mut config = DeviceConfig::default(); + config.tdp_limit = Some(TdpLimitConfig { method: TdpLimitingMethod::GpuHwmon, range: Some(RangeConfig { min: 3, max: 15 }), download_mode_limit: None, firmware_attribute: None, }); - handle.test.platform_config.replace(Some(platform_config)); + handle.test.device_config.replace(Some(config)); let manager = tdp_limit_manager().await.unwrap(); assert_eq!( @@ -1550,13 +1550,13 @@ CCLK_RANGE in Core0: async fn read_max_charge_level() { let handle = testing::start(); - let mut platform_config = PlatformConfig::default(); - platform_config.battery_charge_limit = Some(BatteryChargeLimitConfig { + let mut config = DeviceConfig::default(); + config.battery_charge_limit = Some(BatteryChargeLimitConfig { suggested_minimum_limit: Some(10), hwmon_name: String::from("steamdeck_hwmon"), attribute: String::from("max_battery_charge_level"), }); - handle.test.platform_config.replace(Some(platform_config)); + handle.test.device_config.replace(Some(config)); let base = path(HWMON_PREFIX).join("hwmon6"); create_dir_all(&base).await.expect("create_dir_all"); @@ -1650,14 +1650,14 @@ CCLK_RANGE in Core0: let iface = MockTdpLimit { queue: reply_tx }; - let mut platform_config = PlatformConfig::default(); - platform_config.tdp_limit = Some(TdpLimitConfig { + let mut config = DeviceConfig::default(); + config.tdp_limit = Some(TdpLimitConfig { method: TdpLimitingMethod::GpuHwmon, range: Some(RangeConfig { min: 3, max: 15 }), download_mode_limit: NonZeroU32::new(6), firmware_attribute: None, }); - h.test.platform_config.replace(Some(platform_config)); + h.test.device_config.replace(Some(config)); let manager = tdp_limit_manager().await.unwrap(); connection @@ -1746,14 +1746,14 @@ CCLK_RANGE in Core0: let iface = MockTdpLimit { queue: reply_tx }; - let mut platform_config = PlatformConfig::default(); - platform_config.tdp_limit = Some(TdpLimitConfig { + let mut config = DeviceConfig::default(); + config.tdp_limit = Some(TdpLimitConfig { method: TdpLimitingMethod::GpuHwmon, range: Some(RangeConfig { min: 3, max: 15 }), download_mode_limit: None, firmware_attribute: None, }); - h.test.platform_config.replace(Some(platform_config)); + h.test.device_config.replace(Some(config)); let manager = tdp_limit_manager().await.unwrap(); connection @@ -1808,12 +1808,12 @@ CCLK_RANGE in Core0: let h = testing::start(); setup().await.expect("setup"); - let mut platform_config = PlatformConfig::default(); - platform_config.performance_profile = Some(PerformanceProfileConfig { + let mut config = DeviceConfig::default(); + config.performance_profile = Some(PerformanceProfileConfig { platform_profile_name: String::from("platform-profile0"), suggested_default: String::from("custom"), }); - platform_config.tdp_limit = Some(TdpLimitConfig { + config.tdp_limit = Some(TdpLimitConfig { method: TdpLimitingMethod::FirmwareAttribute, range: Some(RangeConfig { min: 3, max: 15 }), download_mode_limit: None, @@ -1822,7 +1822,7 @@ CCLK_RANGE in Core0: performance_profile: Some(String::from("custom")), }), }); - h.test.platform_config.replace(Some(platform_config)); + h.test.device_config.replace(Some(config)); let attributes_base = path(FirmwareAttributeLimitManager::PREFIX) .join("tdp0") @@ -1903,8 +1903,8 @@ CCLK_RANGE in Core0: let h = testing::start(); setup().await.expect("setup"); - let mut platform_config = PlatformConfig::default(); - platform_config.tdp_limit = Some(TdpLimitConfig { + let mut config = DeviceConfig::default(); + config.tdp_limit = Some(TdpLimitConfig { method: TdpLimitingMethod::FirmwareAttribute, range: Some(RangeConfig { min: 3, max: 15 }), download_mode_limit: None, @@ -1913,7 +1913,7 @@ CCLK_RANGE in Core0: performance_profile: None, }), }); - h.test.platform_config.replace(Some(platform_config)); + h.test.device_config.replace(Some(config)); let attributes_base = path(FirmwareAttributeLimitManager::PREFIX) .join("tdp0") diff --git a/src/testing.rs b/src/testing.rs index 44ca9ee..edf376b 100644 --- a/src/testing.rs +++ b/src/testing.rs @@ -23,7 +23,7 @@ use zbus::zvariant::ObjectPath; use zbus::Address; use zbus_xml::{Method, Node, Property, Signal}; -use crate::platform::PlatformConfig; +use crate::platform::{DeviceConfig, PlatformConfig}; thread_local! { static TEST: RefCell>> = const { RefCell::new(None) }; @@ -70,6 +70,7 @@ pub fn start() -> TestHandle { mock_dbus: Cell::new(None), dbus_address: Mutex::new(None), platform_config: RefCell::new(None), + device_config: RefCell::new(None), }); *lock.borrow_mut() = Some(test.clone()); TestHandle { test } @@ -103,6 +104,7 @@ pub struct Test { pub mock_dbus: Cell>, pub dbus_address: Mutex>, pub platform_config: RefCell>, + pub device_config: RefCell>, } pub struct TestHandle {