Merge branch 'work/whiting/filedescriptor' into 'master'

Implement GetAlsIntegrationTimeFileDescriptor.

See merge request holo/steamos-manager!5
This commit is contained in:
Jeremy Whiting 2023-11-15 23:17:50 +00:00
commit 78d0d6e458
5 changed files with 165 additions and 80 deletions

20
Cargo.lock generated
View file

@ -296,12 +296,6 @@ dependencies = [
"crypto-common", "crypto-common",
] ]
[[package]]
name = "dyn"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd5d33be9d461be19ff7168302689ed4ca466300600546c93795e845d5fa3faf"
[[package]] [[package]]
name = "enumflags2" name = "enumflags2"
version = "0.7.8" version = "0.7.8"
@ -778,18 +772,18 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.188" version = "1.0.192"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.188" version = "1.0.192"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -798,9 +792,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_repr" name = "serde_repr"
version = "0.1.16" version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -876,8 +870,6 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
name = "steamos-manager" name = "steamos-manager"
version = "0.9.0" version = "0.9.0"
dependencies = [ dependencies = [
"dyn",
"serde",
"tokio", "tokio",
"zbus", "zbus",
"zbus_macros", "zbus_macros",

View file

@ -5,9 +5,10 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[profile.release]
strip="symbols"
[dependencies] [dependencies]
dyn = "0.0.0"
serde = { version = "1.0.188", features = ["derive"] }
tokio = { version = "1.33.0", features = ["fs", "process", "io-std", "rt-multi-thread", "macros"] } tokio = { version = "1.33.0", features = ["fs", "process", "io-std", "rt-multi-thread", "macros"] }
zbus = { version = "3.14.1", features = ["tokio"] } zbus = { version = "3.14.1", features = ["tokio"] }
zbus_macros = "3.14.1" zbus_macros = "3.14.1"

View file

@ -172,15 +172,14 @@
</method> </method>
<!-- <!--
SetALSIntegrationTime: GetAlsIntegrationTimeFileDescriptor:
@seconds: The number of seconds to use for ALS integration. @descriptor: A unix file descriptor that can be written to to set ALS integration time.
@success: True on success. False otherwise. Will be null if unable to open file or other error occurred.
Set the ALS integration time to the given value. Get the ALS integration time file descriptor.
--> -->
<method name="SetALSIntegrationTime"> <method name="GetAlsIntegrationTimeFileDescriptor">
<arg type="i" name="seconds" direction="in"/> <arg type="h" name="descriptor" direction="out"/>
<arg type="b" name="success" direction="out"/>
</method> </method>
</interface> </interface>

View file

@ -28,21 +28,19 @@ use zbus::{ConnectionBuilder, Result};
pub mod manager; pub mod manager;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> async fn main() -> Result<()> {
{
// This daemon is responsible for creating a dbus api that steam client can use to do various OS // This daemon is responsible for creating a dbus api that steam client can use to do various OS
// level things. It implements com.steampowered.SteamOSManager1 interface // level things. It implements com.steampowered.SteamOSManager1 interface
let manager = manager::SMManager {}; let manager = manager::SMManager {};
let _system_connection = ConnectionBuilder::system()? let _system_connection = ConnectionBuilder::system()?
.name("com.steampowered.SteamOSManager1")? .name("com.steampowered.SteamOSManager1")?
.serve_at("/com/steampowered/SteamOSManager1", manager)? .serve_at("/com/steampowered/SteamOSManager1", manager)?
.build() .build()
.await?; .await?;
loop loop {
{
std::future::pending::<()>().await; std::future::pending::<()>().await;
} }
} }

View file

@ -23,13 +23,19 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
use std::{ffi::OsStr}; use std::{
use tokio::{process::Command, fs::File, io::AsyncWriteExt}; ffi::OsStr,
os::fd::{FromRawFd, IntoRawFd},
};
use tokio::{fs::File, io::AsyncWriteExt, process::Command};
use zbus::zvariant::OwnedFd;
use zbus_macros::dbus_interface; use zbus_macros::dbus_interface;
pub struct SMManager { pub struct SMManager {}
}
async fn script_exit_code(executable: &str, args: &[impl AsRef<OsStr>]) -> Result<bool, Box<dyn std::error::Error>> { async fn script_exit_code(
executable: &str,
args: &[impl AsRef<OsStr>],
) -> Result<bool, Box<dyn std::error::Error>> {
// Run given script and return true on success // Run given script and return true on success
let mut child = Command::new(executable) let mut child = Command::new(executable)
.args(args) .args(args)
@ -44,14 +50,19 @@ async fn run_script(name: &str, executable: &str, args: &[impl AsRef<OsStr>]) ->
// Return false on failure, but also print an error if needed // Return false on failure, but also print an error if needed
match script_exit_code(executable, args).await { match script_exit_code(executable, args).await {
Ok(value) => value, Ok(value) => value,
Err(err) => { println!("Error running {} {}", name, err); false} Err(err) => {
println!("Error running {} {}", name, err);
false
}
} }
} }
async fn script_output(executable: &str, args: &[impl AsRef<OsStr>]) -> Result<String, Box<dyn std::error::Error>> { async fn script_output(
executable: &str,
args: &[impl AsRef<OsStr>],
) -> Result<String, Box<dyn std::error::Error>> {
// Run given command and return the output given // Run given command and return the output given
let output = Command::new(executable) let output = Command::new(executable).args(args).output();
.args(args).output();
let output = output.await?; let output = output.await?;
@ -66,11 +77,10 @@ async fn script_output(executable: &str, args: &[impl AsRef<OsStr>]) -> Result<S
impl SMManager { impl SMManager {
const API_VERSION: u32 = 1; const API_VERSION: u32 = 1;
async fn say_hello(&self, name: &str) -> String { async fn say_hello(&self, name: &str) -> String {
format!("Hello {}!", name) format!("Hello {}!", name)
} }
async fn factory_reset(&self) -> bool { async fn factory_reset(&self) -> bool {
// Run steamos factory reset script and return true on success // Run steamos factory reset script and return true on success
run_script("factory reset", "steamos-factory-reset-config", &[""]).await run_script("factory reset", "steamos-factory-reset-config", &[""]).await
@ -78,15 +88,30 @@ impl SMManager {
async fn disable_wifi_power_management(&self) -> bool { async fn disable_wifi_power_management(&self) -> bool {
// Run polkit helper script and return true on success // Run polkit helper script and return true on success
run_script("disable wifi power management", "/usr/bin/steamos-polkit-helpers/steamos-disable-wireless-power-management", &[""]).await run_script(
"disable wifi power management",
"/usr/bin/steamos-polkit-helpers/steamos-disable-wireless-power-management",
&[""],
)
.await
} }
async fn enable_fan_control(&self, enable: bool) -> bool { async fn enable_fan_control(&self, enable: bool) -> bool {
// Run what steamos-polkit-helpers/jupiter-fan-control does // Run what steamos-polkit-helpers/jupiter-fan-control does
if enable { if enable {
run_script("enable fan control", "systemcltl", &["start", "jupiter-fan-control-service"]).await run_script(
"enable fan control",
"systemcltl",
&["start", "jupiter-fan-control-service"],
)
.await
} else { } else {
run_script("disable fan control", "systemctl", &["stop", "jupiter-fan-control.service"]).await run_script(
"disable fan control",
"systemctl",
&["stop", "jupiter-fan-control.service"],
)
.await
} }
} }
@ -98,68 +123,93 @@ impl SMManager {
async fn read_als_calibration(&self) -> f32 { async fn read_als_calibration(&self) -> f32 {
// Run script to get calibration value // Run script to get calibration value
let result = script_output("/usr/bin/steamos-polkit-helpers/jupiter-get-als-gain", &[""]).await; let result = script_output(
"/usr/bin/steamos-polkit-helpers/jupiter-get-als-gain",
&[""],
)
.await;
let mut value: f32 = -1.0; let mut value: f32 = -1.0;
match result { match result {
Ok(as_string) => value = as_string.trim().parse().unwrap(), Ok(as_string) => value = as_string.trim().parse().unwrap(),
Err(message) => println!("Unable to run als calibration script : {}", message), Err(message) => println!("Unable to run als calibration script : {}", message),
} }
value value
} }
async fn update_bios(&self) -> bool { async fn update_bios(&self) -> bool {
// Update the bios as needed // Update the bios as needed
// Return true if the script was successful (though that might mean no update was needed), false otherwise // Return true if the script was successful (though that might mean no update was needed), false otherwise
run_script("update bios", "/usr/bin/steamos-potlkit-helpers/jupiter-biosupdate", &["--auto"]).await run_script(
"update bios",
"/usr/bin/steamos-potlkit-helpers/jupiter-biosupdate",
&["--auto"],
)
.await
} }
async fn update_dock(&self) -> bool { async fn update_dock(&self) -> bool {
// Update the dock firmware as needed // Update the dock firmware as needed
// Retur true if successful, false otherwise // Retur true if successful, false otherwise
run_script("update dock firmware", "/usr/bin/steamos-polkit-helpers/jupiter-dock-updater", &[""]).await run_script(
"update dock firmware",
"/usr/bin/steamos-polkit-helpers/jupiter-dock-updater",
&[""],
)
.await
} }
async fn trim_devices(&self) -> bool { async fn trim_devices(&self) -> bool {
// Run steamos-trim-devices script // Run steamos-trim-devices script
// return true on success, false otherwise // return true on success, false otherwise
run_script("trim devices", "/usr/bin/steamos-polkit-helpers/steamos-trim-devices", &[""]).await run_script(
"trim devices",
"/usr/bin/steamos-polkit-helpers/steamos-trim-devices",
&[""],
)
.await
} }
async fn format_sdcard(&self) -> bool { async fn format_sdcard(&self) -> bool {
// Run steamos-format-sdcard script // Run steamos-format-sdcard script
// return true on success, false otherwise // return true on success, false otherwise
run_script("format sdcard", "/usr/bin/steamos-polkit-helpers/steamos-format-sdcard", &[""]).await run_script(
"format sdcard",
"/usr/bin/steamos-polkit-helpers/steamos-format-sdcard",
&[""],
)
.await
} }
async fn set_gpu_performance_level(&self, level: i32) -> bool { async fn set_gpu_performance_level(&self, level: i32) -> bool {
// Set given level to sysfs path /sys/class/drm/card0/device/power_dpm_force_performance_level // Set given level to sysfs path /sys/class/drm/card0/device/power_dpm_force_performance_level
// Levels are defined below // Levels are defined below
// return true if able to write, false otherwise or if level is out of range, etc. // return true if able to write, false otherwise or if level is out of range, etc.
let levels = [ let levels = ["auto", "low", "high", "manual", "peak_performance"];
"auto",
"low",
"high",
"manual",
"peak_performance"
];
if level < 0 || level >= levels.len() as i32 { if level < 0 || level >= levels.len() as i32 {
return false; return false;
} }
// Open sysfs file // Open sysfs file
let result = File::create("/sys/class/drm/card0/device/power_dpm_force_performance_level").await; let result =
let mut myfile; File::create("/sys/class/drm/card0/device/power_dpm_force_performance_level").await;
let mut myfile;
match result { match result {
Ok(f) => myfile = f, Ok(f) => myfile = f,
Err(message) => { println!("Error opening sysfs file for writing {message}"); return false; } Err(message) => {
println!("Error opening sysfs file for writing {message}");
return false;
}
}; };
// write value // write value
let result = myfile.write_all(levels[level as usize].as_bytes()).await; let result = myfile.write_all(levels[level as usize].as_bytes()).await;
match result { match result {
Ok(_worked) => true, Ok(_worked) => true,
Err(message) => { println!("Error writing to sysfs file {message}"); false } Err(message) => {
println!("Error writing to sysfs file {message}");
false
}
} }
} }
@ -175,7 +225,10 @@ impl SMManager {
let mut myfile; let mut myfile;
match result { match result {
Ok(f) => myfile = f, Ok(f) => myfile = f,
Err(message) => { println!("Error opening sysfs file for writing {message}"); return false; } Err(message) => {
println!("Error opening sysfs file for writing {message}");
return false;
}
}; };
// write value // write value
@ -190,16 +243,25 @@ impl SMManager {
let result = myfile.write("c\n".as_bytes()).await; let result = myfile.write("c\n".as_bytes()).await;
match result { match result {
Ok(_worked) => true, Ok(_worked) => true,
Err(message) => { println!("Error writing to sysfs file {message}"); false } Err(message) => {
println!("Error writing to sysfs file {message}");
false
}
} }
}, }
Err(message) => { println!("Error writing to sysfs file {message}"); false } Err(message) => {
println!("Error writing to sysfs file {message}");
false
}
} }
}, }
Err(message) => { println!("Error writing to sysfs file {message}"); false } Err(message) => {
println!("Error writing to sysfs file {message}");
false
}
} }
} }
async fn set_tdp_limit(&self, limit: i32) -> bool { async fn set_tdp_limit(&self, limit: i32) -> bool {
// Set TDP limit given if within range (3-15) // Set TDP limit given if within range (3-15)
// Returns false on error or out of range // Returns false on error or out of range
@ -212,14 +274,20 @@ impl SMManager {
let mut power1file; let mut power1file;
match result { match result {
Ok(f) => power1file = f, Ok(f) => power1file = f,
Err(message) => { println!("Error opening sysfs power1_cap file for writing TDP limits {message}"); return false; } Err(message) => {
println!("Error opening sysfs power1_cap file for writing TDP limits {message}");
return false;
}
}; };
let result = File::create("/sys/class/hwmon/hwmon5/power2_cap").await; let result = File::create("/sys/class/hwmon/hwmon5/power2_cap").await;
let mut power2file; let mut power2file;
match result { match result {
Ok(f) => power2file = f, Ok(f) => power2file = f,
Err(message) => { println!("Error opening sysfs power2_cap file for wtriting TDP limits {message}"); return false; } Err(message) => {
println!("Error opening sysfs power2_cap file for wtriting TDP limits {message}");
return false;
}
}; };
// Now write the value * 1,000,000 // Now write the value * 1,000,000
@ -230,10 +298,38 @@ impl SMManager {
let result = power2file.write(data.as_bytes()).await; let result = power2file.write(data.as_bytes()).await;
match result { match result {
Ok(_worked) => true, Ok(_worked) => true,
Err(message) => { println!("Error writing to power2_cap file: {message}"); false } Err(message) => {
println!("Error writing to power2_cap file: {message}");
false
}
} }
}, }
Err(message) => { println!("Error writing to power1_cap file: {message}"); false } Err(message) => {
println!("Error writing to power1_cap file: {message}");
false
}
}
}
async fn get_als_integration_time_file_descriptor(
&self,
) -> Result<zbus::zvariant::OwnedFd, zbus::fdo::Error> {
// Get the file descriptor for the als integration time sysfs path
// /sys/devices/platform/AMDI0010:00/i2c-0/i2c-PRP0001:01/iio:device0/in_illuminance_integration_time
// Return -1 on error
let result = File::create("/sys/devices/platform/AMDI0010:00/i2c-0/i2c-PRP0001:01/iio:device0/in_illuminance_integration_time").await;
match result {
Ok(f) => {
let raw = f.into_std().await.into_raw_fd();
unsafe {
let fd: OwnedFd = OwnedFd::from_raw_fd(raw);
Ok(fd)
}
}
Err(message) => {
println!("Error opening sysfs file for giving file descriptor {message}");
Err(zbus::fdo::Error::IOError(message.to_string()))
}
} }
} }
@ -243,4 +339,3 @@ impl SMManager {
SMManager::API_VERSION SMManager::API_VERSION
} }
} }