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",
]
[[package]]
name = "dyn"
version = "0.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd5d33be9d461be19ff7168302689ed4ca466300600546c93795e845d5fa3faf"
[[package]]
name = "enumflags2"
version = "0.7.8"
@ -778,18 +772,18 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.188"
version = "1.0.192"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e"
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.188"
version = "1.0.192"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2"
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
dependencies = [
"proc-macro2",
"quote",
@ -798,9 +792,9 @@ dependencies = [
[[package]]
name = "serde_repr"
version = "0.1.16"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00"
checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145"
dependencies = [
"proc-macro2",
"quote",
@ -876,8 +870,6 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
name = "steamos-manager"
version = "0.9.0"
dependencies = [
"dyn",
"serde",
"tokio",
"zbus",
"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
[profile.release]
strip="symbols"
[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"] }
zbus = { version = "3.14.1", features = ["tokio"] }
zbus_macros = "3.14.1"

View file

@ -172,15 +172,14 @@
</method>
<!--
SetALSIntegrationTime:
@seconds: The number of seconds to use for ALS integration.
@success: True on success. False otherwise.
GetAlsIntegrationTimeFileDescriptor:
@descriptor: A unix file descriptor that can be written to to set ALS integration time.
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">
<arg type="i" name="seconds" direction="in"/>
<arg type="b" name="success" direction="out"/>
<method name="GetAlsIntegrationTimeFileDescriptor">
<arg type="h" name="descriptor" direction="out"/>
</method>
</interface>

View file

@ -28,21 +28,19 @@ use zbus::{ConnectionBuilder, Result};
pub mod manager;
#[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
// level things. It implements com.steampowered.SteamOSManager1 interface
let manager = manager::SMManager {};
let _system_connection = ConnectionBuilder::system()?
.name("com.steampowered.SteamOSManager1")?
.serve_at("/com/steampowered/SteamOSManager1", manager)?
.build()
.await?;
loop
{
.name("com.steampowered.SteamOSManager1")?
.serve_at("/com/steampowered/SteamOSManager1", manager)?
.build()
.await?;
loop {
std::future::pending::<()>().await;
}
}

View file

@ -23,13 +23,19 @@
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
use std::{ffi::OsStr};
use tokio::{process::Command, fs::File, io::AsyncWriteExt};
use std::{
ffi::OsStr,
os::fd::{FromRawFd, IntoRawFd},
};
use tokio::{fs::File, io::AsyncWriteExt, process::Command};
use zbus::zvariant::OwnedFd;
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
let mut child = Command::new(executable)
.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
match script_exit_code(executable, args).await {
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
let output = Command::new(executable)
.args(args).output();
let output = Command::new(executable).args(args).output();
let output = output.await?;
@ -66,11 +77,10 @@ async fn script_output(executable: &str, args: &[impl AsRef<OsStr>]) -> Result<S
impl SMManager {
const API_VERSION: u32 = 1;
async fn say_hello(&self, name: &str) -> String {
format!("Hello {}!", name)
}
async fn factory_reset(&self) -> bool {
// Run steamos factory reset script and return true on success
run_script("factory reset", "steamos-factory-reset-config", &[""]).await
@ -78,15 +88,30 @@ impl SMManager {
async fn disable_wifi_power_management(&self) -> bool {
// 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 {
// Run what steamos-polkit-helpers/jupiter-fan-control does
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 {
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 {
// 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;
match result {
Ok(as_string) => value = as_string.trim().parse().unwrap(),
Err(message) => println!("Unable to run als calibration script : {}", message),
}
value
}
async fn update_bios(&self) -> bool {
// Update the bios as needed
// 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 {
// Update the dock firmware as needed
// 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 {
// Run steamos-trim-devices script
// 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 {
// Run steamos-format-sdcard script
// 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 {
// Set given level to sysfs path /sys/class/drm/card0/device/power_dpm_force_performance_level
// Levels are defined below
// return true if able to write, false otherwise or if level is out of range, etc.
let levels = [
"auto",
"low",
"high",
"manual",
"peak_performance"
];
let levels = ["auto", "low", "high", "manual", "peak_performance"];
if level < 0 || level >= levels.len() as i32 {
return false;
}
// Open sysfs file
let result = File::create("/sys/class/drm/card0/device/power_dpm_force_performance_level").await;
let mut myfile;
let result =
File::create("/sys/class/drm/card0/device/power_dpm_force_performance_level").await;
let mut myfile;
match result {
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
let result = myfile.write_all(levels[level as usize].as_bytes()).await;
match result {
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;
match result {
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
@ -190,16 +243,25 @@ impl SMManager {
let result = myfile.write("c\n".as_bytes()).await;
match result {
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 {
// Set TDP limit given if within range (3-15)
// Returns false on error or out of range
@ -212,14 +274,20 @@ impl SMManager {
let mut power1file;
match result {
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 mut power2file;
match result {
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
@ -230,10 +298,38 @@ impl SMManager {
let result = power2file.write(data.as_bytes()).await;
match result {
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
}
}