mirror of
https://gitlab.steamos.cloud/holo/steamos-manager.git
synced 2025-07-05 14:10:34 -04:00
platform: Bring up platform configurations with script replacement, Steam Deck only for now
This commit is contained in:
parent
d465bc2750
commit
77975d9308
6 changed files with 293 additions and 52 deletions
18
data/platforms/jupiter.toml
Normal file
18
data/platforms/jupiter.toml
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
[factory_reset]
|
||||||
|
script = "/usr/bin/steamos-factory-reset-config"
|
||||||
|
|
||||||
|
[update_bios]
|
||||||
|
script = "/usr/bin/jupiter-biosupdate"
|
||||||
|
script_args = ["--auto"]
|
||||||
|
|
||||||
|
[update_dock]
|
||||||
|
script = "/usr/lib/jupiter-dock-updater/jupiter-dock-updater.sh"
|
||||||
|
|
||||||
|
[storage.trim_devices]
|
||||||
|
script = "/usr/lib/hwsupport/trim-devices.sh"
|
||||||
|
|
||||||
|
[storage.format_device]
|
||||||
|
script = "/usr/lib/hwsupport/format-device.sh"
|
||||||
|
label_flag = "--label"
|
||||||
|
device_flag = "--device"
|
||||||
|
no_validate_flag = "--skip-validation"
|
|
@ -17,6 +17,7 @@ mod ds_inhibit;
|
||||||
mod error;
|
mod error;
|
||||||
mod job;
|
mod job;
|
||||||
mod manager;
|
mod manager;
|
||||||
|
mod platform;
|
||||||
mod process;
|
mod process;
|
||||||
mod sls;
|
mod sls;
|
||||||
mod systemd;
|
mod systemd;
|
||||||
|
|
|
@ -21,6 +21,7 @@ use crate::daemon::DaemonCommand;
|
||||||
use crate::error::{to_zbus_error, to_zbus_fdo_error};
|
use crate::error::{to_zbus_error, to_zbus_fdo_error};
|
||||||
use crate::hardware::{variant, FanControl, FanControlState, HardwareVariant};
|
use crate::hardware::{variant, FanControl, FanControlState, HardwareVariant};
|
||||||
use crate::job::JobManager;
|
use crate::job::JobManager;
|
||||||
|
use crate::platform::platform_config;
|
||||||
use crate::power::{
|
use crate::power::{
|
||||||
set_cpu_scaling_governor, set_gpu_clocks, set_gpu_performance_level, set_gpu_power_profile,
|
set_cpu_scaling_governor, set_gpu_clocks, set_gpu_performance_level, set_gpu_power_profile,
|
||||||
set_tdp_limit, CPUScalingGovernor, GPUPerformanceLevel, GPUPowerProfile,
|
set_tdp_limit, CPUScalingGovernor, GPUPerformanceLevel, GPUPowerProfile,
|
||||||
|
@ -32,6 +33,25 @@ use crate::wifi::{
|
||||||
};
|
};
|
||||||
use crate::API_VERSION;
|
use crate::API_VERSION;
|
||||||
|
|
||||||
|
macro_rules! with_platform_config {
|
||||||
|
($config:ident = $field:ident ($name:literal) => $eval:expr) => {
|
||||||
|
if let Some(config) = platform_config()
|
||||||
|
.await
|
||||||
|
.map_err(to_zbus_fdo_error)?
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|config| config.$field.as_ref())
|
||||||
|
{
|
||||||
|
let $config = config;
|
||||||
|
$eval
|
||||||
|
} else {
|
||||||
|
Err(fdo::Error::NotSupported(format!(
|
||||||
|
"{} is not supported on this platform",
|
||||||
|
$name
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Copy, Clone)]
|
#[derive(PartialEq, Debug, Copy, Clone)]
|
||||||
#[repr(u32)]
|
#[repr(u32)]
|
||||||
enum PrepareFactoryReset {
|
enum PrepareFactoryReset {
|
||||||
|
@ -67,12 +87,16 @@ const ALS_INTEGRATION_PATH: &str = "/sys/devices/platform/AMDI0010:00/i2c-0/i2c-
|
||||||
|
|
||||||
#[interface(name = "com.steampowered.SteamOSManager1.RootManager")]
|
#[interface(name = "com.steampowered.SteamOSManager1.RootManager")]
|
||||||
impl SteamOSManager {
|
impl SteamOSManager {
|
||||||
async fn prepare_factory_reset(&self) -> u32 {
|
async fn prepare_factory_reset(&self) -> fdo::Result<u32> {
|
||||||
// Run steamos factory reset script and return true on success
|
// Run steamos factory reset script and return true on success
|
||||||
let res = run_script("/usr/bin/steamos-factory-reset-config", &[] as &[&OsStr]).await;
|
with_platform_config! {
|
||||||
match res {
|
config = factory_reset ("PrepareFactoryReset") => {
|
||||||
Ok(_) => PrepareFactoryReset::RebootRequired as u32,
|
let res = run_script(&config.script, &config.script_args).await;
|
||||||
Err(_) => PrepareFactoryReset::Unknown as u32,
|
Ok(match res {
|
||||||
|
Ok(_) => PrepareFactoryReset::RebootRequired as u32,
|
||||||
|
Err(_) => PrepareFactoryReset::Unknown as u32,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,31 +163,35 @@ impl SteamOSManager {
|
||||||
|
|
||||||
async fn update_bios(&mut self) -> fdo::Result<zvariant::OwnedObjectPath> {
|
async fn update_bios(&mut self) -> fdo::Result<zvariant::OwnedObjectPath> {
|
||||||
// Update the bios as needed
|
// Update the bios as needed
|
||||||
self.job_manager
|
with_platform_config! {
|
||||||
.run_process("/usr/bin/jupiter-biosupdate", &["--auto"], "updating BIOS")
|
config = update_bios ("UpdateBios") => {
|
||||||
.await
|
self.job_manager
|
||||||
|
.run_process(&config.script, &config.script_args, "updating BIOS")
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_dock(&mut self) -> fdo::Result<zvariant::OwnedObjectPath> {
|
async fn update_dock(&mut self) -> fdo::Result<zvariant::OwnedObjectPath> {
|
||||||
// Update the dock firmware as needed
|
// Update the dock firmware as needed
|
||||||
self.job_manager
|
with_platform_config! {
|
||||||
.run_process(
|
config = update_dock ("UpdateDock") => {
|
||||||
"/usr/lib/jupiter-dock-updater/jupiter-dock-updater.sh",
|
self.job_manager
|
||||||
&[] as &[String; 0],
|
.run_process(&config.script, &config.script_args, "updating dock")
|
||||||
"updating dock",
|
.await
|
||||||
)
|
}
|
||||||
.await
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn trim_devices(&mut self) -> fdo::Result<zvariant::OwnedObjectPath> {
|
async fn trim_devices(&mut self) -> fdo::Result<zvariant::OwnedObjectPath> {
|
||||||
// Run steamos-trim-devices script
|
// Run steamos-trim-devices script
|
||||||
self.job_manager
|
with_platform_config! {
|
||||||
.run_process(
|
config = storage ("TrimDevices") => {
|
||||||
"/usr/lib/hwsupport/trim-devices.sh",
|
self.job_manager
|
||||||
&[] as &[String; 0],
|
.run_process(&config.trim_devices.script, config.trim_devices.script_args.as_ref(), "trimming devices")
|
||||||
"trimming devices",
|
.await
|
||||||
)
|
}
|
||||||
.await
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn format_device(
|
async fn format_device(
|
||||||
|
@ -172,17 +200,33 @@ impl SteamOSManager {
|
||||||
label: &str,
|
label: &str,
|
||||||
validate: bool,
|
validate: bool,
|
||||||
) -> fdo::Result<zvariant::OwnedObjectPath> {
|
) -> fdo::Result<zvariant::OwnedObjectPath> {
|
||||||
let mut args = vec!["--label", label, "--device", device];
|
with_platform_config! {
|
||||||
if !validate {
|
config = storage ("FormatDevice") => {
|
||||||
args.push("--skip-validation");
|
let config = &config.format_device;
|
||||||
|
let mut args: Vec<&OsStr> = config.script_args.iter().map(AsRef::as_ref).collect();
|
||||||
|
|
||||||
|
args.extend_from_slice(&[OsStr::new(config.label_flag.as_str()), OsStr::new(label)]);
|
||||||
|
|
||||||
|
match (validate, &config.validate_flag, &config.no_validate_flag) {
|
||||||
|
(true, Some(validate_flag), _) => args.push(OsStr::new(validate_flag)),
|
||||||
|
(false, _, Some(no_validate_flag)) => args.push(OsStr::new(no_validate_flag)),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(device_flag) = &config.device_flag {
|
||||||
|
args.push(OsStr::new(device_flag));
|
||||||
|
}
|
||||||
|
args.push(OsStr::new(device));
|
||||||
|
|
||||||
|
self.job_manager
|
||||||
|
.run_process(
|
||||||
|
&config.script,
|
||||||
|
&args,
|
||||||
|
format!("formatting {device}").as_str(),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
self.job_manager
|
|
||||||
.run_process(
|
|
||||||
"/usr/lib/hwsupport/format-device.sh",
|
|
||||||
args.as_ref(),
|
|
||||||
format!("formatting {device}").as_str(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_gpu_power_profile(&self, value: &str) -> fdo::Result<()> {
|
async fn set_gpu_power_profile(&self, value: &str) -> fdo::Result<()> {
|
||||||
|
@ -326,6 +370,7 @@ mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::daemon::channel;
|
use crate::daemon::channel;
|
||||||
use crate::daemon::root::RootContext;
|
use crate::daemon::root::RootContext;
|
||||||
|
use crate::platform::{PlatformConfig, ScriptConfig};
|
||||||
use crate::power::test::{format_clocks, read_clocks};
|
use crate::power::test::{format_clocks, read_clocks};
|
||||||
use crate::power::{self, get_gpu_performance_level};
|
use crate::power::{self, get_gpu_performance_level};
|
||||||
use crate::process::test::{code, exit, ok};
|
use crate::process::test::{code, exit, ok};
|
||||||
|
@ -379,6 +424,11 @@ mod test {
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn prepare_factory_reset() {
|
async fn prepare_factory_reset() {
|
||||||
let test = start().await.expect("start");
|
let test = start().await.expect("start");
|
||||||
|
|
||||||
|
let mut config = PlatformConfig::default();
|
||||||
|
config.factory_reset = Some(ScriptConfig::default());
|
||||||
|
test.h.test.platform_config.replace(Some(config));
|
||||||
|
|
||||||
let name = test.connection.unique_name().unwrap();
|
let name = test.connection.unique_name().unwrap();
|
||||||
let proxy = PrepareFactoryResetProxy::new(&test.connection, name.clone())
|
let proxy = PrepareFactoryResetProxy::new(&test.connection, name.clone())
|
||||||
.await
|
.await
|
||||||
|
|
|
@ -21,6 +21,7 @@ use crate::daemon::DaemonCommand;
|
||||||
use crate::error::{to_zbus_error, to_zbus_fdo_error, zbus_to_zbus_fdo};
|
use crate::error::{to_zbus_error, to_zbus_fdo_error, zbus_to_zbus_fdo};
|
||||||
use crate::hardware::{check_support, is_deck, HardwareCurrentlySupported};
|
use crate::hardware::{check_support, is_deck, HardwareCurrentlySupported};
|
||||||
use crate::job::JobManagerCommand;
|
use crate::job::JobManagerCommand;
|
||||||
|
use crate::platform::platform_config;
|
||||||
use crate::power::{
|
use crate::power::{
|
||||||
get_available_cpu_scaling_governors, get_available_gpu_performance_levels,
|
get_available_cpu_scaling_governors, get_available_gpu_performance_levels,
|
||||||
get_available_gpu_power_profiles, get_cpu_scaling_governor, get_gpu_clocks,
|
get_available_gpu_power_profiles, get_cpu_scaling_governor, get_gpu_clocks,
|
||||||
|
@ -577,6 +578,7 @@ pub(crate) async fn create_interfaces(
|
||||||
proxy: proxy.clone(),
|
proxy: proxy.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let config = platform_config().await?;
|
||||||
let object_server = session.object_server();
|
let object_server = session.object_server();
|
||||||
object_server.at(MANAGER_PATH, manager).await?;
|
object_server.at(MANAGER_PATH, manager).await?;
|
||||||
|
|
||||||
|
@ -585,7 +587,14 @@ pub(crate) async fn create_interfaces(
|
||||||
}
|
}
|
||||||
|
|
||||||
object_server.at(MANAGER_PATH, cpu_scaling).await?;
|
object_server.at(MANAGER_PATH, cpu_scaling).await?;
|
||||||
object_server.at(MANAGER_PATH, factory_reset).await?;
|
|
||||||
|
if config
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|config| config.factory_reset.is_some())
|
||||||
|
{
|
||||||
|
object_server.at(MANAGER_PATH, factory_reset).await?;
|
||||||
|
}
|
||||||
|
|
||||||
object_server.at(MANAGER_PATH, fan_control).await?;
|
object_server.at(MANAGER_PATH, fan_control).await?;
|
||||||
|
|
||||||
if !get_available_gpu_performance_levels()
|
if !get_available_gpu_performance_levels()
|
||||||
|
@ -612,9 +621,28 @@ pub(crate) async fn create_interfaces(
|
||||||
|
|
||||||
object_server.at(MANAGER_PATH, hdmi_cec).await?;
|
object_server.at(MANAGER_PATH, hdmi_cec).await?;
|
||||||
object_server.at(MANAGER_PATH, manager2).await?;
|
object_server.at(MANAGER_PATH, manager2).await?;
|
||||||
object_server.at(MANAGER_PATH, storage).await?;
|
|
||||||
object_server.at(MANAGER_PATH, update_bios).await?;
|
if config
|
||||||
object_server.at(MANAGER_PATH, update_dock).await?;
|
.as_ref()
|
||||||
|
.is_some_and(|config| config.storage.is_some())
|
||||||
|
{
|
||||||
|
object_server.at(MANAGER_PATH, storage).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if config
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|config| config.update_bios.is_some())
|
||||||
|
{
|
||||||
|
object_server.at(MANAGER_PATH, update_bios).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if config
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|config| config.update_dock.is_some())
|
||||||
|
{
|
||||||
|
object_server.at(MANAGER_PATH, update_dock).await?;
|
||||||
|
}
|
||||||
|
|
||||||
object_server.at(MANAGER_PATH, wifi_debug).await?;
|
object_server.at(MANAGER_PATH, wifi_debug).await?;
|
||||||
object_server
|
object_server
|
||||||
.at(MANAGER_PATH, wifi_power_management)
|
.at(MANAGER_PATH, wifi_power_management)
|
||||||
|
@ -630,6 +658,7 @@ mod test {
|
||||||
use crate::daemon::user::UserContext;
|
use crate::daemon::user::UserContext;
|
||||||
use crate::hardware::test::fake_model;
|
use crate::hardware::test::fake_model;
|
||||||
use crate::hardware::HardwareVariant;
|
use crate::hardware::HardwareVariant;
|
||||||
|
use crate::platform::{PlatformConfig, ScriptConfig, StorageConfig};
|
||||||
use crate::{power, testing};
|
use crate::{power, testing};
|
||||||
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
@ -642,10 +671,21 @@ mod test {
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn start() -> Result<TestHandle> {
|
fn all_config() -> Option<PlatformConfig> {
|
||||||
|
Some(PlatformConfig {
|
||||||
|
factory_reset: Some(ScriptConfig::default()),
|
||||||
|
update_bios: Some(ScriptConfig::default()),
|
||||||
|
update_dock: Some(ScriptConfig::default()),
|
||||||
|
storage: Some(StorageConfig::default()),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn start(platform_config: Option<PlatformConfig>) -> Result<TestHandle> {
|
||||||
let mut handle = testing::start();
|
let mut handle = testing::start();
|
||||||
let (tx_ctx, _rx_ctx) = channel::<UserContext>();
|
let (tx_ctx, _rx_ctx) = channel::<UserContext>();
|
||||||
let (tx_job, _rx_job) = unbounded_channel::<JobManagerCommand>();
|
let (tx_job, _rx_job) = unbounded_channel::<JobManagerCommand>();
|
||||||
|
|
||||||
|
handle.test.platform_config.replace(platform_config);
|
||||||
let connection = handle.new_dbus().await?;
|
let connection = handle.new_dbus().await?;
|
||||||
fake_model(HardwareVariant::Jupiter).await?;
|
fake_model(HardwareVariant::Jupiter).await?;
|
||||||
power::test::create_nodes().await?;
|
power::test::create_nodes().await?;
|
||||||
|
@ -661,7 +701,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches() {
|
async fn interface_matches() {
|
||||||
let test = start().await.expect("start");
|
let test = start(None).await.expect("start");
|
||||||
|
|
||||||
let remote = testing::InterfaceIntrospection::from_remote::<SteamOSManager, _>(
|
let remote = testing::InterfaceIntrospection::from_remote::<SteamOSManager, _>(
|
||||||
&test.connection,
|
&test.connection,
|
||||||
|
@ -689,9 +729,15 @@ mod test {
|
||||||
Ok(remote.compare(&local))
|
Ok(remote.compare(&local))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn test_interface_missing<I: Interface>(connection: &Connection) -> bool {
|
||||||
|
let remote =
|
||||||
|
testing::InterfaceIntrospection::from_remote::<I, _>(connection, MANAGER_PATH).await;
|
||||||
|
return remote.is_err();
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_ambient_light_sensor1() {
|
async fn interface_matches_ambient_light_sensor1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
test_interface_matches::<AmbientLightSensor1>(&test.connection)
|
test_interface_matches::<AmbientLightSensor1>(&test.connection)
|
||||||
|
@ -702,7 +748,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_cpu_scaling1() {
|
async fn interface_matches_cpu_scaling1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(test_interface_matches::<CpuScaling1>(&test.connection)
|
assert!(test_interface_matches::<CpuScaling1>(&test.connection)
|
||||||
.await
|
.await
|
||||||
|
@ -711,16 +757,23 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_factory_reset1() {
|
async fn interface_matches_factory_reset1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(test_interface_matches::<FactoryReset1>(&test.connection)
|
assert!(test_interface_matches::<FactoryReset1>(&test.connection)
|
||||||
.await
|
.await
|
||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn interface_missing_factory_reset1() {
|
||||||
|
let test = start(None).await.expect("start");
|
||||||
|
|
||||||
|
assert!(test_interface_missing::<FactoryReset1>(&test.connection).await);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_fan_control1() {
|
async fn interface_matches_fan_control1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(test_interface_matches::<FanControl1>(&test.connection)
|
assert!(test_interface_matches::<FanControl1>(&test.connection)
|
||||||
.await
|
.await
|
||||||
|
@ -729,7 +782,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_gpu_performance_level1() {
|
async fn interface_matches_gpu_performance_level1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
test_interface_matches::<GpuPerformanceLevel1>(&test.connection)
|
test_interface_matches::<GpuPerformanceLevel1>(&test.connection)
|
||||||
|
@ -740,7 +793,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_gpu_power_profile1() {
|
async fn interface_matches_gpu_power_profile1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(test_interface_matches::<GpuPowerProfile1>(&test.connection)
|
assert!(test_interface_matches::<GpuPowerProfile1>(&test.connection)
|
||||||
.await
|
.await
|
||||||
|
@ -749,7 +802,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_gpu_tdp_limit1() {
|
async fn interface_matches_gpu_tdp_limit1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(test_interface_matches::<GpuTdpLimit1>(&test.connection)
|
assert!(test_interface_matches::<GpuTdpLimit1>(&test.connection)
|
||||||
.await
|
.await
|
||||||
|
@ -758,7 +811,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_hdmi_cec1() {
|
async fn interface_matches_hdmi_cec1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(test_interface_matches::<HdmiCec1>(&test.connection)
|
assert!(test_interface_matches::<HdmiCec1>(&test.connection)
|
||||||
.await
|
.await
|
||||||
|
@ -767,7 +820,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_manager2() {
|
async fn interface_matches_manager2() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(test_interface_matches::<Manager2>(&test.connection)
|
assert!(test_interface_matches::<Manager2>(&test.connection)
|
||||||
.await
|
.await
|
||||||
|
@ -776,34 +829,55 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_storage1() {
|
async fn interface_matches_storage1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(test_interface_matches::<Storage1>(&test.connection)
|
assert!(test_interface_matches::<Storage1>(&test.connection)
|
||||||
.await
|
.await
|
||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn interface_missing_storage1() {
|
||||||
|
let test = start(None).await.expect("start");
|
||||||
|
|
||||||
|
assert!(test_interface_missing::<Storage1>(&test.connection).await);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_update_bios1() {
|
async fn interface_matches_update_bios1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(test_interface_matches::<UpdateBios1>(&test.connection)
|
assert!(test_interface_matches::<UpdateBios1>(&test.connection)
|
||||||
.await
|
.await
|
||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn interface_missing_update_bios1() {
|
||||||
|
let test = start(None).await.expect("start");
|
||||||
|
|
||||||
|
assert!(test_interface_missing::<UpdateBios1>(&test.connection).await);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_update_dock1() {
|
async fn interface_matches_update_dock1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(test_interface_matches::<UpdateDock1>(&test.connection)
|
assert!(test_interface_matches::<UpdateDock1>(&test.connection)
|
||||||
.await
|
.await
|
||||||
.unwrap());
|
.unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn interface_missing_update_dock1() {
|
||||||
|
let test = start(None).await.expect("start");
|
||||||
|
|
||||||
|
assert!(test_interface_missing::<UpdateDock1>(&test.connection).await);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_wifi_power_management1() {
|
async fn interface_matches_wifi_power_management1() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
test_interface_matches::<WifiPowerManagement1>(&test.connection)
|
test_interface_matches::<WifiPowerManagement1>(&test.connection)
|
||||||
|
@ -814,7 +888,7 @@ mod test {
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn interface_matches_wifi_debug() {
|
async fn interface_matches_wifi_debug() {
|
||||||
let test = start().await.expect("start");
|
let test = start(all_config()).await.expect("start");
|
||||||
|
|
||||||
assert!(test_interface_matches::<WifiDebug1>(&test.connection)
|
assert!(test_interface_matches::<WifiDebug1>(&test.connection)
|
||||||
.await
|
.await
|
||||||
|
|
94
src/platform.rs
Normal file
94
src/platform.rs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2023 Collabora Ltd.
|
||||||
|
* Copyright © 2024 Valve Software
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use tokio::fs::read_to_string;
|
||||||
|
#[cfg(not(test))]
|
||||||
|
use tokio::sync::OnceCell;
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
use crate::hardware::is_deck;
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
static CONFIG: OnceCell<Option<PlatformConfig>> = OnceCell::const_new();
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Deserialize, Debug)]
|
||||||
|
#[serde(default)]
|
||||||
|
pub(crate) struct PlatformConfig {
|
||||||
|
pub factory_reset: Option<ScriptConfig>,
|
||||||
|
pub update_bios: Option<ScriptConfig>,
|
||||||
|
pub update_dock: Option<ScriptConfig>,
|
||||||
|
pub storage: Option<StorageConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Deserialize, Debug)]
|
||||||
|
pub(crate) struct ScriptConfig {
|
||||||
|
pub script: PathBuf,
|
||||||
|
#[serde(default)]
|
||||||
|
pub script_args: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Deserialize, Debug)]
|
||||||
|
pub(crate) struct StorageConfig {
|
||||||
|
pub trim_devices: ScriptConfig,
|
||||||
|
pub format_device: FormatDeviceConfig,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Deserialize, Debug)]
|
||||||
|
pub(crate) struct FormatDeviceConfig {
|
||||||
|
pub script: PathBuf,
|
||||||
|
#[serde(default)]
|
||||||
|
pub script_args: Vec<String>,
|
||||||
|
pub label_flag: String,
|
||||||
|
#[serde(default)]
|
||||||
|
pub device_flag: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub validate_flag: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub no_validate_flag: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlatformConfig {
|
||||||
|
#[cfg(not(test))]
|
||||||
|
async fn load() -> Result<Option<PlatformConfig>> {
|
||||||
|
if !is_deck().await? {
|
||||||
|
// Non-Steam Deck platforms are not yet supported
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
|
||||||
|
let config = read_to_string("/usr/share/steamos-manager/platforms/jupiter.toml").await?;
|
||||||
|
Ok(Some(toml::from_str(config.as_ref())?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
pub(crate) async fn platform_config() -> Result<&'static Option<PlatformConfig>> {
|
||||||
|
CONFIG.get_or_try_init(PlatformConfig::load).await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
pub(crate) async fn platform_config() -> Result<Option<PlatformConfig>> {
|
||||||
|
let test = crate::testing::current();
|
||||||
|
let config = test.platform_config.borrow().clone();
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn jupiter_valid() {
|
||||||
|
let config = read_to_string("data/platforms/jupiter.toml")
|
||||||
|
.await
|
||||||
|
.expect("read_to_string");
|
||||||
|
let res = toml::from_str::<PlatformConfig>(config.as_ref());
|
||||||
|
assert!(res.is_ok(), "{res:?}");
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,6 +22,8 @@ use zbus::zvariant::ObjectPath;
|
||||||
use zbus::{Address, Connection, ConnectionBuilder, Interface};
|
use zbus::{Address, Connection, ConnectionBuilder, Interface};
|
||||||
use zbus_xml::{Method, Node, Property};
|
use zbus_xml::{Method, Node, Property};
|
||||||
|
|
||||||
|
use crate::platform::PlatformConfig;
|
||||||
|
|
||||||
thread_local! {
|
thread_local! {
|
||||||
static TEST: RefCell<Option<Rc<Test>>> = RefCell::new(None);
|
static TEST: RefCell<Option<Rc<Test>>> = RefCell::new(None);
|
||||||
}
|
}
|
||||||
|
@ -66,6 +68,7 @@ pub fn start() -> TestHandle {
|
||||||
process_cb: Cell::new(|_, _| Err(anyhow!("No current process_cb"))),
|
process_cb: Cell::new(|_, _| Err(anyhow!("No current process_cb"))),
|
||||||
mock_dbus: Cell::new(None),
|
mock_dbus: Cell::new(None),
|
||||||
dbus_address: Mutex::new(None),
|
dbus_address: Mutex::new(None),
|
||||||
|
platform_config: RefCell::new(None),
|
||||||
});
|
});
|
||||||
*lock.borrow_mut() = Some(test.clone());
|
*lock.borrow_mut() = Some(test.clone());
|
||||||
TestHandle { test }
|
TestHandle { test }
|
||||||
|
@ -98,6 +101,7 @@ pub struct Test {
|
||||||
pub process_cb: Cell<fn(&OsStr, &[&OsStr]) -> Result<(i32, String)>>,
|
pub process_cb: Cell<fn(&OsStr, &[&OsStr]) -> Result<(i32, String)>>,
|
||||||
pub mock_dbus: Cell<Option<MockDBus>>,
|
pub mock_dbus: Cell<Option<MockDBus>>,
|
||||||
pub dbus_address: Mutex<Option<Address>>,
|
pub dbus_address: Mutex<Option<Address>>,
|
||||||
|
pub platform_config: RefCell<Option<PlatformConfig>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TestHandle {
|
pub struct TestHandle {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue