Cargo fmt

This commit is contained in:
NGnius (Graham) 2023-03-27 21:11:22 -04:00
parent 2c0cac125c
commit 54393cd0cb
38 changed files with 1725 additions and 1023 deletions

View file

@ -9,7 +9,10 @@ pub struct RangeLimit<T> {
impl<T> From<limits_core::json::RangeLimit<T>> for RangeLimit<T> { impl<T> From<limits_core::json::RangeLimit<T>> for RangeLimit<T> {
#[inline] #[inline]
fn from(other: limits_core::json::RangeLimit<T>) -> Self { fn from(other: limits_core::json::RangeLimit<T>) -> Self {
RangeLimit { min: other.min, max: other.max } RangeLimit {
min: other.min,
max: other.max,
}
} }
} }
@ -47,8 +50,7 @@ pub struct CpuLimits {
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct GeneralLimits { pub struct GeneralLimits {}
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct GpuLimits { pub struct GpuLimits {

View file

@ -1,29 +1,33 @@
//use usdpl_back::core::serdes::Primitive; //use usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable; use usdpl_back::AsyncCallable;
pub struct AsyncIsh<In: Send + 'static, pub struct AsyncIsh<
In: Send + 'static,
Out: Send + 'static, Out: Send + 'static,
TS: (Fn(super::ApiParameterType) -> Result<In, String>) + Send + Sync, TS: (Fn(super::ApiParameterType) -> Result<In, String>) + Send + Sync,
Gen: (Fn() -> SG) + Send + Sync, Gen: (Fn() -> SG) + Send + Sync,
SG: (Fn(In) -> Out) + Send + Sync + 'static, SG: (Fn(In) -> Out) + Send + Sync + 'static,
TG: (Fn(Out) -> super::ApiParameterType) + Send + Sync> { TG: (Fn(Out) -> super::ApiParameterType) + Send + Sync,
> {
pub trans_setter: TS, // assumed to be pretty fast pub trans_setter: TS, // assumed to be pretty fast
pub set_get: Gen, // probably has locks (i.e. slow) pub set_get: Gen, // probably has locks (i.e. slow)
pub trans_getter: TG, // assumed to be pretty fast pub trans_getter: TG, // assumed to be pretty fast
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl <In: Send + 'static, impl<
Out: Send + 'static, In: Send + 'static,
TS: (Fn(super::ApiParameterType) -> Result<In, String>) + Send + Sync, Out: Send + 'static,
Gen: (Fn() -> SG) + Send + Sync, TS: (Fn(super::ApiParameterType) -> Result<In, String>) + Send + Sync,
SG: (Fn(In) -> Out) + Send + Sync + 'static, Gen: (Fn() -> SG) + Send + Sync,
TG: (Fn(Out) -> super::ApiParameterType) + Send + Sync> SG: (Fn(In) -> Out) + Send + Sync + 'static,
AsyncCallable for AsyncIsh<In, Out, TS, Gen, SG, TG> { TG: (Fn(Out) -> super::ApiParameterType) + Send + Sync,
> AsyncCallable for AsyncIsh<In, Out, TS, Gen, SG, TG>
{
async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType { async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType {
let t_to_set = match (self.trans_setter)(params) { let t_to_set = match (self.trans_setter)(params) {
Ok(t) => t, Ok(t) => t,
Err(e) => return vec![e.into()] Err(e) => return vec![e.into()],
}; };
let setter = (self.set_get)(); let setter = (self.set_get)();
let t_got = match tokio::task::spawn_blocking(move || setter(t_to_set)).await { let t_got = match tokio::task::spawn_blocking(move || setter(t_to_set)).await {
@ -34,20 +38,24 @@ impl <In: Send + 'static,
} }
} }
pub struct AsyncIshGetter<T: Send + 'static, pub struct AsyncIshGetter<
T: Send + 'static,
Gen: (Fn() -> G) + Send + Sync, Gen: (Fn() -> G) + Send + Sync,
G: (Fn() -> T) + Send + Sync + 'static, G: (Fn() -> T) + Send + Sync + 'static,
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> { TG: (Fn(T) -> super::ApiParameterType) + Send + Sync,
pub set_get: Gen, // probably has locks (i.e. slow) > {
pub set_get: Gen, // probably has locks (i.e. slow)
pub trans_getter: TG, // assumed to be pretty fast pub trans_getter: TG, // assumed to be pretty fast
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl <T: Send + 'static, impl<
Gen: (Fn() -> G) + Send + Sync, T: Send + 'static,
G: (Fn() -> T) + Send + Sync + 'static, Gen: (Fn() -> G) + Send + Sync,
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> G: (Fn() -> T) + Send + Sync + 'static,
AsyncCallable for AsyncIshGetter<T, Gen, G, TG> { TG: (Fn(T) -> super::ApiParameterType) + Send + Sync,
> AsyncCallable for AsyncIshGetter<T, Gen, G, TG>
{
async fn call(&self, _params: super::ApiParameterType) -> super::ApiParameterType { async fn call(&self, _params: super::ApiParameterType) -> super::ApiParameterType {
let getter = (self.set_get)(); let getter = (self.set_get)();
let t_got = match tokio::task::spawn_blocking(move || getter()).await { let t_got = match tokio::task::spawn_blocking(move || getter()).await {
@ -63,7 +71,9 @@ pub struct Blocking<F: (Fn(super::ApiParameterType) -> super::ApiParameterType)
} }
#[async_trait::async_trait] #[async_trait::async_trait]
impl <F: (Fn(super::ApiParameterType) -> super::ApiParameterType) + Send + Sync> AsyncCallable for Blocking<F> { impl<F: (Fn(super::ApiParameterType) -> super::ApiParameterType) + Send + Sync> AsyncCallable
for Blocking<F>
{
async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType { async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType {
(self.func)(params) (self.func)(params)
} }

View file

@ -1,4 +1,4 @@
use std::sync::mpsc::{Sender, self}; use std::sync::mpsc::{self, Sender};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use usdpl_back::core::serdes::Primitive; use usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable; use usdpl_back::AsyncCallable;
@ -6,24 +6,27 @@ use usdpl_back::AsyncCallable;
use super::handler::{ApiMessage, BatteryMessage}; use super::handler::{ApiMessage, BatteryMessage};
/// Current current (ha!) web method /// Current current (ha!) web method
pub fn current_now( pub fn current_now(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |val: Option<f64>| tx.send(val).expect("current_now callback send failed"); let callback =
sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadCurrentNow(Box::new(callback)))).expect("current_now send failed"); move |val: Option<f64>| tx.send(val).expect("current_now callback send failed");
sender2
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::ReadCurrentNow(
Box::new(callback),
)))
.expect("current_now send failed");
rx.recv().expect("current_now callback recv failed") rx.recv().expect("current_now callback recv failed")
} }
}; };
super::async_utils::AsyncIshGetter { super::async_utils::AsyncIshGetter {
set_get: getter, set_get: getter,
trans_getter: |result| { trans_getter: |result| super::utility::map_optional_result(Ok(result)),
super::utility::map_optional_result(Ok(result))
}
} }
} }
@ -33,68 +36,77 @@ pub fn current_now(
}*/ }*/
/// Charge now web method /// Charge now web method
pub fn charge_now( pub fn charge_now(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |val: Option<f64>| tx.send(val).expect("charge_now callback send failed"); let callback =
sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadChargeNow(Box::new(callback)))).expect("charge_now send failed"); move |val: Option<f64>| tx.send(val).expect("charge_now callback send failed");
sender2
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::ReadChargeNow(
Box::new(callback),
)))
.expect("charge_now send failed");
rx.recv().expect("charge_now callback recv failed") rx.recv().expect("charge_now callback recv failed")
} }
}; };
super::async_utils::AsyncIshGetter { super::async_utils::AsyncIshGetter {
set_get: getter, set_get: getter,
trans_getter: |result| { trans_getter: |result| super::utility::map_optional_result(Ok(result)),
super::utility::map_optional_result(Ok(result))
}
} }
} }
/// Charge full web method /// Charge full web method
pub fn charge_full( pub fn charge_full(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |val: Option<f64>| tx.send(val).expect("charge_full callback send failed"); let callback =
sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadChargeFull(Box::new(callback)))).expect("charge_full send failed"); move |val: Option<f64>| tx.send(val).expect("charge_full callback send failed");
sender2
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::ReadChargeFull(
Box::new(callback),
)))
.expect("charge_full send failed");
rx.recv().expect("charge_full callback recv failed") rx.recv().expect("charge_full callback recv failed")
} }
}; };
super::async_utils::AsyncIshGetter { super::async_utils::AsyncIshGetter {
set_get: getter, set_get: getter,
trans_getter: |result| { trans_getter: |result| super::utility::map_optional_result(Ok(result)),
super::utility::map_optional_result(Ok(result))
}
} }
} }
/// Charge design web method /// Charge design web method
pub fn charge_design( pub fn charge_design(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |val: Option<f64>| tx.send(val).expect("charge_design callback send failed"); let callback =
sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::ReadChargeDesign(Box::new(callback)))).expect("charge_design send failed"); move |val: Option<f64>| tx.send(val).expect("charge_design callback send failed");
sender2
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::ReadChargeDesign(
Box::new(callback),
)))
.expect("charge_design send failed");
rx.recv().expect("charge_design callback recv failed") rx.recv().expect("charge_design callback recv failed")
} }
}; };
super::async_utils::AsyncIshGetter { super::async_utils::AsyncIshGetter {
set_get: getter, set_get: getter,
trans_getter: |result| { trans_getter: |result| super::utility::map_optional_result(Ok(result)),
super::utility::map_optional_result(Ok(result))
}
} }
} }
@ -103,11 +115,15 @@ pub fn set_charge_rate(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |rate: f64| let setter = move |rate: f64| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Battery(BatteryMessage::SetChargeRate(Some(rate as u64)))) .send(ApiMessage::Battery(BatteryMessage::SetChargeRate(Some(
.expect("set_charge_rate send failed"); rate as u64,
))))
.expect("set_charge_rate send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(new_val)) = params_in.get(0) { if let Some(&Primitive::F64(new_val)) = params_in.get(0) {
setter(new_val); setter(new_val);
@ -125,13 +141,18 @@ pub fn get_charge_rate(
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |rate: Option<u64>| tx.send(rate).expect("get_charge_rate callback send failed"); let callback =
sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::GetChargeRate(Box::new(callback)))).expect("get_charge_rate send failed"); move |rate: Option<u64>| tx.send(rate).expect("get_charge_rate callback send failed");
sender
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::GetChargeRate(
Box::new(callback),
)))
.expect("get_charge_rate send failed");
rx.recv().expect("get_charge_rate callback recv failed") rx.recv().expect("get_charge_rate callback recv failed")
}; };
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)]
vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)]
}
} }
/// Generate unset battery charge rate web method /// Generate unset battery charge rate web method
@ -139,7 +160,13 @@ pub fn unset_charge_rate(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move || sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::SetChargeRate(None))).expect("unset_charge_rate send failed"); let setter = move || {
sender
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::SetChargeRate(None)))
.expect("unset_charge_rate send failed")
};
move |_params_in: super::ApiParameterType| { move |_params_in: super::ApiParameterType| {
setter(); setter();
vec![true.into()] vec![true.into()]
@ -151,11 +178,15 @@ pub fn set_charge_mode(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |mode: String| let setter = move |mode: String| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Battery(BatteryMessage::SetChargeMode(Some(mode)))) .send(ApiMessage::Battery(BatteryMessage::SetChargeMode(Some(
.expect("set_charge_mode send failed"); mode,
))))
.expect("set_charge_mode send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::String(new_val)) = params_in.get(0) { if let Some(Primitive::String(new_val)) = params_in.get(0) {
setter(new_val.to_owned()); setter(new_val.to_owned());
@ -173,13 +204,19 @@ pub fn get_charge_mode(
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |mode: Option<String>| tx.send(mode).expect("get_charge_mode callback send failed"); let callback = move |mode: Option<String>| {
sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::GetChargeMode(Box::new(callback)))).expect("get_charge_mode send failed"); tx.send(mode).expect("get_charge_mode callback send failed")
};
sender
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::GetChargeMode(
Box::new(callback),
)))
.expect("get_charge_mode send failed");
rx.recv().expect("get_charge_mode callback recv failed") rx.recv().expect("get_charge_mode callback recv failed")
}; };
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)]
vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)]
}
} }
/// Generate unset battery charge mode web method /// Generate unset battery charge mode web method
@ -187,7 +224,13 @@ pub fn unset_charge_mode(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move || sender.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::SetChargeMode(None))).expect("unset_charge_mode send failed"); let setter = move || {
sender
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::SetChargeMode(None)))
.expect("unset_charge_mode send failed")
};
move |_params_in: super::ApiParameterType| { move |_params_in: super::ApiParameterType| {
setter(); setter();
vec![true.into()] vec![true.into()]
@ -200,7 +243,11 @@ pub fn on_unplugged(
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
move |_| { move |_| {
sender.lock().unwrap().send(ApiMessage::OnUnplugged).expect("on_unplugged send failed"); sender
.lock()
.unwrap()
.send(ApiMessage::OnUnplugged)
.expect("on_unplugged send failed");
vec![true.into()] vec![true.into()]
} }
} }
@ -211,7 +258,11 @@ pub fn on_plugged(
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
move |_| { move |_| {
sender.lock().unwrap().send(ApiMessage::OnPluggedIn).expect("on_plugged send failed"); sender
.lock()
.unwrap()
.send(ApiMessage::OnPluggedIn)
.expect("on_plugged send failed");
vec![true.into()] vec![true.into()]
} }
} }
@ -221,11 +272,15 @@ pub fn set_charge_limit(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |limit: f64| let setter = move |limit: f64| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Battery(BatteryMessage::SetChargeLimit(Some(limit)))) .send(ApiMessage::Battery(BatteryMessage::SetChargeLimit(Some(
.expect("set_charge_limit send failed"); limit,
))))
.expect("set_charge_limit send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(new_val)) = params_in.get(0) { if let Some(&Primitive::F64(new_val)) = params_in.get(0) {
setter(new_val); setter(new_val);
@ -241,11 +296,13 @@ pub fn unset_charge_limit(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let unsetter = move || let unsetter = move || {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Battery(BatteryMessage::SetChargeLimit(None))) .send(ApiMessage::Battery(BatteryMessage::SetChargeLimit(None)))
.expect("unset_charge_limit send failed"); .expect("unset_charge_limit send failed")
};
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
unsetter(); unsetter();
vec![true.into()] vec![true.into()]
@ -253,23 +310,27 @@ pub fn unset_charge_limit(
} }
/// Charge design web method /// Charge design web method
pub fn get_charge_limit( pub fn get_charge_limit(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |val: Option<f64>| tx.send(val).expect("get_charge_limit callback send failed"); let callback = move |val: Option<f64>| {
sender2.lock().unwrap().send(ApiMessage::Battery(BatteryMessage::GetChargeLimit(Box::new(callback)))).expect("get_charge_limit send failed"); tx.send(val).expect("get_charge_limit callback send failed")
};
sender2
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::GetChargeLimit(
Box::new(callback),
)))
.expect("get_charge_limit send failed");
rx.recv().expect("get_charge_limit callback recv failed") rx.recv().expect("get_charge_limit callback recv failed")
} }
}; };
super::async_utils::AsyncIshGetter { super::async_utils::AsyncIshGetter {
set_get: getter, set_get: getter,
trans_getter: |result| { trans_getter: |result| super::utility::map_optional_result(Ok(result)),
super::utility::map_optional_result(Ok(result))
}
} }
} }

View file

@ -1,9 +1,9 @@
use std::sync::mpsc::{Sender, self}; use std::sync::mpsc::{self, Sender};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use usdpl_back::core::serdes::Primitive; use usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable; use usdpl_back::AsyncCallable;
use crate::settings::{SettingError, SettingVariant, MinMax}; use crate::settings::{MinMax, SettingError, SettingVariant};
//use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal};
use super::handler::{ApiMessage, CpuMessage}; use super::handler::{ApiMessage, CpuMessage};
@ -12,13 +12,11 @@ pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType {
super::utility::map_result( super::utility::map_result(
crate::settings::steam_deck::Cpus::cpu_count() crate::settings::steam_deck::Cpus::cpu_count()
.map(|x| x as u64) .map(|x| x as u64)
.ok_or_else( .ok_or_else(|| SettingError {
|| SettingError { msg: "Failed to parse CPU count".to_owned(),
msg: "Failed to parse CPU count".to_owned(), setting: SettingVariant::Cpu,
setting: SettingVariant::Cpu, }),
} )
)
)
} }
/// Generate set CPU online web method /// Generate set CPU online web method
@ -26,10 +24,13 @@ pub fn set_cpu_online(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, value: bool| let setter = move |index: usize, value: bool| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpuOnline(index, value))).expect("set_cpu_online send failed"); .send(ApiMessage::Cpu(CpuMessage::SetCpuOnline(index, value)))
.expect("set_cpu_online send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(index)) = params_in.get(0) { if let Some(&Primitive::F64(index)) = params_in.get(0) {
//let mut settings_lock = unwrap_lock(settings.lock(), "cpu"); //let mut settings_lock = unwrap_lock(settings.lock(), "cpu");
@ -49,10 +50,13 @@ pub fn set_cpus_online(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |values: Vec<bool>| let setter = move |values: Vec<bool>| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpusOnline(values))).expect("set_cpus_online send failed"); .send(ApiMessage::Cpu(CpuMessage::SetCpusOnline(values)))
.expect("set_cpus_online send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
let mut result = Vec::with_capacity(params_in.len()); let mut result = Vec::with_capacity(params_in.len());
let mut values = Vec::with_capacity(params_in.len()); let mut values = Vec::with_capacity(params_in.len());
@ -90,16 +94,19 @@ pub fn set_cpus_online(
} }
}*/ }*/
pub fn set_smt( pub fn set_smt(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move |smt: bool| { move |smt: bool| {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<bool>| tx.send(values).expect("set_smt callback send failed"); let callback =
sender2.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::SetSmt(smt, Box::new(callback)))).expect("set_smt send failed"); move |values: Vec<bool>| tx.send(values).expect("set_smt callback send failed");
sender2
.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetSmt(smt, Box::new(callback))))
.expect("set_smt send failed");
rx.recv().expect("set_smt callback recv failed") rx.recv().expect("set_smt callback recv failed")
} }
}; };
@ -118,41 +125,48 @@ pub fn set_smt(
output.push(status.into()); output.push(status.into());
} }
output output
} },
} }
} }
pub fn get_smt( pub fn get_smt(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |value: bool| tx.send(value).expect("get_smt callback send failed"); let callback = move |value: bool| tx.send(value).expect("get_smt callback send failed");
sender2.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetSmt(Box::new(callback)))).expect("get_smt send failed"); sender2
.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::GetSmt(Box::new(callback))))
.expect("get_smt send failed");
rx.recv().expect("get_smt callback recv failed") rx.recv().expect("get_smt callback recv failed")
} }
}; };
super::async_utils::AsyncIshGetter { super::async_utils::AsyncIshGetter {
set_get: getter, set_get: getter,
trans_getter: |result| { trans_getter: |result| vec![result.into()],
vec![result.into()]
}
} }
} }
pub fn get_cpus_online( pub fn get_cpus_online(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<bool>| tx.send(values).expect("get_cpus_online callback send failed"); let callback = move |values: Vec<bool>| {
sender2.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusOnline(Box::new(callback)))).expect("get_cpus_online send failed"); tx.send(values)
.expect("get_cpus_online callback send failed")
};
sender2
.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::GetCpusOnline(Box::new(
callback,
))))
.expect("get_cpus_online send failed");
rx.recv().expect("get_cpus_online callback recv failed") rx.recv().expect("get_cpus_online callback recv failed")
} }
}; };
@ -164,7 +178,7 @@ pub fn get_cpus_online(
output.push(status.into()); output.push(status.into());
} }
output output
} },
} }
} }
@ -172,25 +186,29 @@ pub fn set_clock_limits(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, value: MinMax<u64>| let setter = move |index: usize, value: MinMax<u64>| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetClockLimits(index, Some(value)))).expect("set_clock_limits send failed"); .send(ApiMessage::Cpu(CpuMessage::SetClockLimits(
index,
Some(value),
)))
.expect("set_clock_limits send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(index)) = params_in.get(0) { if let Some(&Primitive::F64(index)) = params_in.get(0) {
if let Some(&Primitive::F64(min)) = params_in.get(1) { if let Some(&Primitive::F64(min)) = params_in.get(1) {
if let Some(&Primitive::F64(max)) = params_in.get(2) { if let Some(&Primitive::F64(max)) = params_in.get(2) {
let safe_max = if max < min { let safe_max = if max < min { min } else { max };
min let safe_min = if min > max { max } else { min };
} else { setter(
max index as usize,
}; MinMax {
let safe_min = if min > max { min: safe_min as u64,
max max: safe_max as u64,
} else { },
min );
};
setter(index as usize, MinMax {min: safe_min as u64, max: safe_max as u64});
vec![safe_min.into(), safe_max.into()] vec![safe_min.into(), safe_max.into()]
} else { } else {
vec!["set_clock_limits missing parameter 2".into()] vec!["set_clock_limits missing parameter 2".into()]
@ -210,8 +228,18 @@ pub fn get_clock_limits(
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move |index: usize| { let getter = move |index: usize| {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |values: Option<MinMax<u64>>| tx.send(values).expect("get_clock_limits callback send failed"); let callback = move |values: Option<MinMax<u64>>| {
sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetClockLimits(index, Box::new(callback)))).expect("get_clock_limits send failed"); tx.send(values)
.expect("get_clock_limits callback send failed")
};
sender
.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::GetClockLimits(
index,
Box::new(callback),
)))
.expect("get_clock_limits send failed");
rx.recv().expect("get_clock_limits callback recv failed") rx.recv().expect("get_clock_limits callback recv failed")
}; };
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
@ -231,10 +259,13 @@ pub fn unset_clock_limits(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize| let setter = move |index: usize| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetClockLimits(index, None))).expect("unset_clock_limits send failed"); .send(ApiMessage::Cpu(CpuMessage::SetClockLimits(index, None)))
.expect("unset_clock_limits send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(index)) = params_in.get(0) { if let Some(&Primitive::F64(index)) = params_in.get(0) {
setter(index as usize); setter(index as usize);
@ -249,10 +280,13 @@ pub fn set_cpu_governor(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, governor: String| let setter = move |index: usize, governor: String| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpuGovernor(index, governor))).expect("set_cpu_governor send failed"); .send(ApiMessage::Cpu(CpuMessage::SetCpuGovernor(index, governor)))
.expect("set_cpu_governor send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(index)) = params_in.get(0) { if let Some(&Primitive::F64(index)) = params_in.get(0) {
if let Some(Primitive::String(governor)) = params_in.get(1) { if let Some(Primitive::String(governor)) = params_in.get(1) {
@ -271,10 +305,13 @@ pub fn set_cpus_governors(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |governors: Vec<String>| let setter = move |governors: Vec<String>| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Cpu(CpuMessage::SetCpusGovernor(governors))).expect("set_cpus_governor send failed"); .send(ApiMessage::Cpu(CpuMessage::SetCpusGovernor(governors)))
.expect("set_cpus_governor send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
let mut result = Vec::with_capacity(params_in.len()); let mut result = Vec::with_capacity(params_in.len());
let mut values = Vec::with_capacity(params_in.len()); let mut values = Vec::with_capacity(params_in.len());
@ -298,8 +335,17 @@ pub fn get_cpu_governors(
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<String>| tx.send(values).expect("get_cpu_governors callback send failed"); let callback = move |values: Vec<String>| {
sender.lock().unwrap().send(ApiMessage::Cpu(CpuMessage::GetCpusGovernor(Box::new(callback)))).expect("get_cpu_governors send failed"); tx.send(values)
.expect("get_cpu_governors callback send failed")
};
sender
.lock()
.unwrap()
.send(ApiMessage::Cpu(CpuMessage::GetCpusGovernor(Box::new(
callback,
))))
.expect("get_cpu_governors send failed");
rx.recv().expect("get_cpu_governors callback recv failed") rx.recv().expect("get_cpu_governors callback recv failed")
}; };
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {

View file

@ -1,4 +1,4 @@
use std::sync::mpsc::{Sender, self}; use std::sync::mpsc::{self, Sender};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use usdpl_back::core::serdes::Primitive; use usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable; use usdpl_back::AsyncCallable;
@ -11,10 +11,13 @@ pub fn set_persistent(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |pers: bool| let setter = move |pers: bool| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::General(GeneralMessage::SetPersistent(pers))).expect("set_persistent send failed"); .send(ApiMessage::General(GeneralMessage::SetPersistent(pers)))
.expect("set_persistent send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(&Primitive::Bool(new_val)) = params_in.get(0) { if let Some(&Primitive::Bool(new_val)) = params_in.get(0) {
setter(new_val); setter(new_val);
@ -33,13 +36,18 @@ pub fn get_persistent(
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |value: bool| tx.send(value).expect("get_persistent callback send failed"); let callback =
sender.lock().unwrap().send(ApiMessage::General(GeneralMessage::GetPersistent(Box::new(callback)))).expect("get_persistent send failed"); move |value: bool| tx.send(value).expect("get_persistent callback send failed");
sender
.lock()
.unwrap()
.send(ApiMessage::General(GeneralMessage::GetPersistent(
Box::new(callback),
)))
.expect("get_persistent send failed");
rx.recv().expect("get_persistent callback recv failed") rx.recv().expect("get_persistent callback recv failed")
}; };
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| vec![getter().into()]
vec![getter().into()]
}
} }
/// Generate load app settings from file web method /// Generate load app settings from file web method
@ -47,10 +55,13 @@ pub fn load_settings(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |path: i64, name: String| let setter = move |path: i64, name: String| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::LoadSettings(path, name)).expect("load_settings send failed"); .send(ApiMessage::LoadSettings(path, name))
.expect("load_settings send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(Primitive::F64(id)) = params_in.get(0) { if let Some(Primitive::F64(id)) = params_in.get(0) {
if let Some(Primitive::String(name)) = params_in.get(1) { if let Some(Primitive::String(name)) = params_in.get(1) {
@ -73,10 +84,13 @@ pub fn load_default_settings(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move || let setter = move || {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::LoadMainSettings).expect("load_default_settings send failed"); .send(ApiMessage::LoadMainSettings)
.expect("load_default_settings send failed")
};
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
setter(); setter();
vec![true.into()] vec![true.into()]
@ -99,10 +113,13 @@ pub fn load_system_settings(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move || let setter = move || {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::LoadSystemSettings).expect("load_default_settings send failed"); .send(ApiMessage::LoadSystemSettings)
.expect("load_default_settings send failed")
};
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
setter(); setter();
vec![true.into()] vec![true.into()]
@ -121,68 +138,75 @@ pub fn load_system_settings(
} }
/// Generate get current settings name /// Generate get current settings name
pub fn get_name( pub fn get_name(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |name: String| tx.send(name).expect("get_name callback send failed"); let callback =
sender2.lock().unwrap().send(ApiMessage::General(GeneralMessage::GetCurrentProfileName(Box::new(callback)))).expect("get_name send failed"); move |name: String| tx.send(name).expect("get_name callback send failed");
sender2
.lock()
.unwrap()
.send(ApiMessage::General(GeneralMessage::GetCurrentProfileName(
Box::new(callback),
)))
.expect("get_name send failed");
rx.recv().expect("get_name callback recv failed") rx.recv().expect("get_name callback recv failed")
} }
}; };
super::async_utils::AsyncIshGetter { super::async_utils::AsyncIshGetter {
set_get: getter, set_get: getter,
trans_getter: |result| { trans_getter: |result| vec![result.into()],
vec![result.into()]
}
} }
} }
/// Generate get current settings name /// Generate get current settings name
pub fn get_path( pub fn get_path(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |name: std::path::PathBuf| tx.send(name).expect("get_path callback send failed"); let callback = move |name: std::path::PathBuf| {
sender2.lock().unwrap().send(ApiMessage::General(GeneralMessage::GetPath(Box::new(callback)))).expect("get_name send failed"); tx.send(name).expect("get_path callback send failed")
};
sender2
.lock()
.unwrap()
.send(ApiMessage::General(GeneralMessage::GetPath(Box::new(
callback,
))))
.expect("get_name send failed");
rx.recv().expect("get_path callback recv failed") rx.recv().expect("get_path callback recv failed")
} }
}; };
super::async_utils::AsyncIshGetter { super::async_utils::AsyncIshGetter {
set_get: getter, set_get: getter,
trans_getter: |result| { trans_getter: |result| vec![result.to_string_lossy().to_string().into()],
vec![result.to_string_lossy().to_string().into()]
}
} }
} }
/// Generate wait for all locks to be available web method /// Generate wait for all locks to be available web method
pub fn lock_unlock_all( pub fn lock_unlock_all(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |x| tx.send(x).expect("lock_unlock_all callback send failed"); let callback = move |x| tx.send(x).expect("lock_unlock_all callback send failed");
sender2.lock().unwrap().send(ApiMessage::WaitForEmptyQueue(Box::new(callback))).expect("lock_unlock_all send failed"); sender2
.lock()
.unwrap()
.send(ApiMessage::WaitForEmptyQueue(Box::new(callback)))
.expect("lock_unlock_all send failed");
rx.recv().expect("lock_unlock_all callback recv failed") rx.recv().expect("lock_unlock_all callback recv failed")
} }
}; };
super::async_utils::AsyncIshGetter { super::async_utils::AsyncIshGetter {
set_get: getter, set_get: getter,
trans_getter: |_| { trans_getter: |_| vec![true.into()],
vec![true.into()]
}
} }
} }
@ -193,8 +217,14 @@ pub fn get_limits(
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |value: super::SettingsLimits| tx.send(value).expect("get_limits callback send failed"); let callback = move |value: super::SettingsLimits| {
sender.lock().unwrap().send(ApiMessage::GetLimits(Box::new(callback))).expect("get_limits send failed"); tx.send(value).expect("get_limits callback send failed")
};
sender
.lock()
.unwrap()
.send(ApiMessage::GetLimits(Box::new(callback)))
.expect("get_limits send failed");
rx.recv().expect("get_limits callback recv failed") rx.recv().expect("get_limits callback recv failed")
}; };
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
@ -203,16 +233,20 @@ pub fn get_limits(
} }
/// Generate get current driver name /// Generate get current driver name
pub fn get_provider( pub fn get_provider(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move |provider_name: String| { move |provider_name: String| {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |name: crate::persist::DriverJson| tx.send(name).expect("get_provider callback send failed"); let callback = move |name: crate::persist::DriverJson| {
sender2.lock().unwrap().send(ApiMessage::GetProvider(provider_name, Box::new(callback))).expect("get_provider send failed"); tx.send(name).expect("get_provider callback send failed")
};
sender2
.lock()
.unwrap()
.send(ApiMessage::GetProvider(provider_name, Box::new(callback)))
.expect("get_provider send failed");
rx.recv().expect("get_provider callback recv failed") rx.recv().expect("get_provider callback recv failed")
} }
}; };
@ -225,9 +259,7 @@ pub fn get_provider(
} }
}, },
set_get: getter, set_get: getter,
trans_getter: |result| { trans_getter: |result| vec![format!("{:?}", result).into()],
vec![format!("{:?}", result).into()]
}
} }
} }
@ -277,14 +309,15 @@ pub fn force_apply(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |_: ()| let setter = move |_: ()| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::General(GeneralMessage::ApplyNow)) .send(ApiMessage::General(GeneralMessage::ApplyNow))
.expect("force_apply send failed"); .expect("force_apply send failed")
};
move |_params_in: super::ApiParameterType| { move |_params_in: super::ApiParameterType| {
setter(()); setter(());
vec![true.into()] vec![true.into()]
} }
} }

View file

@ -1,5 +1,5 @@
use std::sync::mpsc::{Sender, self}; use std::sync::mpsc::{self, Sender};
use std::sync::{Mutex, Arc}; use std::sync::{Arc, Mutex};
use usdpl_back::core::serdes::Primitive; use usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable; use usdpl_back::AsyncCallable;
@ -11,10 +11,13 @@ pub fn set_ppt(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |fast: u64, slow: u64| let setter = move |fast: u64, slow: u64| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetPpt(Some(fast), Some(slow)))).expect("set_ppt send failed"); .send(ApiMessage::Gpu(GpuMessage::SetPpt(Some(fast), Some(slow))))
.expect("set_ppt send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(fast_ppt)) = params_in.get(0) { if let Some(&Primitive::F64(fast_ppt)) = params_in.get(0) {
if let Some(&Primitive::F64(slow_ppt)) = params_in.get(1) { if let Some(&Primitive::F64(slow_ppt)) = params_in.get(1) {
@ -29,16 +32,20 @@ pub fn set_ppt(
} }
} }
pub fn get_ppt( pub fn get_ppt(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |ppt: (Option<u64>, Option<u64>)| tx.send(ppt).expect("get_ppt callback send failed"); let callback = move |ppt: (Option<u64>, Option<u64>)| {
sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetPpt(Box::new(callback)))).expect("get_ppt send failed"); tx.send(ppt).expect("get_ppt callback send failed")
};
sender2
.lock()
.unwrap()
.send(ApiMessage::Gpu(GpuMessage::GetPpt(Box::new(callback))))
.expect("get_ppt send failed");
rx.recv().expect("get_ppt callback recv failed") rx.recv().expect("get_ppt callback recv failed")
} }
}; };
@ -49,7 +56,7 @@ pub fn get_ppt(
fast.map(|x| x.into()).unwrap_or(Primitive::Empty), fast.map(|x| x.into()).unwrap_or(Primitive::Empty),
slow.map(|x| x.into()).unwrap_or(Primitive::Empty), slow.map(|x| x.into()).unwrap_or(Primitive::Empty),
] ]
} },
} }
} }
@ -57,10 +64,13 @@ pub fn unset_ppt(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move || let setter = move || {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetPpt(None, None))).expect("set_ppt send failed"); .send(ApiMessage::Gpu(GpuMessage::SetPpt(None, None)))
.expect("set_ppt send failed")
};
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
setter(); setter();
vec![true.into()] vec![true.into()]
@ -71,23 +81,18 @@ pub fn set_clock_limits(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |value: MinMax<u64>| let setter = move |value: MinMax<u64>| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetClockLimits(Some(value)))).expect("set_clock_limits send failed"); .send(ApiMessage::Gpu(GpuMessage::SetClockLimits(Some(value))))
.expect("set_clock_limits send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(min)) = params_in.get(0) { if let Some(&Primitive::F64(min)) = params_in.get(0) {
if let Some(&Primitive::F64(max)) = params_in.get(1) { if let Some(&Primitive::F64(max)) = params_in.get(1) {
let safe_max = if max < min { let safe_max = if max < min { min } else { max };
min let safe_min = if min > max { max } else { min };
} else {
max
};
let safe_min = if min > max {
max
} else {
min
};
setter(MinMax { setter(MinMax {
min: safe_min as _, min: safe_min as _,
max: safe_max as _, max: safe_max as _,
@ -102,26 +107,33 @@ pub fn set_clock_limits(
} }
} }
pub fn get_clock_limits( pub fn get_clock_limits(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move|| { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |clocks: Option<MinMax<u64>>| tx.send(clocks).expect("get_clock_limits callback send failed"); let callback = move |clocks: Option<MinMax<u64>>| {
sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetClockLimits(Box::new(callback)))).expect("get_clock_limits send failed"); tx.send(clocks)
.expect("get_clock_limits callback send failed")
};
sender2
.lock()
.unwrap()
.send(ApiMessage::Gpu(GpuMessage::GetClockLimits(Box::new(
callback,
))))
.expect("get_clock_limits send failed");
rx.recv().expect("get_clock_limits callback recv failed") rx.recv().expect("get_clock_limits callback recv failed")
} }
}; };
super::async_utils::AsyncIshGetter { super::async_utils::AsyncIshGetter {
set_get: getter, set_get: getter,
trans_getter: |clocks: Option<MinMax<u64>>| { trans_getter: |clocks: Option<MinMax<u64>>| {
clocks.map(|x| vec![ clocks
x.min.into(), x.max.into() .map(|x| vec![x.min.into(), x.max.into()])
]).unwrap_or_else(|| vec![Primitive::Empty, Primitive::Empty]) .unwrap_or_else(|| vec![Primitive::Empty, Primitive::Empty])
} },
} }
} }
@ -129,10 +141,13 @@ pub fn unset_clock_limits(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move || let setter = move || {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetClockLimits(None))).expect("unset_clock_limits send failed"); .send(ApiMessage::Gpu(GpuMessage::SetClockLimits(None)))
.expect("unset_clock_limits send failed")
};
move |_: super::ApiParameterType| { move |_: super::ApiParameterType| {
setter(); setter();
vec![true.into()] vec![true.into()]
@ -143,10 +158,13 @@ pub fn set_slow_memory(
sender: Sender<ApiMessage>, sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |value: bool| let setter = move |value: bool| {
sender.lock() sender
.lock()
.unwrap() .unwrap()
.send(ApiMessage::Gpu(GpuMessage::SetSlowMemory(value))).expect("unset_clock_limits send failed"); .send(ApiMessage::Gpu(GpuMessage::SetSlowMemory(value)))
.expect("unset_clock_limits send failed")
};
move |params_in: super::ApiParameterType| { move |params_in: super::ApiParameterType| {
if let Some(&Primitive::Bool(memory_is_slow)) = params_in.get(0) { if let Some(&Primitive::Bool(memory_is_slow)) = params_in.get(0) {
setter(memory_is_slow); setter(memory_is_slow);
@ -157,23 +175,28 @@ pub fn set_slow_memory(
} }
} }
pub fn get_slow_memory( pub fn get_slow_memory(sender: Sender<ApiMessage>) -> impl AsyncCallable {
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || { let getter = move || {
let sender2 = sender.clone(); let sender2 = sender.clone();
move || { move || {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
let callback = move |value: bool| tx.send(value).expect("get_slow_memory callback send failed"); let callback = move |value: bool| {
sender2.lock().unwrap().send(ApiMessage::Gpu(GpuMessage::GetSlowMemory(Box::new(callback)))).expect("get_slow_memory send failed"); tx.send(value)
.expect("get_slow_memory callback send failed")
};
sender2
.lock()
.unwrap()
.send(ApiMessage::Gpu(GpuMessage::GetSlowMemory(Box::new(
callback,
))))
.expect("get_slow_memory send failed");
rx.recv().expect("get_slow_memory callback recv failed") rx.recv().expect("get_slow_memory callback recv failed")
} }
}; };
super::async_utils::AsyncIshGetter { super::async_utils::AsyncIshGetter {
set_get: getter, set_get: getter,
trans_getter: |value: bool| { trans_getter: |value: bool| vec![value.into()],
vec![value.into()]
}
} }
} }

View file

@ -1,8 +1,10 @@
use std::sync::mpsc::{self, Receiver, Sender};
use std::fmt::Write; use std::fmt::Write;
use std::sync::mpsc::{self, Receiver, Sender};
use crate::settings::{Settings, TCpus, TGpu, TBattery, TGeneral, OnSet, OnResume, MinMax, OnPowerEvent, PowerMode};
use crate::persist::SettingsJson; use crate::persist::SettingsJson;
use crate::settings::{
MinMax, OnPowerEvent, OnResume, OnSet, PowerMode, Settings, TBattery, TCpus, TGeneral, TGpu,
};
use crate::utility::unwrap_maybe_fatal; use crate::utility::unwrap_maybe_fatal;
type Callback<T> = Box<dyn FnOnce(T) + Send>; type Callback<T> = Box<dyn FnOnce(T) + Send>;
@ -84,12 +86,14 @@ impl CpuMessage {
// NOTE: "cpu" refers to the Linux kernel definition of a CPU, which is actually a hardware thread // NOTE: "cpu" refers to the Linux kernel definition of a CPU, which is actually a hardware thread
// not to be confused with a CPU chip, which usually has multiple hardware threads (cpu cores/threads) in the chip // not to be confused with a CPU chip, which usually has multiple hardware threads (cpu cores/threads) in the chip
match self { match self {
Self::SetCpuOnline(index, status) => {settings.cpus().get_mut(index).map(|c| *c.online() = status);}, Self::SetCpuOnline(index, status) => {
settings.cpus().get_mut(index).map(|c| *c.online() = status);
}
Self::SetCpusOnline(cpus) => { Self::SetCpusOnline(cpus) => {
for i in 0..cpus.len() { for i in 0..cpus.len() {
settings.cpus().get_mut(i).map(|c| *c.online() = cpus[i]); settings.cpus().get_mut(i).map(|c| *c.online() = cpus[i]);
} }
}, }
Self::SetSmt(status, cb) => { Self::SetSmt(status, cb) => {
if *settings.smt() == status { if *settings.smt() == status {
// already set, do nothing // already set, do nothing
@ -105,8 +109,8 @@ impl CpuMessage {
// for 1c:2t configs (i.e. anything with SMT2), the highest cpu core is always odd // for 1c:2t configs (i.e. anything with SMT2), the highest cpu core is always odd
// (e.g. 4c8t has CPUs 0-7, inclusive) // (e.g. 4c8t has CPUs 0-7, inclusive)
// this enables the """fake""" (i.e. odd) cpu which is disabled when SMT is set off // this enables the """fake""" (i.e. odd) cpu which is disabled when SMT is set off
if i % 2 == 0 && i+1 != cpu_count { if i % 2 == 0 && i + 1 != cpu_count {
*(settings.cpus()[i+1].online()) = true; *(settings.cpus()[i + 1].online()) = true;
} }
} else { } else {
*settings.cpus()[i].online() = should_be_online; *settings.cpus()[i].online() = should_be_online;
@ -118,7 +122,8 @@ impl CpuMessage {
for i in 0..settings.len() { for i in 0..settings.len() {
// this disables the """fake""" (odd) cpu for appearances' sake // this disables the """fake""" (odd) cpu for appearances' sake
// the kernel will automatically disable that same cpu when SMT is changed // the kernel will automatically disable that same cpu when SMT is changed
*settings.cpus()[i].online() = *settings.cpus()[i].online() && (status || i % 2 == 0); *settings.cpus()[i].online() =
*settings.cpus()[i].online() && (status || i % 2 == 0);
} }
} }
let mut result = Vec::with_capacity(settings.len()); let mut result = Vec::with_capacity(settings.len());
@ -126,25 +131,40 @@ impl CpuMessage {
result.push(*settings.cpus()[i].online()); result.push(*settings.cpus()[i].online());
} }
cb(result); cb(result);
}, }
Self::GetSmt(cb) => { Self::GetSmt(cb) => {
cb(*settings.smt()); cb(*settings.smt());
}, }
Self::GetCpusOnline(cb) => { Self::GetCpusOnline(cb) => {
let mut result = Vec::with_capacity(settings.len()); let mut result = Vec::with_capacity(settings.len());
for cpu in settings.cpus() { for cpu in settings.cpus() {
result.push(*cpu.online()); result.push(*cpu.online());
} }
cb(result); cb(result);
}, }
Self::SetClockLimits(index, clocks) => {settings.cpus().get_mut(index).map(|c| c.clock_limits(clocks));}, Self::SetClockLimits(index, clocks) => {
Self::GetClockLimits(index, cb) => {settings.cpus().get(index).map(|c| cb(c.get_clock_limits().map(|x| x.to_owned())));}, settings
Self::SetCpuGovernor(index, gov) => {settings.cpus().get_mut(index).map(|c| c.governor(gov));}, .cpus()
.get_mut(index)
.map(|c| c.clock_limits(clocks));
}
Self::GetClockLimits(index, cb) => {
settings
.cpus()
.get(index)
.map(|c| cb(c.get_clock_limits().map(|x| x.to_owned())));
}
Self::SetCpuGovernor(index, gov) => {
settings.cpus().get_mut(index).map(|c| c.governor(gov));
}
Self::SetCpusGovernor(govs) => { Self::SetCpusGovernor(govs) => {
for i in 0..govs.len() { for i in 0..govs.len() {
settings.cpus().get_mut(i).map(|c| c.governor(govs[i].clone())); settings
.cpus()
.get_mut(i)
.map(|c| c.governor(govs[i].clone()));
} }
}, }
Self::GetCpusGovernor(cb) => { Self::GetCpusGovernor(cb) => {
let mut result = Vec::with_capacity(settings.len()); let mut result = Vec::with_capacity(settings.len());
for cpu in settings.cpus() { for cpu in settings.cpus() {
@ -158,13 +178,14 @@ impl CpuMessage {
/// Message instructs the driver to modify settings /// Message instructs the driver to modify settings
fn is_modify(&self) -> bool { fn is_modify(&self) -> bool {
matches!(self, matches!(
self,
Self::SetCpuOnline(_, _) Self::SetCpuOnline(_, _)
| Self::SetCpusOnline(_) | Self::SetCpusOnline(_)
| Self::SetSmt(_, _) | Self::SetSmt(_, _)
| Self::SetClockLimits(_, _) | Self::SetClockLimits(_, _)
| Self::SetCpuGovernor(_, _) | Self::SetCpuGovernor(_, _)
| Self::SetCpusGovernor(_) | Self::SetCpusGovernor(_)
) )
} }
} }
@ -193,10 +214,9 @@ impl GpuMessage {
} }
fn is_modify(&self) -> bool { fn is_modify(&self) -> bool {
matches!(self, matches!(
Self::SetPpt(_, _) self,
| Self::SetClockLimits(_) Self::SetPpt(_, _) | Self::SetClockLimits(_) | Self::SetSlowMemory(_)
| Self::SetSlowMemory(_)
) )
} }
} }
@ -217,7 +237,7 @@ impl GeneralMessage {
Self::GetPersistent(cb) => cb(*settings.persistent()), Self::GetPersistent(cb) => cb(*settings.persistent()),
Self::GetCurrentProfileName(cb) => cb(settings.get_name().to_owned()), Self::GetCurrentProfileName(cb) => cb(settings.get_name().to_owned()),
Self::GetPath(cb) => cb(settings.get_path().to_owned()), Self::GetPath(cb) => cb(settings.get_path().to_owned()),
Self::ApplyNow => {}, Self::ApplyNow => {}
} }
dirty dirty
} }
@ -234,7 +254,9 @@ pub struct ApiMessageHandler {
fn print_errors(call_name: &str, errors: Vec<crate::settings::SettingError>) { fn print_errors(call_name: &str, errors: Vec<crate::settings::SettingError>) {
let mut err_list = String::new(); let mut err_list = String::new();
errors.iter().for_each(|e| write!(err_list, "\t{},\n", e).unwrap_or(())); errors
.iter()
.for_each(|e| write!(err_list, "\t{},\n", e).unwrap_or(()));
log::error!("Settings {}() err:\n{}", call_name, err_list); log::error!("Settings {}() err:\n{}", call_name, err_list);
} }
@ -248,7 +270,7 @@ impl ApiMessageHandler {
} }
if dirty || dirty_echo { if dirty || dirty_echo {
dirty_echo = dirty; // echo only once dirty_echo = dirty; // echo only once
// run on_set // run on_set
if let Err(e) = settings.on_set() { if let Err(e) = settings.on_set() {
print_errors("on_set", e); print_errors("on_set", e);
} }
@ -259,8 +281,8 @@ impl ApiMessageHandler {
// save // save
log::debug!("api_worker is saving..."); log::debug!("api_worker is saving...");
let is_persistent = *settings.general.persistent(); let is_persistent = *settings.general.persistent();
let save_path = crate::utility::settings_dir() let save_path =
.join(settings.general.get_path().clone()); crate::utility::settings_dir().join(settings.general.get_path().clone());
if is_persistent { if is_persistent {
let settings_clone = settings.json(); let settings_clone = settings.json();
let save_json: SettingsJson = settings_clone.into(); let save_json: SettingsJson = settings_clone.into();
@ -272,7 +294,11 @@ impl ApiMessageHandler {
} else { } else {
if save_path.exists() { if save_path.exists() {
if let Err(e) = std::fs::remove_file(&save_path) { if let Err(e) = std::fs::remove_file(&save_path) {
log::warn!("Failed to delete persistent settings file {}: {}", save_path.display(), e); log::warn!(
"Failed to delete persistent settings file {}: {}",
save_path.display(),
e
);
} else { } else {
log::debug!("Deleted persistent settings file {}", save_path.display()); log::debug!("Deleted persistent settings file {}", save_path.display());
} }
@ -333,7 +359,7 @@ impl ApiMessageHandler {
ApiMessage::WaitForEmptyQueue(callback) => { ApiMessage::WaitForEmptyQueue(callback) => {
self.on_empty.push(callback); self.on_empty.push(callback);
false false
}, }
ApiMessage::LoadSettings(id, name) => { ApiMessage::LoadSettings(id, name) => {
let path = format!("{}.json", id); let path = format!("{}.json", id);
match settings.load_file(path.into(), name, false) { match settings.load_file(path.into(), name, false) {
@ -346,7 +372,7 @@ impl ApiMessageHandler {
match settings.load_file( match settings.load_file(
crate::consts::DEFAULT_SETTINGS_FILE.into(), crate::consts::DEFAULT_SETTINGS_FILE.into(),
crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
true true,
) { ) {
Ok(success) => log::info!("Loaded main settings file? {}", success), Ok(success) => log::info!("Loaded main settings file? {}", success),
Err(e) => log::warn!("Load file err: {}", e), Err(e) => log::warn!("Load file err: {}", e),
@ -356,7 +382,7 @@ impl ApiMessageHandler {
ApiMessage::LoadSystemSettings => { ApiMessage::LoadSystemSettings => {
settings.load_system_default(settings.general.get_name().to_owned()); settings.load_system_default(settings.general.get_name().to_owned());
true true
}, }
ApiMessage::GetLimits(cb) => { ApiMessage::GetLimits(cb) => {
cb(super::SettingsLimits { cb(super::SettingsLimits {
battery: settings.battery.limits(), battery: settings.battery.limits(),
@ -365,7 +391,7 @@ impl ApiMessageHandler {
general: settings.general.limits(), general: settings.general.limits(),
}); });
false false
}, }
ApiMessage::GetProvider(name, cb) => { ApiMessage::GetProvider(name, cb) => {
cb(match &name as &str { cb(match &name as &str {
"battery" => settings.battery.provider(), "battery" => settings.battery.provider(),
@ -380,9 +406,12 @@ impl ApiMessageHandler {
pub fn new() -> (Self, Sender<ApiMessage>) { pub fn new() -> (Self, Sender<ApiMessage>) {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
(Self { (
intake: rx, Self {
on_empty: Vec::with_capacity(4), intake: rx,
}, tx) on_empty: Vec::with_capacity(4),
},
tx,
)
} }
} }

View file

@ -1,10 +1,10 @@
mod api_types; mod api_types;
mod async_utils;
pub mod battery; pub mod battery;
pub mod cpu; pub mod cpu;
pub mod general; pub mod general;
pub mod gpu; pub mod gpu;
pub mod handler; pub mod handler;
mod async_utils;
mod utility; mod utility;
pub(super) type ApiParameterType = Vec<usdpl_back::core::serdes::Primitive>; pub(super) type ApiParameterType = Vec<usdpl_back::core::serdes::Primitive>;

View file

@ -10,12 +10,14 @@ pub fn map_result<T: Into<Primitive>>(result: Result<T, SettingError>) -> super:
Err(e) => { Err(e) => {
log::debug!("Mapping error to primitive: {}", e); log::debug!("Mapping error to primitive: {}", e);
vec![e.msg.into()] vec![e.msg.into()]
}, }
} }
} }
#[inline] #[inline]
pub fn map_optional_result<T: Into<Primitive>>(result: Result<Option<T>, SettingError>) -> super::ApiParameterType { pub fn map_optional_result<T: Into<Primitive>>(
result: Result<Option<T>, SettingError>,
) -> super::ApiParameterType {
match result { match result {
Ok(val) => match val { Ok(val) => match val {
Some(val) => vec![val.into()], Some(val) => vec![val.into()],
@ -24,7 +26,7 @@ pub fn map_optional_result<T: Into<Primitive>>(result: Result<Option<T>, Setting
Err(e) => { Err(e) => {
log::debug!("Mapping error to primitive: {}", e); log::debug!("Mapping error to primitive: {}", e);
vec![e.msg.into()] vec![e.msg.into()]
}, }
} }
} }

View file

@ -22,17 +22,18 @@ fn main() -> Result<(), ()> {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
let log_filepath = usdpl_back::api::dirs::home() let log_filepath = usdpl_back::api::dirs::home()
.unwrap_or_else(|| "/tmp/".into()) .unwrap_or_else(|| "/tmp/".into())
.join(PACKAGE_NAME.to_owned()+".log"); .join(PACKAGE_NAME.to_owned() + ".log");
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
let log_filepath = std::path::Path::new("/tmp").join(format!("{}.log", PACKAGE_NAME)); let log_filepath = std::path::Path::new("/tmp").join(format!("{}.log", PACKAGE_NAME));
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
let old_log_filepath = usdpl_back::api::dirs::home() let old_log_filepath = usdpl_back::api::dirs::home()
.unwrap_or_else(|| "/tmp/".into()) .unwrap_or_else(|| "/tmp/".into())
.join(PACKAGE_NAME.to_owned()+".log.old"); .join(PACKAGE_NAME.to_owned() + ".log.old");
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{ {
if std::path::Path::new(&log_filepath).exists() { if std::path::Path::new(&log_filepath).exists() {
std::fs::copy(&log_filepath, &old_log_filepath).expect("Unable to increment logs. Do you have write permissions?"); std::fs::copy(&log_filepath, &old_log_filepath)
.expect("Unable to increment logs. Do you have write permissions?");
} }
} }
WriteLogger::init( WriteLogger::init(
@ -53,8 +54,14 @@ fn main() -> Result<(), ()> {
println!("Logging to: {:?}", log_filepath); println!("Logging to: {:?}", log_filepath);
log::info!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION); log::info!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION);
println!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION); println!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION);
log::info!("Current dir `{}`", std::env::current_dir().unwrap().display()); log::info!(
println!("Current dir `{}`", std::env::current_dir().unwrap().display()); "Current dir `{}`",
std::env::current_dir().unwrap().display()
);
println!(
"Current dir `{}`",
std::env::current_dir().unwrap().display()
);
log::info!("home dir: {:?}", usdpl_back::api::dirs::home()); log::info!("home dir: {:?}", usdpl_back::api::dirs::home());
@ -66,11 +73,20 @@ fn main() -> Result<(), ()> {
} }
let _limits_handle = crate::settings::limits_worker_spawn(); let _limits_handle = crate::settings::limits_worker_spawn();
log::info!("Detected device automatically, starting with driver: {:?} (This can be overriden)", crate::settings::auto_detect_provider()); log::info!(
"Detected device automatically, starting with driver: {:?} (This can be overriden)",
crate::settings::auto_detect_provider()
);
let mut loaded_settings = persist::SettingsJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE)) let mut loaded_settings =
.map(|settings| settings::Settings::from_json(settings, DEFAULT_SETTINGS_FILE.into())) persist::SettingsJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE))
.unwrap_or_else(|_| settings::Settings::system_default(DEFAULT_SETTINGS_FILE.into(), DEFAULT_SETTINGS_NAME.into())); .map(|settings| settings::Settings::from_json(settings, DEFAULT_SETTINGS_FILE.into()))
.unwrap_or_else(|_| {
settings::Settings::system_default(
DEFAULT_SETTINGS_FILE.into(),
DEFAULT_SETTINGS_NAME.into(),
)
});
log::debug!("Settings: {:?}", loaded_settings); log::debug!("Settings: {:?}", loaded_settings);
@ -83,19 +99,33 @@ fn main() -> Result<(), ()> {
let instance = Instance::new(PORT) let instance = Instance::new(PORT)
.register("V_INFO", |_: Vec<Primitive>| { .register("V_INFO", |_: Vec<Primitive>| {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
{vec![format!("v{}-dbg", PACKAGE_VERSION).into()]} {
vec![format!("v{}-dbg", PACKAGE_VERSION).into()]
}
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
{vec![format!("v{}-rls", PACKAGE_VERSION).into()]} {
}) vec![format!("v{}-rls", PACKAGE_VERSION).into()]
.register("NAME", |_: Vec<Primitive>| { }
vec![PACKAGE_NAME.into()]
}) })
.register("NAME", |_: Vec<Primitive>| vec![PACKAGE_NAME.into()])
.register("LOG", api::general::log_it()) .register("LOG", api::general::log_it())
// battery API functions // battery API functions
.register_async("BATTERY_current_now", api::battery::current_now(api_sender.clone())) .register_async(
.register_async("BATTERY_charge_now", api::battery::charge_now(api_sender.clone())) "BATTERY_current_now",
.register_async("BATTERY_charge_full", api::battery::charge_full(api_sender.clone())) api::battery::current_now(api_sender.clone()),
.register_async("BATTERY_charge_design", api::battery::charge_design(api_sender.clone())) )
.register_async(
"BATTERY_charge_now",
api::battery::charge_now(api_sender.clone()),
)
.register_async(
"BATTERY_charge_full",
api::battery::charge_full(api_sender.clone()),
)
.register_async(
"BATTERY_charge_design",
api::battery::charge_design(api_sender.clone()),
)
.register( .register(
"BATTERY_set_charge_rate", "BATTERY_set_charge_rate",
api::battery::set_charge_rate(api_sender.clone()), api::battery::set_charge_rate(api_sender.clone()),
@ -136,138 +166,124 @@ fn main() -> Result<(), ()> {
.register("CPU_count", api::cpu::max_cpus) .register("CPU_count", api::cpu::max_cpus)
.register( .register(
"CPU_set_online", "CPU_set_online",
api::cpu::set_cpu_online(api_sender.clone()) api::cpu::set_cpu_online(api_sender.clone()),
) )
.register( .register(
"CPU_set_onlines", "CPU_set_onlines",
api::cpu::set_cpus_online(api_sender.clone()) api::cpu::set_cpus_online(api_sender.clone()),
) )
.register_async( .register_async(
"CPU_get_onlines", "CPU_get_onlines",
api::cpu::get_cpus_online(api_sender.clone()) api::cpu::get_cpus_online(api_sender.clone()),
)
.register_async(
"CPU_set_smt",
api::cpu::set_smt(api_sender.clone())
)
.register_async(
"CPU_get_smt",
api::cpu::get_smt(api_sender.clone())
) )
.register_async("CPU_set_smt", api::cpu::set_smt(api_sender.clone()))
.register_async("CPU_get_smt", api::cpu::get_smt(api_sender.clone()))
.register( .register(
"CPU_set_clock_limits", "CPU_set_clock_limits",
api::cpu::set_clock_limits(api_sender.clone()) api::cpu::set_clock_limits(api_sender.clone()),
) )
.register( .register(
"CPU_get_clock_limits", "CPU_get_clock_limits",
api::cpu::get_clock_limits(api_sender.clone()) api::cpu::get_clock_limits(api_sender.clone()),
) )
.register( .register(
"CPU_unset_clock_limits", "CPU_unset_clock_limits",
api::cpu::unset_clock_limits(api_sender.clone()) api::cpu::unset_clock_limits(api_sender.clone()),
) )
.register( .register(
"CPU_set_governor", "CPU_set_governor",
api::cpu::set_cpu_governor(api_sender.clone()) api::cpu::set_cpu_governor(api_sender.clone()),
) )
.register( .register(
"CPU_set_governors", "CPU_set_governors",
api::cpu::set_cpus_governors(api_sender.clone()) api::cpu::set_cpus_governors(api_sender.clone()),
) )
.register( .register(
"CPU_get_governors", "CPU_get_governors",
api::cpu::get_cpu_governors(api_sender.clone()) api::cpu::get_cpu_governors(api_sender.clone()),
) )
// gpu API functions // gpu API functions
.register( .register("GPU_set_ppt", api::gpu::set_ppt(api_sender.clone()))
"GPU_set_ppt", .register_async("GPU_get_ppt", api::gpu::get_ppt(api_sender.clone()))
api::gpu::set_ppt(api_sender.clone()) .register("GPU_unset_ppt", api::gpu::unset_ppt(api_sender.clone()))
)
.register_async(
"GPU_get_ppt",
api::gpu::get_ppt(api_sender.clone())
)
.register(
"GPU_unset_ppt",
api::gpu::unset_ppt(api_sender.clone())
)
.register( .register(
"GPU_set_clock_limits", "GPU_set_clock_limits",
api::gpu::set_clock_limits(api_sender.clone()) api::gpu::set_clock_limits(api_sender.clone()),
) )
.register_async( .register_async(
"GPU_get_clock_limits", "GPU_get_clock_limits",
api::gpu::get_clock_limits(api_sender.clone()) api::gpu::get_clock_limits(api_sender.clone()),
) )
.register( .register(
"GPU_unset_clock_limits", "GPU_unset_clock_limits",
api::gpu::unset_clock_limits(api_sender.clone()) api::gpu::unset_clock_limits(api_sender.clone()),
) )
.register( .register(
"GPU_set_slow_memory", "GPU_set_slow_memory",
api::gpu::set_slow_memory(api_sender.clone()) api::gpu::set_slow_memory(api_sender.clone()),
) )
.register_async( .register_async(
"GPU_get_slow_memory", "GPU_get_slow_memory",
api::gpu::get_slow_memory(api_sender.clone()) api::gpu::get_slow_memory(api_sender.clone()),
) )
// general API functions // general API functions
.register( .register(
"GENERAL_set_persistent", "GENERAL_set_persistent",
api::general::set_persistent(api_sender.clone()) api::general::set_persistent(api_sender.clone()),
) )
.register( .register(
"GENERAL_get_persistent", "GENERAL_get_persistent",
api::general::get_persistent(api_sender.clone()) api::general::get_persistent(api_sender.clone()),
) )
.register( .register(
"GENERAL_load_settings", "GENERAL_load_settings",
api::general::load_settings(api_sender.clone()) api::general::load_settings(api_sender.clone()),
) )
.register( .register(
"GENERAL_load_default_settings", "GENERAL_load_default_settings",
api::general::load_default_settings(api_sender.clone()) api::general::load_default_settings(api_sender.clone()),
) )
.register( .register(
"GENERAL_load_system_settings", "GENERAL_load_system_settings",
api::general::load_system_settings(api_sender.clone()) api::general::load_system_settings(api_sender.clone()),
) )
.register_async( .register_async(
"GENERAL_get_name", "GENERAL_get_name",
api::general::get_name(api_sender.clone()) api::general::get_name(api_sender.clone()),
) )
.register_async( .register_async(
"GENERAL_get_path", "GENERAL_get_path",
api::general::get_path(api_sender.clone()) api::general::get_path(api_sender.clone()),
) )
.register_async( .register_async(
"GENERAL_wait_for_unlocks", "GENERAL_wait_for_unlocks",
api::general::lock_unlock_all(api_sender.clone()) api::general::lock_unlock_all(api_sender.clone()),
) )
.register_blocking( .register_blocking(
"GENERAL_get_limits", "GENERAL_get_limits",
api::general::get_limits(api_sender.clone()) api::general::get_limits(api_sender.clone()),
) )
.register_async( .register_async(
"GENERAL_get_provider", "GENERAL_get_provider",
api::general::get_provider(api_sender.clone()) api::general::get_provider(api_sender.clone()),
) )
.register("GENERAL_idk", api::general::gunter) .register("GENERAL_idk", api::general::gunter)
.register( .register(
"GENERAL_apply_now", "GENERAL_apply_now",
api::general::force_apply(api_sender.clone()) api::general::force_apply(api_sender.clone()),
) )
.register( .register(
"GENERAL_on_pluggedin", "GENERAL_on_pluggedin",
api::battery::on_plugged(api_sender.clone()) api::battery::on_plugged(api_sender.clone()),
) )
.register( .register(
"GENERAL_on_unplugged", "GENERAL_on_unplugged",
api::battery::on_unplugged(api_sender.clone()) api::battery::on_unplugged(api_sender.clone()),
); );
if let Err(e) = loaded_settings.on_set() { if let Err(e) = loaded_settings.on_set() {
e.iter().for_each(|e| log::error!("Startup Settings.on_set() error: {}", e)); e.iter()
.for_each(|e| log::error!("Startup Settings.on_set() error: {}", e));
} else { } else {
log::info!("Startup Settings.on_set() success"); log::info!("Startup Settings.on_set() success");
} }
@ -278,6 +294,5 @@ fn main() -> Result<(), ()> {
api_worker::spawn(loaded_settings, api_handler); api_worker::spawn(loaded_settings, api_handler);
instance instance.run_blocking()
.run_blocking()
} }

View file

@ -3,7 +3,7 @@ use std::default::Default;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use super::JsonError; use super::JsonError;
use super::{BatteryJson, CpuJson, GpuJson, DriverJson}; use super::{BatteryJson, CpuJson, DriverJson, GpuJson};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct SettingsJson { pub struct SettingsJson {

View file

@ -5,7 +5,7 @@ mod error;
mod general; mod general;
mod gpu; mod gpu;
pub use battery::{BatteryJson, BatteryEventJson}; pub use battery::{BatteryEventJson, BatteryJson};
pub use cpu::CpuJson; pub use cpu::CpuJson;
pub use driver::DriverJson; pub use driver::DriverJson;
pub use general::{MinMaxJson, SettingsJson}; pub use general::{MinMaxJson, SettingsJson};

View file

@ -1,6 +1,6 @@
use std::sync::mpsc::Sender;
use std::thread::{self, JoinHandle}; use std::thread::{self, JoinHandle};
use std::time::Duration; use std::time::Duration;
use std::sync::mpsc::Sender;
use crate::api::handler::ApiMessage; use crate::api::handler::ApiMessage;
//use crate::utility::unwrap_maybe_fatal; //use crate::utility::unwrap_maybe_fatal;
@ -11,7 +11,9 @@ pub fn spawn(sender: Sender<ApiMessage>) -> JoinHandle<()> {
thread::spawn(move || { thread::spawn(move || {
log::info!("power_worker starting..."); log::info!("power_worker starting...");
loop { loop {
sender.send(ApiMessage::PowerVibeCheck).expect("power_worker send failed"); sender
.send(ApiMessage::PowerVibeCheck)
.expect("power_worker send failed");
thread::sleep(PERIOD); thread::sleep(PERIOD);
} }
//log::warn!("resume_worker completed!"); //log::warn!("resume_worker completed!");

View file

@ -1,6 +1,6 @@
use std::sync::mpsc::Sender;
use std::thread::{self, JoinHandle}; use std::thread::{self, JoinHandle};
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use std::sync::mpsc::Sender;
use crate::api::handler::ApiMessage; use crate::api::handler::ApiMessage;
//use crate::utility::unwrap_maybe_fatal; //use crate::utility::unwrap_maybe_fatal;
@ -11,7 +11,7 @@ pub fn spawn(sender: Sender<ApiMessage>) -> JoinHandle<()> {
thread::spawn(move || { thread::spawn(move || {
log::info!("resume_worker starting..."); log::info!("resume_worker starting...");
let duration = Duration::from_millis(10); // very low so it detects before Steam client does let duration = Duration::from_millis(10); // very low so it detects before Steam client does
// this allows PowerTools to set some values at wakeup and Steam to override them before user notices // this allows PowerTools to set some values at wakeup and Steam to override them before user notices
let mut start = Instant::now(); let mut start = Instant::now();
loop { loop {
let old_start = start.elapsed(); let old_start = start.elapsed();
@ -19,7 +19,9 @@ pub fn spawn(sender: Sender<ApiMessage>) -> JoinHandle<()> {
if old_start.as_secs_f64() > duration.as_secs_f64() * (1.0 + ALLOWED_ERROR) { if old_start.as_secs_f64() > duration.as_secs_f64() * (1.0 + ALLOWED_ERROR) {
// has just resumed from sleep // has just resumed from sleep
log::info!("Resume detected"); log::info!("Resume detected");
sender.send(ApiMessage::OnResume).expect("resume_worker send failed"); sender
.send(ApiMessage::OnResume)
.expect("resume_worker send failed");
log::debug!( log::debug!(
"OnResume completed after sleeping for {}s", "OnResume completed after sleeping for {}s",
old_start.as_secs_f32() old_start.as_secs_f32()

View file

@ -2,25 +2,31 @@ use std::fs::File;
use regex::RegexBuilder; use regex::RegexBuilder;
use limits_core::json::{Limits, BatteryLimit, CpuLimit, GpuLimit}; use limits_core::json::{BatteryLimit, CpuLimit, GpuLimit, Limits};
use crate::persist::{DriverJson, SettingsJson}; use crate::persist::{DriverJson, SettingsJson};
use crate::settings::{TGeneral, TCpus, TGpu, TBattery, Driver, General}; use crate::settings::{Driver, General, TBattery, TCpus, TGeneral, TGpu};
fn get_limits() -> limits_core::json::Base { fn get_limits() -> limits_core::json::Base {
let limits_path = super::utility::limits_path(); let limits_path = super::utility::limits_path();
match File::open(&limits_path) { match File::open(&limits_path) {
Ok(f) => { Ok(f) => match serde_json::from_reader(f) {
match serde_json::from_reader(f) { Ok(lim) => lim,
Ok(lim) => lim, Err(e) => {
Err(e) => { log::warn!(
log::warn!("Failed to parse limits file `{}`, cannot use for auto_detect: {}", limits_path.display(), e); "Failed to parse limits file `{}`, cannot use for auto_detect: {}",
limits_core::json::Base::default() limits_path.display(),
} e
);
limits_core::json::Base::default()
} }
}, },
Err(e) => { Err(e) => {
log::warn!("Failed to open limits file `{}` (trying force refresh...): {}", limits_path.display(), e); log::warn!(
"Failed to open limits file `{}` (trying force refresh...): {}",
limits_path.display(),
e
);
super::limits_worker::get_limits_blocking() super::limits_worker::get_limits_blocking()
} }
} }
@ -28,22 +34,34 @@ fn get_limits() -> limits_core::json::Base {
#[inline] #[inline]
pub fn auto_detect_provider() -> DriverJson { pub fn auto_detect_provider() -> DriverJson {
let provider = auto_detect0(None, crate::utility::settings_dir().join("autodetect.json"), "".to_owned()) let provider = auto_detect0(
.battery None,
.provider(); crate::utility::settings_dir().join("autodetect.json"),
"".to_owned(),
)
.battery
.provider();
//log::info!("Detected device automatically, compatible driver: {:?}", provider); //log::info!("Detected device automatically, compatible driver: {:?}", provider);
provider provider
} }
/// Device detection logic /// Device detection logic
pub fn auto_detect0(settings_opt: Option<SettingsJson>, json_path: std::path::PathBuf, name: String) -> Driver { pub fn auto_detect0(
settings_opt: Option<SettingsJson>,
json_path: std::path::PathBuf,
name: String,
) -> Driver {
let mut builder = DriverBuilder::new(json_path, name); let mut builder = DriverBuilder::new(json_path, name);
let cpu_info: String = usdpl_back::api::files::read_single("/proc/cpuinfo").unwrap_or_default(); let cpu_info: String = usdpl_back::api::files::read_single("/proc/cpuinfo").unwrap_or_default();
log::debug!("Read from /proc/cpuinfo:\n{}", cpu_info); log::debug!("Read from /proc/cpuinfo:\n{}", cpu_info);
let os_info: String = usdpl_back::api::files::read_single("/etc/os-release").unwrap_or_default(); let os_info: String =
usdpl_back::api::files::read_single("/etc/os-release").unwrap_or_default();
log::debug!("Read from /etc/os-release:\n{}", os_info); log::debug!("Read from /etc/os-release:\n{}", os_info);
let dmi_info: String = std::process::Command::new("dmidecode").output().map(|out| String::from_utf8_lossy(&out.stdout).into_owned()).unwrap_or_default(); let dmi_info: String = std::process::Command::new("dmidecode")
.output()
.map(|out| String::from_utf8_lossy(&out.stdout).into_owned())
.unwrap_or_default();
log::debug!("Read dmidecode:\n{}", dmi_info); log::debug!("Read dmidecode:\n{}", dmi_info);
let limits = get_limits(); let limits = get_limits();
@ -60,26 +78,27 @@ pub fn auto_detect0(settings_opt: Option<SettingsJson>, json_path: std::path::Pa
.multi_line(true) .multi_line(true)
.build() .build()
.expect("Invalid DMI regex"); .expect("Invalid DMI regex");
matches &=pattern.is_match(&dmi_info); matches &= pattern.is_match(&dmi_info);
} }
if let Some(cpuinfo) = &conditions.cpuinfo { if let Some(cpuinfo) = &conditions.cpuinfo {
let pattern = RegexBuilder::new(cpuinfo) let pattern = RegexBuilder::new(cpuinfo)
.multi_line(true) .multi_line(true)
.build() .build()
.expect("Invalid CPU regex"); .expect("Invalid CPU regex");
matches &=pattern.is_match(&cpu_info); matches &= pattern.is_match(&cpu_info);
} }
if let Some(os) = &conditions.os { if let Some(os) = &conditions.os {
let pattern = RegexBuilder::new(os) let pattern = RegexBuilder::new(os)
.multi_line(true) .multi_line(true)
.build() .build()
.expect("Invalid OS regex"); .expect("Invalid OS regex");
matches &=pattern.is_match(&os_info); matches &= pattern.is_match(&os_info);
} }
if let Some(cmd) = &conditions.command { if let Some(cmd) = &conditions.command {
match std::process::Command::new("bash") match std::process::Command::new("bash")
.args(["-c", cmd]) .args(["-c", cmd])
.status() { .status()
{
Ok(status) => matches &= status.code().map(|c| c == 0).unwrap_or(false), Ok(status) => matches &= status.code().map(|c| c == 0).unwrap_or(false),
Err(e) => log::warn!("Ignoring bash limits error: {}", e), Err(e) => log::warn!("Ignoring bash limits error: {}", e),
} }
@ -97,30 +116,102 @@ pub fn auto_detect0(settings_opt: Option<SettingsJson>, json_path: std::path::Pa
match limit { match limit {
Limits::Cpu(cpus) => { Limits::Cpu(cpus) => {
let cpu_driver: Box<dyn TCpus> = match cpus { let cpu_driver: Box<dyn TCpus> = match cpus {
CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)), CpuLimit::SteamDeck => {
CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)), Box::new(crate::settings::steam_deck::Cpus::from_json(
CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::<crate::settings::generic::Cpu>::from_json_and_limits(settings.cpus.clone(), settings.version, x)), settings.cpus.clone(),
CpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Cpus::from_json_and_limits(settings.cpus.clone(), settings.version, x)), settings.version,
CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::from_json(settings.cpus.clone(), settings.version)), ))
}
CpuLimit::SteamDeckAdvance => {
Box::new(crate::settings::steam_deck::Cpus::from_json(
settings.cpus.clone(),
settings.version,
))
}
CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::<
crate::settings::generic::Cpu,
>::from_json_and_limits(
settings.cpus.clone(),
settings.version,
x,
)),
CpuLimit::GenericAMD(x) => Box::new(
crate::settings::generic_amd::Cpus::from_json_and_limits(
settings.cpus.clone(),
settings.version,
x,
),
),
CpuLimit::Unknown => {
Box::new(crate::settings::unknown::Cpus::from_json(
settings.cpus.clone(),
settings.version,
))
}
}; };
builder.cpus = Some(cpu_driver); builder.cpus = Some(cpu_driver);
}, }
Limits::Gpu(gpu) => { Limits::Gpu(gpu) => {
let driver: Box<dyn TGpu> = match gpu { let driver: Box<dyn TGpu> = match gpu {
GpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Gpu::from_json(settings.gpu.clone(), settings.version)), GpuLimit::SteamDeck => {
GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Gpu::from_json(settings.gpu.clone(), settings.version)), Box::new(crate::settings::steam_deck::Gpu::from_json(
GpuLimit::Generic(x) => Box::new(crate::settings::generic::Gpu::from_json_and_limits(settings.gpu.clone(), settings.version, x)), settings.gpu.clone(),
GpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Gpu::from_json_and_limits(settings.gpu.clone(), settings.version, x)), settings.version,
GpuLimit::Unknown => Box::new(crate::settings::unknown::Gpu::from_json(settings.gpu.clone(), settings.version)), ))
}
GpuLimit::SteamDeckAdvance => {
Box::new(crate::settings::steam_deck::Gpu::from_json(
settings.gpu.clone(),
settings.version,
))
}
GpuLimit::Generic(x) => {
Box::new(crate::settings::generic::Gpu::from_json_and_limits(
settings.gpu.clone(),
settings.version,
x,
))
}
GpuLimit::GenericAMD(x) => Box::new(
crate::settings::generic_amd::Gpu::from_json_and_limits(
settings.gpu.clone(),
settings.version,
x,
),
),
GpuLimit::Unknown => {
Box::new(crate::settings::unknown::Gpu::from_json(
settings.gpu.clone(),
settings.version,
))
}
}; };
builder.gpu = Some(driver); builder.gpu = Some(driver);
}, }
Limits::Battery(batt) => { Limits::Battery(batt) => {
let driver: Box<dyn TBattery> = match batt { let driver: Box<dyn TBattery> = match batt {
BatteryLimit::SteamDeck => Box::new(crate::settings::steam_deck::Battery::from_json(settings.battery.clone(), settings.version)), BatteryLimit::SteamDeck => {
BatteryLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Battery::from_json(settings.battery.clone(), settings.version)), Box::new(crate::settings::steam_deck::Battery::from_json(
BatteryLimit::Generic(x) => Box::new(crate::settings::generic::Battery::from_json_and_limits(settings.battery.clone(), settings.version, x)), settings.battery.clone(),
BatteryLimit::Unknown => Box::new(crate::settings::unknown::Battery), settings.version,
))
}
BatteryLimit::SteamDeckAdvance => {
Box::new(crate::settings::steam_deck::Battery::from_json(
settings.battery.clone(),
settings.version,
))
}
BatteryLimit::Generic(x) => Box::new(
crate::settings::generic::Battery::from_json_and_limits(
settings.battery.clone(),
settings.version,
x,
),
),
BatteryLimit::Unknown => {
Box::new(crate::settings::unknown::Battery)
}
}; };
builder.battery = Some(driver); builder.battery = Some(driver);
} }
@ -131,37 +222,66 @@ pub fn auto_detect0(settings_opt: Option<SettingsJson>, json_path: std::path::Pa
match limit { match limit {
Limits::Cpu(cpus) => { Limits::Cpu(cpus) => {
let cpu_driver: Box<dyn TCpus> = match cpus { let cpu_driver: Box<dyn TCpus> = match cpus {
CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::system_default()), CpuLimit::SteamDeck => {
CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Cpus::system_default()), Box::new(crate::settings::steam_deck::Cpus::system_default())
CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::<crate::settings::generic::Cpu>::from_limits(x)), }
CpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Cpus::from_limits(x)), CpuLimit::SteamDeckAdvance => {
CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::system_default()), Box::new(crate::settings::steam_deck::Cpus::system_default())
}
CpuLimit::Generic(x) => {
Box::new(crate::settings::generic::Cpus::<
crate::settings::generic::Cpu,
>::from_limits(x))
}
CpuLimit::GenericAMD(x) => {
Box::new(crate::settings::generic_amd::Cpus::from_limits(x))
}
CpuLimit::Unknown => {
Box::new(crate::settings::unknown::Cpus::system_default())
}
}; };
builder.cpus = Some(cpu_driver); builder.cpus = Some(cpu_driver);
}, }
Limits::Gpu(gpu) => { Limits::Gpu(gpu) => {
let driver: Box<dyn TGpu> = match gpu { let driver: Box<dyn TGpu> = match gpu {
GpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Gpu::system_default()), GpuLimit::SteamDeck => {
GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Gpu::system_default()), Box::new(crate::settings::steam_deck::Gpu::system_default())
GpuLimit::Generic(x) => Box::new(crate::settings::generic::Gpu::from_limits(x)), }
GpuLimit::GenericAMD(x) => Box::new(crate::settings::generic_amd::Gpu::from_limits(x)), GpuLimit::SteamDeckAdvance => {
GpuLimit::Unknown => Box::new(crate::settings::unknown::Gpu::system_default()), Box::new(crate::settings::steam_deck::Gpu::system_default())
}
GpuLimit::Generic(x) => {
Box::new(crate::settings::generic::Gpu::from_limits(x))
}
GpuLimit::GenericAMD(x) => {
Box::new(crate::settings::generic_amd::Gpu::from_limits(x))
}
GpuLimit::Unknown => {
Box::new(crate::settings::unknown::Gpu::system_default())
}
}; };
builder.gpu = Some(driver); builder.gpu = Some(driver);
}, }
Limits::Battery(batt) => { Limits::Battery(batt) => {
let driver: Box<dyn TBattery> = match batt { let driver: Box<dyn TBattery> = match batt {
BatteryLimit::SteamDeck => Box::new(crate::settings::steam_deck::Battery::system_default()), BatteryLimit::SteamDeck => {
BatteryLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Battery::system_default()), Box::new(crate::settings::steam_deck::Battery::system_default())
BatteryLimit::Generic(x) => Box::new(crate::settings::generic::Battery::from_limits(x)), }
BatteryLimit::Unknown => Box::new(crate::settings::unknown::Battery), BatteryLimit::SteamDeckAdvance => {
Box::new(crate::settings::steam_deck::Battery::system_default())
}
BatteryLimit::Generic(x) => {
Box::new(crate::settings::generic::Battery::from_limits(x))
}
BatteryLimit::Unknown => {
Box::new(crate::settings::unknown::Battery)
}
}; };
builder.battery = Some(driver); builder.battery = Some(driver);
} }
} }
} }
} }
} }
} }
@ -197,9 +317,15 @@ impl DriverBuilder {
fn build(self) -> Driver { fn build(self) -> Driver {
Driver { Driver {
general: self.general, general: self.general,
cpus: self.cpus.unwrap_or_else(|| Box::new(crate::settings::unknown::Cpus::system_default())), cpus: self
gpu: self.gpu.unwrap_or_else(|| Box::new(crate::settings::unknown::Gpu::system_default())), .cpus
battery: self.battery.unwrap_or_else(|| Box::new(crate::settings::unknown::Battery)) .unwrap_or_else(|| Box::new(crate::settings::unknown::Cpus::system_default())),
gpu: self
.gpu
.unwrap_or_else(|| Box::new(crate::settings::unknown::Gpu::system_default())),
battery: self
.battery
.unwrap_or_else(|| Box::new(crate::settings::unknown::Battery)),
} }
} }
} }

View file

@ -8,20 +8,18 @@ use limits_core::json::Base;
pub fn spawn() -> JoinHandle<()> { pub fn spawn() -> JoinHandle<()> {
thread::spawn(move || { thread::spawn(move || {
log::info!("limits_worker starting..."); log::info!("limits_worker starting...");
let sleep_dur = Duration::from_secs(60*60*24); // 1 day let sleep_dur = Duration::from_secs(60 * 60 * 24); // 1 day
let limits_path = super::utility::limits_path(); let limits_path = super::utility::limits_path();
loop { loop {
thread::sleep(sleep_dur); thread::sleep(sleep_dur);
if (limits_path.exists() && limits_path.is_file()) || !limits_path.exists() { if (limits_path.exists() && limits_path.is_file()) || !limits_path.exists() {
// try to load limits from file, fallback to built-in default // try to load limits from file, fallback to built-in default
let base = match std::fs::File::open(&limits_path) { let base = match std::fs::File::open(&limits_path) {
Ok(f) => { Ok(f) => match serde_json::from_reader(f) {
match serde_json::from_reader(f) { Ok(b) => b,
Ok(b) => b, Err(e) => {
Err(e) => { log::error!("Cannot parse {}: {}", limits_path.display(), e);
log::error!("Cannot parse {}: {}", limits_path.display(), e); Base::default()
Base::default()
}
} }
}, },
Err(e) => { Err(e) => {
@ -31,17 +29,18 @@ pub fn spawn() -> JoinHandle<()> {
}; };
if let Some(refresh) = &base.refresh { if let Some(refresh) = &base.refresh {
// try to retrieve newer version // try to retrieve newer version
match ureq::get(refresh) match ureq::get(refresh).call() {
.call() {
Ok(response) => { Ok(response) => {
let json_res: std::io::Result<Base> = response.into_json(); let json_res: std::io::Result<Base> = response.into_json();
match json_res { match json_res {
Ok(new_base) => { Ok(new_base) => {
save_base(&new_base, &limits_path); save_base(&new_base, &limits_path);
}, }
Err(e) => log::error!("Cannot parse response from `{}`: {}", refresh, e), Err(e) => {
log::error!("Cannot parse response from `{}`: {}", refresh, e)
}
} }
}, }
Err(e) => log::warn!("Cannot download limits from `{}`: {}", refresh, e), Err(e) => log::warn!("Cannot download limits from `{}`: {}", refresh, e),
} }
} else { } else {
@ -67,13 +66,11 @@ pub fn get_limits_blocking() -> Base {
let limits_path = super::utility::limits_path(); let limits_path = super::utility::limits_path();
if limits_path.is_file() { if limits_path.is_file() {
match std::fs::File::open(&limits_path) { match std::fs::File::open(&limits_path) {
Ok(f) => { Ok(f) => match serde_json::from_reader(f) {
match serde_json::from_reader(f) { Ok(b) => b,
Ok(b) => b, Err(e) => {
Err(e) => { log::error!("Cannot parse {}: {}", limits_path.display(), e);
log::error!("Cannot parse {}: {}", limits_path.display(), e); Base::default()
Base::default()
}
} }
}, },
Err(e) => { Err(e) => {
@ -86,17 +83,18 @@ pub fn get_limits_blocking() -> Base {
{ {
let refresh = Base::default().refresh.unwrap(); let refresh = Base::default().refresh.unwrap();
match ureq::get(&refresh) // try to retrieve newer version match ureq::get(&refresh) // try to retrieve newer version
.call() { .call()
{
Ok(response) => { Ok(response) => {
let json_res: std::io::Result<Base> = response.into_json(); let json_res: std::io::Result<Base> = response.into_json();
match json_res { match json_res {
Ok(new_base) => { Ok(new_base) => {
save_base(&new_base, &limits_path); save_base(&new_base, &limits_path);
return new_base; return new_base;
}, }
Err(e) => log::error!("Cannot parse response from `{}`: {}", refresh, e) Err(e) => log::error!("Cannot parse response from `{}`: {}", refresh, e),
} }
}, }
Err(e) => log::warn!("Cannot download limits from `{}`: {}", refresh, e), Err(e) => log::warn!("Cannot download limits from `{}`: {}", refresh, e),
} }
} }
@ -108,12 +106,14 @@ pub fn get_limits_blocking() -> Base {
fn save_base(new_base: &Base, path: impl AsRef<std::path::Path>) { fn save_base(new_base: &Base, path: impl AsRef<std::path::Path>) {
let limits_path = path.as_ref(); let limits_path = path.as_ref();
match std::fs::File::create(&limits_path) { match std::fs::File::create(&limits_path) {
Ok(f) => { Ok(f) => match serde_json::to_writer_pretty(f, &new_base) {
match serde_json::to_writer_pretty(f, &new_base) { Ok(_) => log::info!("Successfully saved new limits to {}", limits_path.display()),
Ok(_) => log::info!("Successfully saved new limits to {}", limits_path.display()), Err(e) => log::error!(
Err(e) => log::error!("Failed to save limits json to file `{}`: {}", limits_path.display(), e), "Failed to save limits json to file `{}`: {}",
} limits_path.display(),
e
),
}, },
Err(e) => log::error!("Cannot create {}: {}", limits_path.display(), e) Err(e) => log::error!("Cannot create {}: {}", limits_path.display(), e),
} }
} }

View file

@ -2,4 +2,4 @@ mod auto_detect;
pub mod limits_worker; pub mod limits_worker;
mod utility; mod utility;
pub use auto_detect::{auto_detect_provider, auto_detect0}; pub use auto_detect::{auto_detect0, auto_detect_provider};

View file

@ -1,5 +1,5 @@
use super::{auto_detect0, General, SettingError, TBattery, TCpus, TGeneral, TGpu};
use crate::persist::{DriverJson, SettingsJson}; use crate::persist::{DriverJson, SettingsJson};
use super::{TGeneral, TCpus, TGpu, TBattery, SettingError, General, auto_detect0};
pub struct Driver { pub struct Driver {
pub general: Box<dyn TGeneral>, pub general: Box<dyn TGeneral>,
@ -9,7 +9,10 @@ pub struct Driver {
} }
impl Driver { impl Driver {
pub fn init(settings: SettingsJson, json_path: std::path::PathBuf) -> Result<Self, SettingError> { pub fn init(
settings: SettingsJson,
json_path: std::path::PathBuf,
) -> Result<Self, SettingError> {
Ok(match settings.version { Ok(match settings.version {
0 => Self::version0(settings, json_path)?, 0 => Self::version0(settings, json_path)?,
_ => Self { _ => Self {
@ -19,14 +22,26 @@ impl Driver {
name: settings.name, name: settings.name,
driver: DriverJson::SteamDeck, driver: DriverJson::SteamDeck,
}), }),
cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, settings.version)), cpus: Box::new(super::steam_deck::Cpus::from_json(
gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)), settings.cpus,
battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), settings.version,
)),
gpu: Box::new(super::steam_deck::Gpu::from_json(
settings.gpu,
settings.version,
)),
battery: Box::new(super::steam_deck::Battery::from_json(
settings.battery,
settings.version,
)),
}, },
}) })
} }
fn version0(settings: SettingsJson, json_path: std::path::PathBuf) -> Result<Self, SettingError> { fn version0(
settings: SettingsJson,
json_path: std::path::PathBuf,
) -> Result<Self, SettingError> {
let name = settings.name.clone(); let name = settings.name.clone();
if let Some(provider) = &settings.provider { if let Some(provider) = &settings.provider {
match provider { match provider {
@ -37,9 +52,18 @@ impl Driver {
name: settings.name, name: settings.name,
driver: DriverJson::SteamDeck, driver: DriverJson::SteamDeck,
}), }),
cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, settings.version)), cpus: Box::new(super::steam_deck::Cpus::from_json(
gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)), settings.cpus,
battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), settings.version,
)),
gpu: Box::new(super::steam_deck::Gpu::from_json(
settings.gpu,
settings.version,
)),
battery: Box::new(super::steam_deck::Battery::from_json(
settings.battery,
settings.version,
)),
}), }),
// There's nothing special about SteamDeckAdvance, it just appears different // There's nothing special about SteamDeckAdvance, it just appears different
DriverJson::SteamDeckAdvance => Ok(Self { DriverJson::SteamDeckAdvance => Ok(Self {
@ -49,13 +73,28 @@ impl Driver {
name: settings.name, name: settings.name,
driver: DriverJson::SteamDeckAdvance, driver: DriverJson::SteamDeckAdvance,
}), }),
cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, settings.version)), cpus: Box::new(super::steam_deck::Cpus::from_json(
gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)), settings.cpus,
battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)), settings.version,
)),
gpu: Box::new(super::steam_deck::Gpu::from_json(
settings.gpu,
settings.version,
)),
battery: Box::new(super::steam_deck::Battery::from_json(
settings.battery,
settings.version,
)),
}), }),
DriverJson::Generic | DriverJson::GenericAMD => Ok(super::detect::auto_detect0(Some(settings), json_path, name)), DriverJson::Generic | DriverJson::GenericAMD => {
DriverJson::Unknown => Ok(super::detect::auto_detect0(Some(settings), json_path, name)), Ok(super::detect::auto_detect0(Some(settings), json_path, name))
DriverJson::AutoDetect => Ok(super::detect::auto_detect0(Some(settings), json_path, name)), }
DriverJson::Unknown => {
Ok(super::detect::auto_detect0(Some(settings), json_path, name))
}
DriverJson::AutoDetect => {
Ok(super::detect::auto_detect0(Some(settings), json_path, name))
}
} }
} else { } else {
Ok(super::detect::auto_detect0(Some(settings), json_path, name)) Ok(super::detect::auto_detect0(Some(settings), json_path, name))
@ -73,9 +112,11 @@ pub fn maybe_do_button() {
match super::auto_detect_provider() { match super::auto_detect_provider() {
DriverJson::SteamDeck | DriverJson::SteamDeckAdvance => { DriverJson::SteamDeck | DriverJson::SteamDeckAdvance => {
crate::settings::steam_deck::flash_led(); crate::settings::steam_deck::flash_led();
}, }
DriverJson::Generic | DriverJson::GenericAMD => log::warn!("You need to come up with something fun on generic"), DriverJson::Generic | DriverJson::GenericAMD => {
log::warn!("You need to come up with something fun on generic")
}
DriverJson::Unknown => log::warn!("Can't do button activities on unknown platform"), DriverJson::Unknown => log::warn!("Can't do button activities on unknown platform"),
DriverJson::AutoDetect => log::warn!("WTF, why is auto_detect detecting AutoDetect???") DriverJson::AutoDetect => log::warn!("WTF, why is auto_detect detecting AutoDetect???"),
} }
} }

View file

@ -3,7 +3,7 @@ use std::path::PathBuf;
//use super::{Battery, Cpus, Gpu}; //use super::{Battery, Cpus, Gpu};
use super::{OnResume, OnSet, SettingError}; use super::{OnResume, OnSet, SettingError};
use super::{TGeneral, TGpu, TCpus, TBattery}; use super::{TBattery, TCpus, TGeneral, TGpu};
use crate::persist::SettingsJson; use crate::persist::SettingsJson;
//use crate::utility::unwrap_lock; //use crate::utility::unwrap_lock;
@ -52,7 +52,7 @@ impl crate::settings::OnPowerEvent for General {}
impl TGeneral for General { impl TGeneral for General {
fn limits(&self) -> crate::api::GeneralLimits { fn limits(&self) -> crate::api::GeneralLimits {
crate::api::GeneralLimits { } crate::api::GeneralLimits {}
} }
fn get_persistent(&self) -> bool { fn get_persistent(&self) -> bool {
@ -97,17 +97,25 @@ impl OnSet for Settings {
let mut errors = Vec::new(); let mut errors = Vec::new();
log::debug!("Applying settings for on_resume"); log::debug!("Applying settings for on_resume");
self.general.on_set().unwrap_or_else(|mut e| errors.append(&mut e)); self.general
.on_set()
.unwrap_or_else(|mut e| errors.append(&mut e));
log::debug!("Resumed general"); log::debug!("Resumed general");
self.battery.on_set().unwrap_or_else(|mut e| errors.append(&mut e)); self.battery
.on_set()
.unwrap_or_else(|mut e| errors.append(&mut e));
log::debug!("Resumed battery"); log::debug!("Resumed battery");
self.cpus.on_set().unwrap_or_else(|mut e| errors.append(&mut e)); self.cpus
.on_set()
.unwrap_or_else(|mut e| errors.append(&mut e));
log::debug!("Resumed CPUs"); log::debug!("Resumed CPUs");
self.gpu.on_set().unwrap_or_else(|mut e| errors.append(&mut e)); self.gpu
.on_set()
.unwrap_or_else(|mut e| errors.append(&mut e));
log::debug!("Resumed GPU"); log::debug!("Resumed GPU");
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
} else { } else {
Err(errors) Err(errors)
} }
@ -120,14 +128,20 @@ impl Settings {
let name_bup = other.name.clone(); let name_bup = other.name.clone();
match super::Driver::init(other, json_path.clone()) { match super::Driver::init(other, json_path.clone()) {
Ok(x) => { Ok(x) => {
log::info!("Loaded settings with drivers general:{:?},cpus:{:?},gpu:{:?},battery:{:?}", x.general.provider(), x.cpus.provider(), x.gpu.provider(), x.battery.provider()); log::info!(
"Loaded settings with drivers general:{:?},cpus:{:?},gpu:{:?},battery:{:?}",
x.general.provider(),
x.cpus.provider(),
x.gpu.provider(),
x.battery.provider()
);
Self { Self {
general: x.general, general: x.general,
cpus: x.cpus, cpus: x.cpus,
gpu: x.gpu, gpu: x.gpu,
battery: x.battery, battery: x.battery,
} }
}, }
Err(e) => { Err(e) => {
log::error!("Driver init error: {}", e); log::error!("Driver init error: {}", e);
Self::system_default(json_path, name_bup) Self::system_default(json_path, name_bup)
@ -153,7 +167,12 @@ impl Settings {
self.general = driver.general; self.general = driver.general;
} }
pub fn load_file(&mut self, filename: PathBuf, name: String, system_defaults: bool) -> Result<bool, SettingError> { pub fn load_file(
&mut self,
filename: PathBuf,
name: String,
system_defaults: bool,
) -> Result<bool, SettingError> {
let json_path = crate::utility::settings_dir().join(&filename); let json_path = crate::utility::settings_dir().join(&filename);
if json_path.exists() { if json_path.exists() {
let settings_json = SettingsJson::open(&json_path).map_err(|e| SettingError { let settings_json = SettingsJson::open(&json_path).map_err(|e| SettingError {
@ -161,7 +180,11 @@ impl Settings {
setting: SettingVariant::General, setting: SettingVariant::General,
})?; })?;
if !settings_json.persistent { if !settings_json.persistent {
log::warn!("Loaded persistent config `{}` ({}) with persistent=false", &settings_json.name, json_path.display()); log::warn!(
"Loaded persistent config `{}` ({}) with persistent=false",
&settings_json.name,
json_path.display()
);
*self.general.persistent() = false; *self.general.persistent() = false;
self.general.name(name); self.general.name(name);
} else { } else {
@ -172,7 +195,7 @@ impl Settings {
self.cpus = x.cpus; self.cpus = x.cpus;
self.gpu = x.gpu; self.gpu = x.gpu;
self.battery = x.battery; self.battery = x.battery;
}, }
Err(e) => { Err(e) => {
log::error!("Driver init error: {}", e); log::error!("Driver init error: {}", e);
self.general.name(name); self.general.name(name);
@ -243,17 +266,25 @@ impl OnResume for Settings {
let mut errors = Vec::new(); let mut errors = Vec::new();
log::debug!("Applying settings for on_resume"); log::debug!("Applying settings for on_resume");
self.general.on_resume().unwrap_or_else(|mut e| errors.append(&mut e)); self.general
.on_resume()
.unwrap_or_else(|mut e| errors.append(&mut e));
log::debug!("Resumed general"); log::debug!("Resumed general");
self.battery.on_resume().unwrap_or_else(|mut e| errors.append(&mut e)); self.battery
.on_resume()
.unwrap_or_else(|mut e| errors.append(&mut e));
log::debug!("Resumed battery"); log::debug!("Resumed battery");
self.cpus.on_resume().unwrap_or_else(|mut e| errors.append(&mut e)); self.cpus
.on_resume()
.unwrap_or_else(|mut e| errors.append(&mut e));
log::debug!("Resumed CPUs"); log::debug!("Resumed CPUs");
self.gpu.on_resume().unwrap_or_else(|mut e| errors.append(&mut e)); self.gpu
.on_resume()
.unwrap_or_else(|mut e| errors.append(&mut e));
log::debug!("Resumed GPU"); log::debug!("Resumed GPU");
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
} else { } else {
Err(errors) Err(errors)
} }
@ -264,13 +295,21 @@ impl crate::settings::OnPowerEvent for Settings {
fn on_power_event(&mut self, new_mode: super::PowerMode) -> Result<(), Vec<SettingError>> { fn on_power_event(&mut self, new_mode: super::PowerMode) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new(); let mut errors = Vec::new();
self.general.on_power_event(new_mode).unwrap_or_else(|mut e| errors.append(&mut e)); self.general
self.battery.on_power_event(new_mode).unwrap_or_else(|mut e| errors.append(&mut e)); .on_power_event(new_mode)
self.cpus.on_power_event(new_mode).unwrap_or_else(|mut e| errors.append(&mut e)); .unwrap_or_else(|mut e| errors.append(&mut e));
self.gpu.on_power_event(new_mode).unwrap_or_else(|mut e| errors.append(&mut e)); self.battery
.on_power_event(new_mode)
.unwrap_or_else(|mut e| errors.append(&mut e));
self.cpus
.on_power_event(new_mode)
.unwrap_or_else(|mut e| errors.append(&mut e));
self.gpu
.on_power_event(new_mode)
.unwrap_or_else(|mut e| errors.append(&mut e));
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
} else { } else {
Err(errors) Err(errors)
} }

View file

@ -2,9 +2,9 @@ use std::convert::Into;
use limits_core::json::GenericBatteryLimit; use limits_core::json::GenericBatteryLimit;
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::TBattery;
use crate::persist::BatteryJson; use crate::persist::BatteryJson;
use crate::settings::TBattery;
use crate::settings::{OnResume, OnSet, SettingError};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Battery { pub struct Battery {
@ -39,16 +39,16 @@ impl Battery {
pub fn from_limits(limits: limits_core::json::GenericBatteryLimit) -> Self { pub fn from_limits(limits: limits_core::json::GenericBatteryLimit) -> Self {
// TODO // TODO
Self { Self { limits }
limits
}
} }
pub fn from_json_and_limits(_other: BatteryJson, _version: u64, limits: limits_core::json::GenericBatteryLimit) -> Self { pub fn from_json_and_limits(
_other: BatteryJson,
_version: u64,
limits: limits_core::json::GenericBatteryLimit,
) -> Self {
// TODO // TODO
Self { Self { limits }
limits
}
} }
} }
@ -83,15 +83,13 @@ impl TBattery for Battery {
self.clone().into() self.clone().into()
} }
fn charge_rate(&mut self, _rate: Option<u64>) { fn charge_rate(&mut self, _rate: Option<u64>) {}
}
fn get_charge_rate(&self) -> Option<u64> { fn get_charge_rate(&self) -> Option<u64> {
None None
} }
fn charge_mode(&mut self, _rate: Option<String>) { fn charge_mode(&mut self, _rate: Option<String>) {}
}
fn get_charge_mode(&self) -> Option<String> { fn get_charge_mode(&self) -> Option<String> {
None None
@ -133,7 +131,9 @@ impl TBattery for Battery {
fn charge_limit(&mut self, _limit: Option<f64>) {} fn charge_limit(&mut self, _limit: Option<f64>) {}
fn get_charge_limit(&self) -> Option<f64> { None } fn get_charge_limit(&self) -> Option<f64> {
None
}
fn provider(&self) -> crate::persist::DriverJson { fn provider(&self) -> crate::persist::DriverJson {
crate::persist::DriverJson::Generic crate::persist::DriverJson::Generic

View file

@ -1,12 +1,12 @@
use std::convert::{Into, AsMut, AsRef}; use std::convert::{AsMut, AsRef, Into};
use limits_core::json::GenericCpuLimit; use limits_core::json::GenericCpuLimit;
use crate::settings::{MinMax, min_max_from_json};
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::{TCpus, TCpu};
use crate::persist::CpuJson;
use super::FromGenericCpuInfo; use super::FromGenericCpuInfo;
use crate::persist::CpuJson;
use crate::settings::{min_max_from_json, MinMax};
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::{TCpu, TCpus};
const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present";
const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control";
@ -24,25 +24,19 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + OnSet> OnSet for Cpus<C> {
if self.smt_capable { if self.smt_capable {
// toggle SMT // toggle SMT
if self.smt { if self.smt {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "on").map_err(|e| { usdpl_back::api::files::write_single(CPU_SMT_PATH, "on")
SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!("Failed to write `on` to `{}`: {}", CPU_SMT_PATH, e),
"Failed to write `on` to `{}`: {}",
CPU_SMT_PATH, e
),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
} else { } else {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| { usdpl_back::api::files::write_single(CPU_SMT_PATH, "off")
SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!("Failed to write `off` to `{}`: {}", CPU_SMT_PATH, e),
"Failed to write `off` to `{}`: {}",
CPU_SMT_PATH, e
),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
} }
} }
for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() {
@ -61,7 +55,8 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + OnResume> OnResume for Cpus<C> {
fn on_resume(&self) -> Result<(), Vec<SettingError>> { fn on_resume(&self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new(); let mut errors = Vec::new();
for cpu in &self.cpus { for cpu in &self.cpus {
cpu.on_resume().unwrap_or_else(|mut e| errors.append(&mut e)); cpu.on_resume()
.unwrap_or_else(|mut e| errors.append(&mut e));
} }
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
@ -88,7 +83,7 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> Cpus<C> {
fn system_smt_capabilities() -> (bool, bool) { fn system_smt_capabilities() -> (bool, bool) {
match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) { match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) {
Ok(val) => (val.trim().to_lowercase() == "on", true), Ok(val) => (val.trim().to_lowercase() == "on", true),
Err(_) => (false, false) Err(_) => (false, false),
} }
} }
@ -107,7 +102,11 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> Cpus<C> {
} }
} }
pub fn from_json_and_limits(mut other: Vec<CpuJson>, version: u64, limits: limits_core::json::GenericCpuLimit) -> Self { pub fn from_json_and_limits(
mut other: Vec<CpuJson>,
version: u64,
limits: limits_core::json::GenericCpuLimit,
) -> Self {
let (_, can_smt) = Self::system_smt_capabilities(); let (_, can_smt) = Self::system_smt_capabilities();
let mut result = Vec::with_capacity(other.len()); let mut result = Vec::with_capacity(other.len());
let max_cpus = Self::cpu_count(); let max_cpus = Self::cpu_count();
@ -138,11 +137,17 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> Cpus<C> {
} }
} }
impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + crate::settings::OnPowerEvent> crate::settings::OnPowerEvent for Cpus<C> { impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + crate::settings::OnPowerEvent>
fn on_power_event(&mut self, new_mode: crate::settings::PowerMode) -> Result<(), Vec<SettingError>> { crate::settings::OnPowerEvent for Cpus<C>
{
fn on_power_event(
&mut self,
new_mode: crate::settings::PowerMode,
) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new(); let mut errors = Vec::new();
for cpu in &mut self.cpus { for cpu in &mut self.cpus {
cpu.on_power_event(new_mode).unwrap_or_else(|mut e| errors.append(&mut e)); cpu.on_power_event(new_mode)
.unwrap_or_else(|mut e| errors.append(&mut e));
} }
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
@ -152,7 +157,9 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + crate::settings::OnPowerEvent> crate::s
} }
} }
impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + OnResume + OnSet + crate::settings::OnPowerEvent> TCpus for Cpus<C> { impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + OnResume + OnSet + crate::settings::OnPowerEvent> TCpus
for Cpus<C>
{
fn limits(&self) -> crate::api::CpusLimits { fn limits(&self) -> crate::api::CpusLimits {
crate::api::CpusLimits { crate::api::CpusLimits {
cpus: self.cpus.iter().map(|x| x.as_ref().limits()).collect(), cpus: self.cpus.iter().map(|x| x.as_ref().limits()).collect(),
@ -163,7 +170,10 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + OnResume + OnSet + crate::settings::OnP
} }
fn json(&self) -> Vec<crate::persist::CpuJson> { fn json(&self) -> Vec<crate::persist::CpuJson> {
self.cpus.iter().map(|x| x.as_ref().to_owned().into()).collect() self.cpus
.iter()
.map(|x| x.as_ref().to_owned().into())
.collect()
} }
fn cpus(&mut self) -> Vec<&mut dyn TCpu> { fn cpus(&mut self) -> Vec<&mut dyn TCpu> {
@ -228,7 +238,12 @@ impl FromGenericCpuInfo for Cpu {
} }
#[inline] #[inline]
fn from_json_and_limits(other: CpuJson, version: u64, i: usize, limits: GenericCpuLimit) -> Self { fn from_json_and_limits(
other: CpuJson,
version: u64,
i: usize,
limits: GenericCpuLimit,
) -> Self {
let clock_lims = if limits.clock_min.is_some() && limits.clock_max.is_some() { let clock_lims = if limits.clock_min.is_some() && limits.clock_max.is_some() {
other.clock_limits.map(|x| min_max_from_json(x, version)) other.clock_limits.map(|x| min_max_from_json(x, version))
} else { } else {
@ -259,28 +274,29 @@ impl Cpu {
fn set_all(&mut self) -> Result<(), Vec<SettingError>> { fn set_all(&mut self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new(); let mut errors = Vec::new();
// set cpu online/offline // set cpu online/offline
if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled if self.index != 0 && self.state.do_set_online {
// cpu0 cannot be disabled
let online_path = cpu_online_path(self.index); let online_path = cpu_online_path(self.index);
usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| { usdpl_back::api::files::write_single(&online_path, self.online as u8)
SettingError { .map_err(|e| SettingError {
msg: format!("Failed to write to `{}`: {}", &online_path, e), msg: format!("Failed to write to `{}`: {}", &online_path, e),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
} }
// set governor // set governor
if self.index == 0 || self.online { if self.index == 0 || self.online {
let governor_path = cpu_governor_path(self.index); let governor_path = cpu_governor_path(self.index);
usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| { usdpl_back::api::files::write_single(&governor_path, &self.governor)
SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
&self.governor, &governor_path, e &self.governor, &governor_path, e
), ),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
} }
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
@ -301,13 +317,14 @@ impl Cpu {
fn governors(&self) -> Vec<String> { fn governors(&self) -> Vec<String> {
// NOTE: this eats errors // NOTE: this eats errors
let gov_str: String = match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) { let gov_str: String =
Ok(s) => s, match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) {
Err(e) => { Ok(s) => s,
log::warn!("Error getting available CPU governors: {}", e); Err(e) => {
return vec![]; log::warn!("Error getting available CPU governors: {}", e);
}, return vec![];
}; }
};
gov_str.split(' ').map(|s| s.to_owned()).collect() gov_str.split(' ').map(|s| s.to_owned()).collect()
} }

View file

@ -2,10 +2,10 @@ use std::convert::Into;
use limits_core::json::GenericGpuLimit; use limits_core::json::GenericGpuLimit;
use crate::settings::{MinMax, min_max_from_json};
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::TGpu;
use crate::persist::GpuJson; use crate::persist::GpuJson;
use crate::settings::TGpu;
use crate::settings::{min_max_from_json, MinMax};
use crate::settings::{OnResume, OnSet, SettingError};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Gpu { pub struct Gpu {
@ -40,7 +40,11 @@ impl Gpu {
} }
} }
pub fn from_json_and_limits(other: GpuJson, version: u64, limits: limits_core::json::GenericGpuLimit) -> Self { pub fn from_json_and_limits(
other: GpuJson,
version: u64,
limits: limits_core::json::GenericGpuLimit,
) -> Self {
let clock_lims = if limits.clock_min.is_some() && limits.clock_max.is_some() { let clock_lims = if limits.clock_min.is_some() && limits.clock_max.is_some() {
other.clock_limits.map(|x| min_max_from_json(x, version)) other.clock_limits.map(|x| min_max_from_json(x, version))
} else { } else {
@ -48,8 +52,16 @@ impl Gpu {
}; };
Self { Self {
slow_memory: false, slow_memory: false,
fast_ppt: if limits.fast_ppt.is_some() {other.fast_ppt} else {None}, fast_ppt: if limits.fast_ppt.is_some() {
slow_ppt: if limits.slow_ppt.is_some() {other.slow_ppt} else {None}, other.fast_ppt
} else {
None
},
slow_ppt: if limits.slow_ppt.is_some() {
other.slow_ppt
} else {
None
},
clock_limits: clock_lims, clock_limits: clock_lims,
limits, limits,
} }

View file

@ -1,8 +1,13 @@
use limits_core::json::GenericCpuLimit;
use crate::persist::CpuJson; use crate::persist::CpuJson;
use limits_core::json::GenericCpuLimit;
pub trait FromGenericCpuInfo { pub trait FromGenericCpuInfo {
fn from_limits(cpu_index: usize, limits: GenericCpuLimit) -> Self; fn from_limits(cpu_index: usize, limits: GenericCpuLimit) -> Self;
fn from_json_and_limits(other: CpuJson, version: u64, cpu_index: usize, limits: GenericCpuLimit) -> Self; fn from_json_and_limits(
other: CpuJson,
version: u64,
cpu_index: usize,
limits: GenericCpuLimit,
) -> Self;
} }

View file

@ -1,8 +1,8 @@
use crate::persist::CpuJson; use crate::persist::CpuJson;
use crate::settings::MinMax;
use crate::settings::generic::{Cpu as GenericCpu, Cpus as GenericCpus, FromGenericCpuInfo}; use crate::settings::generic::{Cpu as GenericCpu, Cpus as GenericCpus, FromGenericCpuInfo};
use crate::settings::MinMax;
use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::{TCpus, TCpu}; use crate::settings::{TCpu, TCpus};
#[derive(Debug)] #[derive(Debug)]
pub struct Cpus { pub struct Cpus {
@ -16,7 +16,11 @@ impl Cpus {
} }
} }
pub fn from_json_and_limits(other: Vec<CpuJson>, version: u64, limits: limits_core::json::GenericCpuLimit) -> Self { pub fn from_json_and_limits(
other: Vec<CpuJson>,
version: u64,
limits: limits_core::json::GenericCpuLimit,
) -> Self {
Self { Self {
generic: GenericCpus::from_json_and_limits(other, version, limits), generic: GenericCpus::from_json_and_limits(other, version, limits),
} }
@ -73,16 +77,17 @@ pub struct Cpu {
impl FromGenericCpuInfo for Cpu { impl FromGenericCpuInfo for Cpu {
fn from_limits(cpu_index: usize, limits: limits_core::json::GenericCpuLimit) -> Self { fn from_limits(cpu_index: usize, limits: limits_core::json::GenericCpuLimit) -> Self {
let gen = GenericCpu::from_limits(cpu_index, limits.clone()); let gen = GenericCpu::from_limits(cpu_index, limits.clone());
Self { Self { generic: gen }
generic: gen,
}
} }
fn from_json_and_limits(other: CpuJson, version: u64, cpu_index: usize, limits: limits_core::json::GenericCpuLimit) -> Self { fn from_json_and_limits(
other: CpuJson,
version: u64,
cpu_index: usize,
limits: limits_core::json::GenericCpuLimit,
) -> Self {
let gen = GenericCpu::from_json_and_limits(other, version, cpu_index, limits); let gen = GenericCpu::from_json_and_limits(other, version, cpu_index, limits);
Self { Self { generic: gen }
generic: gen,
}
} }
} }

View file

@ -1,11 +1,11 @@
use std::sync::Mutex;
use libryzenadj::RyzenAdj; use libryzenadj::RyzenAdj;
use std::sync::Mutex;
use crate::persist::GpuJson; use crate::persist::GpuJson;
use crate::settings::MinMax;
use crate::settings::generic::Gpu as GenericGpu; use crate::settings::generic::Gpu as GenericGpu;
use crate::settings::{OnResume, OnSet, SettingError, SettingVariant}; use crate::settings::MinMax;
use crate::settings::TGpu; use crate::settings::TGpu;
use crate::settings::{OnResume, OnSet, SettingError, SettingVariant};
fn ryzen_adj_or_log() -> Option<Mutex<RyzenAdj>> { fn ryzen_adj_or_log() -> Option<Mutex<RyzenAdj>> {
match RyzenAdj::new() { match RyzenAdj::new() {
@ -44,7 +44,11 @@ impl Gpu {
} }
} }
pub fn from_json_and_limits(other: GpuJson, version: u64, limits: limits_core::json::GenericGpuLimit) -> Self { pub fn from_json_and_limits(
other: GpuJson,
version: u64,
limits: limits_core::json::GenericGpuLimit,
) -> Self {
Self { Self {
generic: GenericGpu::from_json_and_limits(other, version, limits), generic: GenericGpu::from_json_and_limits(other, version, limits),
implementor: ryzen_adj_or_log(), implementor: ryzen_adj_or_log(),
@ -76,71 +80,95 @@ impl Gpu {
if self.state.old_fast_ppt.is_none() { if self.state.old_fast_ppt.is_none() {
match lock.get_fast_value() { match lock.get_fast_value() {
Ok(val) => self.state.old_fast_ppt = Some(val as _), Ok(val) => self.state.old_fast_ppt = Some(val as _),
Err(e) => errors.push( Err(e) => errors.push(SettingError {
SettingError { msg: format!("RyzenAdj get_fast_value() err: {}", e),
msg: format!("RyzenAdj get_fast_value() err: {}", e), setting: SettingVariant::Gpu,
setting: SettingVariant::Gpu, }),
}
)
} }
} }
lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError { lock.set_fast_limit(*fast_ppt as _)
msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e), .map_err(|e| SettingError {
setting: SettingVariant::Gpu, msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e),
}).unwrap_or_else(|e| errors.push(e)); setting: SettingVariant::Gpu,
})
.unwrap_or_else(|e| errors.push(e));
} else if let Some(fast_ppt) = &self.state.old_fast_ppt { } else if let Some(fast_ppt) = &self.state.old_fast_ppt {
lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError { lock.set_fast_limit(*fast_ppt as _)
msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e), .map_err(|e| SettingError {
setting: SettingVariant::Gpu, msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e),
}).unwrap_or_else(|e| errors.push(e)); setting: SettingVariant::Gpu,
})
.unwrap_or_else(|e| errors.push(e));
self.state.old_fast_ppt = None; self.state.old_fast_ppt = None;
} }
if let Some(slow_ppt) = &self.generic.slow_ppt { if let Some(slow_ppt) = &self.generic.slow_ppt {
if self.state.old_slow_ppt.is_none() { if self.state.old_slow_ppt.is_none() {
match lock.get_slow_value() { match lock.get_slow_value() {
Ok(val) => self.state.old_fast_ppt = Some(val as _), Ok(val) => self.state.old_fast_ppt = Some(val as _),
Err(e) => errors.push( Err(e) => errors.push(SettingError {
SettingError { msg: format!("RyzenAdj get_slow_value() err: {}", e),
msg: format!("RyzenAdj get_slow_value() err: {}", e), setting: SettingVariant::Gpu,
setting: SettingVariant::Gpu, }),
}
)
} }
} }
lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError { lock.set_slow_limit(*slow_ppt as _)
msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e), .map_err(|e| SettingError {
setting: SettingVariant::Gpu, msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e),
}).unwrap_or_else(|e| errors.push(e)); setting: SettingVariant::Gpu,
})
.unwrap_or_else(|e| errors.push(e));
} else if let Some(slow_ppt) = &self.state.old_slow_ppt { } else if let Some(slow_ppt) = &self.state.old_slow_ppt {
lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError { lock.set_slow_limit(*slow_ppt as _)
msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e), .map_err(|e| SettingError {
setting: SettingVariant::Gpu, msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e),
}).unwrap_or_else(|e| errors.push(e)); setting: SettingVariant::Gpu,
})
.unwrap_or_else(|e| errors.push(e));
self.state.old_slow_ppt = None; self.state.old_slow_ppt = None;
} }
if let Some(clock_limits) = &self.generic.clock_limits { if let Some(clock_limits) = &self.generic.clock_limits {
self.state.clock_limits_set = true; self.state.clock_limits_set = true;
lock.set_max_gfxclk_freq(clock_limits.max as _).map_err(|e| SettingError { lock.set_max_gfxclk_freq(clock_limits.max as _)
msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", clock_limits.max, e), .map_err(|e| SettingError {
setting: SettingVariant::Gpu, msg: format!(
}).unwrap_or_else(|e| errors.push(e)); "RyzenAdj set_max_gfxclk_freq({}) err: {}",
lock.set_min_gfxclk_freq(clock_limits.min as _).map_err(|e| SettingError { clock_limits.max, e
msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", clock_limits.min, e), ),
setting: SettingVariant::Gpu, setting: SettingVariant::Gpu,
}).unwrap_or_else(|e| errors.push(e)); })
.unwrap_or_else(|e| errors.push(e));
lock.set_min_gfxclk_freq(clock_limits.min as _)
.map_err(|e| SettingError {
msg: format!(
"RyzenAdj set_min_gfxclk_freq({}) err: {}",
clock_limits.min, e
),
setting: SettingVariant::Gpu,
})
.unwrap_or_else(|e| errors.push(e));
} else if self.state.clock_limits_set { } else if self.state.clock_limits_set {
self.state.clock_limits_set = false; self.state.clock_limits_set = false;
let limits = self.generic.limits(); let limits = self.generic.limits();
if let Some(min_limits) = limits.clock_min_limits { if let Some(min_limits) = limits.clock_min_limits {
if let Some(max_limits) = limits.clock_max_limits { if let Some(max_limits) = limits.clock_max_limits {
lock.set_max_gfxclk_freq(max_limits.max as _).map_err(|e| SettingError { lock.set_max_gfxclk_freq(max_limits.max as _)
msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", max_limits.max, e), .map_err(|e| SettingError {
setting: SettingVariant::Gpu, msg: format!(
}).unwrap_or_else(|e| errors.push(e)); "RyzenAdj set_max_gfxclk_freq({}) err: {}",
lock.set_min_gfxclk_freq(min_limits.min as _).map_err(|e| SettingError { max_limits.max, e
msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", min_limits.min, e), ),
setting: SettingVariant::Gpu, setting: SettingVariant::Gpu,
}).unwrap_or_else(|e| errors.push(e)); })
.unwrap_or_else(|e| errors.push(e));
lock.set_min_gfxclk_freq(min_limits.min as _)
.map_err(|e| SettingError {
msg: format!(
"RyzenAdj set_min_gfxclk_freq({}) err: {}",
min_limits.min, e
),
setting: SettingVariant::Gpu,
})
.unwrap_or_else(|e| errors.push(e));
} }
} }
} }
@ -174,26 +202,40 @@ impl Gpu {
}; };
let mut errors = Vec::new(); let mut errors = Vec::new();
if let Some(fast_ppt) = &self.generic.fast_ppt { if let Some(fast_ppt) = &self.generic.fast_ppt {
lock.set_fast_limit(*fast_ppt as _).map_err(|e| SettingError { lock.set_fast_limit(*fast_ppt as _)
msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e), .map_err(|e| SettingError {
setting: SettingVariant::Gpu, msg: format!("RyzenAdj set_fast_limit({}) err: {}", *fast_ppt, e),
}).unwrap_or_else(|e| errors.push(e)); setting: SettingVariant::Gpu,
})
.unwrap_or_else(|e| errors.push(e));
} }
if let Some(slow_ppt) = &self.generic.slow_ppt { if let Some(slow_ppt) = &self.generic.slow_ppt {
lock.set_slow_limit(*slow_ppt as _).map_err(|e| SettingError { lock.set_slow_limit(*slow_ppt as _)
msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e), .map_err(|e| SettingError {
setting: SettingVariant::Gpu, msg: format!("RyzenAdj set_slow_limit({}) err: {}", *slow_ppt, e),
}).unwrap_or_else(|e| errors.push(e)); setting: SettingVariant::Gpu,
})
.unwrap_or_else(|e| errors.push(e));
} }
if let Some(clock_limits) = &self.generic.clock_limits { if let Some(clock_limits) = &self.generic.clock_limits {
lock.set_max_gfxclk_freq(clock_limits.max as _).map_err(|e| SettingError { lock.set_max_gfxclk_freq(clock_limits.max as _)
msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", clock_limits.max, e), .map_err(|e| SettingError {
setting: SettingVariant::Gpu, msg: format!(
}).unwrap_or_else(|e| errors.push(e)); "RyzenAdj set_max_gfxclk_freq({}) err: {}",
lock.set_min_gfxclk_freq(clock_limits.min as _).map_err(|e| SettingError { clock_limits.max, e
msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", clock_limits.min, e), ),
setting: SettingVariant::Gpu, setting: SettingVariant::Gpu,
}).unwrap_or_else(|e| errors.push(e)); })
.unwrap_or_else(|e| errors.push(e));
lock.set_min_gfxclk_freq(clock_limits.min as _)
.map_err(|e| SettingError {
msg: format!(
"RyzenAdj set_min_gfxclk_freq({}) err: {}",
clock_limits.min, e
),
setting: SettingVariant::Gpu,
})
.unwrap_or_else(|e| errors.push(e));
} }
Ok(()) Ok(())
} }

View file

@ -13,11 +13,11 @@ pub mod unknown;
pub use detect::{auto_detect0, auto_detect_provider, limits_worker::spawn as limits_worker_spawn}; pub use detect::{auto_detect0, auto_detect_provider, limits_worker::spawn as limits_worker_spawn};
pub use driver::Driver; pub use driver::Driver;
pub use general::{SettingVariant, Settings, General}; pub use general::{General, SettingVariant, Settings};
pub use min_max::{MinMax, min_max_from_json}; pub use min_max::{min_max_from_json, MinMax};
pub use error::SettingError; pub use error::SettingError;
pub use traits::{OnResume, OnSet, TGeneral, TGpu, TCpus, TBattery, TCpu, OnPowerEvent, PowerMode}; pub use traits::{OnPowerEvent, OnResume, OnSet, PowerMode, TBattery, TCpu, TCpus, TGeneral, TGpu};
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

View file

@ -1,11 +1,11 @@
use std::convert::Into; use std::convert::Into;
use crate::api::RangeLimit;
use crate::settings::{OnResume, OnSet, SettingError, OnPowerEvent, PowerMode};
use crate::settings::TBattery;
use crate::persist::{BatteryJson, BatteryEventJson};
use super::util::ChargeMode;
use super::oc_limits::{BatteryLimits, OverclockLimits}; use super::oc_limits::{BatteryLimits, OverclockLimits};
use super::util::ChargeMode;
use crate::api::RangeLimit;
use crate::persist::{BatteryEventJson, BatteryJson};
use crate::settings::TBattery;
use crate::settings::{OnPowerEvent, OnResume, OnSet, PowerMode, SettingError};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Battery { pub struct Battery {
@ -40,11 +40,11 @@ impl OnPowerEvent for EventInstruction {
(EventTrigger::PluggedIn, PowerMode::PluggedIn) => { (EventTrigger::PluggedIn, PowerMode::PluggedIn) => {
log::info!("Steam Deck plugged in event handled"); log::info!("Steam Deck plugged in event handled");
self.set_all() self.set_all()
}, }
(EventTrigger::PluggedOut, PowerMode::PluggedOut) => { (EventTrigger::PluggedOut, PowerMode::PluggedOut) => {
log::info!("Steam Deck plugged out event handled"); log::info!("Steam Deck plugged out event handled");
self.set_all() self.set_all()
}, }
(EventTrigger::BatteryAbove(exp), PowerMode::BatteryCharge(act)) => { (EventTrigger::BatteryAbove(exp), PowerMode::BatteryCharge(act)) => {
if act > *exp { if act > *exp {
if self.is_triggered { if self.is_triggered {
@ -58,7 +58,7 @@ impl OnPowerEvent for EventInstruction {
self.is_triggered = false; self.is_triggered = false;
Ok(()) Ok(())
} }
}, }
(EventTrigger::BatteryBelow(exp), PowerMode::BatteryCharge(act)) => { (EventTrigger::BatteryBelow(exp), PowerMode::BatteryCharge(act)) => {
if act < *exp { if act < *exp {
if self.is_triggered { if self.is_triggered {
@ -72,8 +72,8 @@ impl OnPowerEvent for EventInstruction {
self.is_triggered = false; self.is_triggered = false;
Ok(()) Ok(())
} }
}, }
_ => Ok(()) _ => Ok(()),
} }
} }
} }
@ -95,8 +95,16 @@ impl EventInstruction {
match s { match s {
"normal" => Some(EventTrigger::PluggedIn), "normal" => Some(EventTrigger::PluggedIn),
"idle" => Some(EventTrigger::PluggedOut), "idle" => Some(EventTrigger::PluggedOut),
s if s.starts_with('>') => s.trim_start_matches('>').parse::<f64>().ok().map(|x| EventTrigger::BatteryAbove(x)), s if s.starts_with('>') => s
s if s.starts_with('<') => s.trim_start_matches('<').parse::<f64>().ok().map(|x| EventTrigger::BatteryBelow(x)), .trim_start_matches('>')
.parse::<f64>()
.ok()
.map(|x| EventTrigger::BatteryAbove(x)),
s if s.starts_with('<') => s
.trim_start_matches('<')
.parse::<f64>()
.ok()
.map(|x| EventTrigger::BatteryBelow(x)),
_ => None, _ => None,
} }
} }
@ -105,19 +113,22 @@ impl EventInstruction {
Self { Self {
trigger: Self::str_to_trigger(&other.trigger).unwrap_or(EventTrigger::Ignored), trigger: Self::str_to_trigger(&other.trigger).unwrap_or(EventTrigger::Ignored),
charge_rate: other.charge_rate, charge_rate: other.charge_rate,
charge_mode: other.charge_mode.map(|x| Battery::str_to_charge_mode(&x)).flatten(), charge_mode: other
.charge_mode
.map(|x| Battery::str_to_charge_mode(&x))
.flatten(),
is_triggered: false, is_triggered: false,
} }
} }
fn set_charge_mode(&self) -> Result<(), SettingError> { fn set_charge_mode(&self) -> Result<(), SettingError> {
if let Some(charge_mode) = self.charge_mode { if let Some(charge_mode) = self.charge_mode {
super::util::set(super::util::Setting::ChargeMode, charge_mode as _).map_err( super::util::set(super::util::Setting::ChargeMode, charge_mode as _)
|e| SettingError { .map_err(|e| SettingError {
msg: format!("Failed to set charge mode: {}", e), msg: format!("Failed to set charge mode: {}", e),
setting: crate::settings::SettingVariant::Battery, setting: crate::settings::SettingVariant::Battery,
}, })
).map(|_| ()) .map(|_| ())
} else { } else {
Ok(()) Ok(())
} }
@ -125,18 +136,18 @@ impl EventInstruction {
fn set_charge_rate(&self) -> Result<(), SettingError> { fn set_charge_rate(&self) -> Result<(), SettingError> {
if let Some(charge_rate) = self.charge_rate { if let Some(charge_rate) = self.charge_rate {
usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, charge_rate).map_err( usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, charge_rate)
|e| SettingError { .map_err(|e| SettingError {
msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e),
setting: crate::settings::SettingVariant::Battery, setting: crate::settings::SettingVariant::Battery,
}, })
).map(|_| ()) .map(|_| ())
} else { } else {
Ok(()) Ok(())
} }
} }
fn set_all(&self) -> Result<(), Vec<SettingError>> { fn set_all(&self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new(); let mut errors = Vec::new();
self.set_charge_rate().unwrap_or_else(|e| errors.push(e)); self.set_charge_rate().unwrap_or_else(|e| errors.push(e));
@ -174,20 +185,38 @@ impl Battery {
pub fn from_json(other: BatteryJson, version: u64) -> Self { pub fn from_json(other: BatteryJson, version: u64) -> Self {
let (oc_limits, is_default) = OverclockLimits::load_or_default(); let (oc_limits, is_default) = OverclockLimits::load_or_default();
let oc_limits = oc_limits.battery; let oc_limits = oc_limits.battery;
let driver = if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }; let driver = if is_default {
crate::persist::DriverJson::SteamDeck
} else {
crate::persist::DriverJson::SteamDeckAdvance
};
match version { match version {
0 => Self { 0 => Self {
charge_rate: other.charge_rate, charge_rate: other.charge_rate,
charge_mode: other.charge_mode.map(|x| Self::str_to_charge_mode(&x)).flatten(), charge_mode: other
events: other.events.into_iter().map(|x| EventInstruction::from_json(x, version)).collect(), .charge_mode
.map(|x| Self::str_to_charge_mode(&x))
.flatten(),
events: other
.events
.into_iter()
.map(|x| EventInstruction::from_json(x, version))
.collect(),
limits: oc_limits, limits: oc_limits,
state: crate::state::steam_deck::Battery::default(), state: crate::state::steam_deck::Battery::default(),
driver_mode: driver, driver_mode: driver,
}, },
_ => Self { _ => Self {
charge_rate: other.charge_rate, charge_rate: other.charge_rate,
charge_mode: other.charge_mode.map(|x| Self::str_to_charge_mode(&x)).flatten(), charge_mode: other
events: other.events.into_iter().map(|x| EventInstruction::from_json(x, version)).collect(), .charge_mode
.map(|x| Self::str_to_charge_mode(&x))
.flatten(),
events: other
.events
.into_iter()
.map(|x| EventInstruction::from_json(x, version))
.collect(),
limits: oc_limits, limits: oc_limits,
state: crate::state::steam_deck::Battery::default(), state: crate::state::steam_deck::Battery::default(),
driver_mode: driver, driver_mode: driver,
@ -201,7 +230,8 @@ impl Battery {
ChargeMode::Normal => "normal", ChargeMode::Normal => "normal",
ChargeMode::Idle => "idle", ChargeMode::Idle => "idle",
ChargeMode::Discharge => "discharge", ChargeMode::Discharge => "discharge",
}.to_owned() }
.to_owned()
} }
#[inline] #[inline]
@ -217,20 +247,20 @@ impl Battery {
fn set_charge_mode(&mut self) -> Result<(), SettingError> { fn set_charge_mode(&mut self) -> Result<(), SettingError> {
if let Some(charge_mode) = self.charge_mode { if let Some(charge_mode) = self.charge_mode {
self.state.charge_mode_set = true; self.state.charge_mode_set = true;
super::util::set(super::util::Setting::ChargeMode, charge_mode as _).map_err( super::util::set(super::util::Setting::ChargeMode, charge_mode as _)
|e| SettingError { .map_err(|e| SettingError {
msg: format!("Failed to set charge mode: {}", e), msg: format!("Failed to set charge mode: {}", e),
setting: crate::settings::SettingVariant::Battery, setting: crate::settings::SettingVariant::Battery,
}, })
).map(|_| ()) .map(|_| ())
} else if self.state.charge_mode_set { } else if self.state.charge_mode_set {
self.state.charge_mode_set = false; self.state.charge_mode_set = false;
super::util::set(super::util::Setting::ChargeMode, ChargeMode::Normal as _).map_err( super::util::set(super::util::Setting::ChargeMode, ChargeMode::Normal as _)
|e| SettingError { .map_err(|e| SettingError {
msg: format!("Failed to set charge mode: {}", e), msg: format!("Failed to set charge mode: {}", e),
setting: crate::settings::SettingVariant::Battery, setting: crate::settings::SettingVariant::Battery,
}, })
).map(|_| ()) .map(|_| ())
} else { } else {
Ok(()) Ok(())
} }
@ -240,20 +270,23 @@ impl Battery {
let mut errors = Vec::new(); let mut errors = Vec::new();
if let Some(charge_rate) = self.charge_rate { if let Some(charge_rate) = self.charge_rate {
self.state.charge_rate_set = true; self.state.charge_rate_set = true;
usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, charge_rate).map_err( usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, charge_rate)
|e| SettingError { .map_err(|e| SettingError {
msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e),
setting: crate::settings::SettingVariant::Battery, setting: crate::settings::SettingVariant::Battery,
}, })
).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
} else if self.state.charge_rate_set { } else if self.state.charge_rate_set {
self.state.charge_rate_set = false; self.state.charge_rate_set = false;
usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, self.limits.charge_rate.max).map_err( usdpl_back::api::files::write_single(
|e| SettingError { BATTERY_CHARGE_RATE_PATH,
msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), self.limits.charge_rate.max,
setting: crate::settings::SettingVariant::Battery, )
}, .map_err(|e| SettingError {
).unwrap_or_else(|e| errors.push(e)); msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e),
setting: crate::settings::SettingVariant::Battery,
})
.unwrap_or_else(|e| errors.push(e));
} }
self.set_charge_mode().unwrap_or_else(|e| errors.push(e)); self.set_charge_mode().unwrap_or_else(|e| errors.push(e));
if errors.is_empty() { if errors.is_empty() {
@ -265,7 +298,8 @@ impl Battery {
fn clamp_all(&mut self) { fn clamp_all(&mut self) {
if let Some(charge_rate) = &mut self.charge_rate { if let Some(charge_rate) = &mut self.charge_rate {
*charge_rate = (*charge_rate).clamp(self.limits.charge_rate.min, self.limits.charge_rate.max); *charge_rate =
(*charge_rate).clamp(self.limits.charge_rate.min, self.limits.charge_rate.max);
} }
} }
@ -306,7 +340,10 @@ impl Battery {
pub fn read_charge_design() -> Result<f64, SettingError> { pub fn read_charge_design() -> Result<f64, SettingError> {
match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_DESIGN_PATH) { match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_DESIGN_PATH) {
Err(e) => Err(SettingError { Err(e) => Err(SettingError {
msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_DESIGN_PATH, e), msg: format!(
"Failed to read from `{}`: {}",
BATTERY_CHARGE_DESIGN_PATH, e
),
setting: crate::settings::SettingVariant::Battery, setting: crate::settings::SettingVariant::Battery,
}), }),
// convert to Wh // convert to Wh
@ -321,14 +358,18 @@ impl Battery {
setting: crate::settings::SettingVariant::Battery, setting: crate::settings::SettingVariant::Battery,
}), }),
// convert to V (from mV) // convert to V (from mV)
Ok(val) => Ok((val as f64)/1000.0), Ok(val) => Ok((val as f64) / 1000.0),
} }
} }
pub fn system_default() -> Self { pub fn system_default() -> Self {
let (oc_limits, is_default) = OverclockLimits::load_or_default(); let (oc_limits, is_default) = OverclockLimits::load_or_default();
let oc_limits = oc_limits.battery; let oc_limits = oc_limits.battery;
let driver = if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }; let driver = if is_default {
crate::persist::DriverJson::SteamDeck
} else {
crate::persist::DriverJson::SteamDeckAdvance
};
Self { Self {
charge_rate: None, charge_rate: None,
charge_mode: None, charge_mode: None,
@ -346,8 +387,8 @@ impl Battery {
if event.charge_mode.is_some() { if event.charge_mode.is_some() {
return Some(i); return Some(i);
} }
}, }
_ => {}, _ => {}
} }
} }
None None
@ -360,8 +401,8 @@ impl Battery {
if event.charge_mode.is_some() { if event.charge_mode.is_some() {
return Some(i); return Some(i);
} }
}, }
_ => {}, _ => {}
} }
} }
None None
@ -374,7 +415,7 @@ impl Into<BatteryJson> for Battery {
BatteryJson { BatteryJson {
charge_rate: self.charge_rate, charge_rate: self.charge_rate,
charge_mode: self.charge_mode.map(Self::charge_mode_to_str), charge_mode: self.charge_mode.map(Self::charge_mode_to_str),
events: self.events.into_iter().map(|x| x.into()).collect() events: self.events.into_iter().map(|x| x.into()).collect(),
} }
} }
} }
@ -398,20 +439,24 @@ impl OnPowerEvent for Battery {
match new_mode { match new_mode {
PowerMode::PluggedIn => { PowerMode::PluggedIn => {
// plug event resets battery settings // plug event resets battery settings
self.events.iter_mut().for_each(|ev| ev.is_triggered = false); self.events
self.set_charge_mode() .iter_mut()
.map_err(|e| vec![e]) .for_each(|ev| ev.is_triggered = false);
}, self.set_charge_mode().map_err(|e| vec![e])
}
PowerMode::PluggedOut => { PowerMode::PluggedOut => {
// plug event resets battery settings // plug event resets battery settings
self.events.iter_mut().for_each(|ev| ev.is_triggered = false); self.events
self.set_charge_mode() .iter_mut()
.map_err(|e| vec![e]) .for_each(|ev| ev.is_triggered = false);
}, self.set_charge_mode().map_err(|e| vec![e])
PowerMode::BatteryCharge(_) => Ok(()) }
}.unwrap_or_else(|mut e| errors.append(&mut e)); PowerMode::BatteryCharge(_) => Ok(()),
}
.unwrap_or_else(|mut e| errors.append(&mut e));
for ev in &mut self.events { for ev in &mut self.events {
ev.on_power_event(new_mode).unwrap_or_else(|mut e| errors.append(&mut e)); ev.on_power_event(new_mode)
.unwrap_or_else(|mut e| errors.append(&mut e));
} }
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
@ -424,12 +469,16 @@ impl OnPowerEvent for Battery {
impl TBattery for Battery { impl TBattery for Battery {
fn limits(&self) -> crate::api::BatteryLimits { fn limits(&self) -> crate::api::BatteryLimits {
crate::api::BatteryLimits { crate::api::BatteryLimits {
charge_current: Some(RangeLimit{ charge_current: Some(RangeLimit {
min: self.limits.charge_rate.min, min: self.limits.charge_rate.min,
max: self.limits.charge_rate.max max: self.limits.charge_rate.max,
}), }),
charge_current_step: 50, charge_current_step: 50,
charge_modes: vec!["normal".to_owned(), "discharge".to_owned(), "idle".to_owned()], charge_modes: vec![
"normal".to_owned(),
"discharge".to_owned(),
"idle".to_owned(),
],
charge_limit: Some(RangeLimit { charge_limit: Some(RangeLimit {
min: 10.0, min: 10.0,
max: 90.0, max: 90.0,
@ -503,9 +552,12 @@ impl TBattery for Battery {
let index = self.find_limit_event(); let index = self.find_limit_event();
if let Some(index) = index { if let Some(index) = index {
if let Some(limit) = limit { if let Some(limit) = limit {
log::info!("Updating Steam Deck charge limit event instruction to >{}", limit); log::info!(
"Updating Steam Deck charge limit event instruction to >{}",
limit
);
self.events[index] = EventInstruction { self.events[index] = EventInstruction {
trigger: EventTrigger::BatteryAbove(limit/100.0), trigger: EventTrigger::BatteryAbove(limit / 100.0),
charge_rate: None, charge_rate: None,
charge_mode: Some(ChargeMode::Idle), charge_mode: Some(ChargeMode::Idle),
is_triggered: false, is_triggered: false,
@ -514,24 +566,28 @@ impl TBattery for Battery {
self.events.remove(index); self.events.remove(index);
} }
} else if let Some(limit) = limit { } else if let Some(limit) = limit {
log::info!("Creating Steam Deck charge limit event instruction of >{}", limit); log::info!(
self.events.push( "Creating Steam Deck charge limit event instruction of >{}",
EventInstruction { limit
trigger: EventTrigger::BatteryAbove(limit/100.0),
charge_rate: None,
charge_mode: Some(ChargeMode::Idle),
is_triggered: false,
}
); );
self.events.push(EventInstruction {
trigger: EventTrigger::BatteryAbove(limit / 100.0),
charge_rate: None,
charge_mode: Some(ChargeMode::Idle),
is_triggered: false,
});
} }
// lower limit // lower limit
let index = self.find_unlimit_event(); let index = self.find_unlimit_event();
if let Some(index) = index { if let Some(index) = index {
if let Some(limit) = limit { if let Some(limit) = limit {
let limit = (limit - 10.0).clamp(0.0, 100.0); let limit = (limit - 10.0).clamp(0.0, 100.0);
log::info!("Updating Steam Deck charge limit event instruction to <{}", limit); log::info!(
"Updating Steam Deck charge limit event instruction to <{}",
limit
);
self.events[index] = EventInstruction { self.events[index] = EventInstruction {
trigger: EventTrigger::BatteryBelow(limit/100.0), trigger: EventTrigger::BatteryBelow(limit / 100.0),
charge_rate: None, charge_rate: None,
charge_mode: Some(ChargeMode::Normal), charge_mode: Some(ChargeMode::Normal),
is_triggered: false, is_triggered: false,
@ -541,15 +597,16 @@ impl TBattery for Battery {
} }
} else if let Some(limit) = limit { } else if let Some(limit) = limit {
let limit = (limit - 10.0).clamp(0.0, 100.0); let limit = (limit - 10.0).clamp(0.0, 100.0);
log::info!("Creating Steam Deck charge limit event instruction of <{}", limit); log::info!(
self.events.push( "Creating Steam Deck charge limit event instruction of <{}",
EventInstruction { limit
trigger: EventTrigger::BatteryBelow(limit/100.0),
charge_rate: None,
charge_mode: Some(ChargeMode::Normal),
is_triggered: false,
}
); );
self.events.push(EventInstruction {
trigger: EventTrigger::BatteryBelow(limit / 100.0),
charge_rate: None,
charge_mode: Some(ChargeMode::Normal),
is_triggered: false,
});
} }
} }
@ -572,24 +629,28 @@ impl TBattery for Battery {
let mut errors = Vec::new(); let mut errors = Vec::new();
let mut events = Vec::new(); let mut events = Vec::new();
match (Self::read_charge_full(), Self::read_charge_now()) { match (Self::read_charge_full(), Self::read_charge_now()) {
(Ok(full), Ok(now)) => events.push(PowerMode::BatteryCharge(now/full)), (Ok(full), Ok(now)) => events.push(PowerMode::BatteryCharge(now / full)),
(Err(e1), Err(e2)) => { (Err(e1), Err(e2)) => {
errors.push(e1); errors.push(e1);
errors.push(e2); errors.push(e2);
}, }
(Err(e), _) => errors.push(e), (Err(e), _) => errors.push(e),
(_, Err(e)) => errors.push(e), (_, Err(e)) => errors.push(e),
} }
match Self::read_usb_voltage() { match Self::read_usb_voltage() {
Ok(voltage) => { Ok(voltage) => {
if voltage > 0.0 && self.state.charger_state != crate::state::steam_deck::ChargeState::PluggedIn { if voltage > 0.0
&& self.state.charger_state != crate::state::steam_deck::ChargeState::PluggedIn
{
events.push(PowerMode::PluggedIn); events.push(PowerMode::PluggedIn);
self.state.charger_state = crate::state::steam_deck::ChargeState::PluggedIn; self.state.charger_state = crate::state::steam_deck::ChargeState::PluggedIn;
} else if voltage == 0.0 && self.state.charger_state != crate::state::steam_deck::ChargeState::Unplugged { } else if voltage == 0.0
&& self.state.charger_state != crate::state::steam_deck::ChargeState::Unplugged
{
events.push(PowerMode::PluggedOut); events.push(PowerMode::PluggedOut);
self.state.charger_state = crate::state::steam_deck::ChargeState::Unplugged; self.state.charger_state = crate::state::steam_deck::ChargeState::Unplugged;
} }
}, }
Err(e) => errors.push(e), Err(e) => errors.push(e),
} }
if errors.is_empty() { if errors.is_empty() {

View file

@ -1,12 +1,12 @@
use std::convert::Into; use std::convert::Into;
use crate::api::RangeLimit; use super::oc_limits::{CpuLimits, CpusLimits, OverclockLimits};
use crate::settings::{MinMax, min_max_from_json};
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::{TCpus, TCpu};
use crate::persist::CpuJson;
use super::oc_limits::{OverclockLimits, CpusLimits, CpuLimits};
use super::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT; use super::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT;
use crate::api::RangeLimit;
use crate::persist::CpuJson;
use crate::settings::{min_max_from_json, MinMax};
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::{TCpu, TCpus};
const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present";
const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control";
@ -26,25 +26,19 @@ impl OnSet for Cpus {
if self.smt_capable { if self.smt_capable {
// toggle SMT // toggle SMT
if self.smt { if self.smt {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "on").map_err(|e| { usdpl_back::api::files::write_single(CPU_SMT_PATH, "on")
SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!("Failed to write `on` to `{}`: {}", CPU_SMT_PATH, e),
"Failed to write `on` to `{}`: {}",
CPU_SMT_PATH, e
),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
} else { } else {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| { usdpl_back::api::files::write_single(CPU_SMT_PATH, "off")
SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!("Failed to write `off` to `{}`: {}", CPU_SMT_PATH, e),
"Failed to write `off` to `{}`: {}",
CPU_SMT_PATH, e
),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
} }
} }
for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() {
@ -63,7 +57,8 @@ impl OnResume for Cpus {
fn on_resume(&self) -> Result<(), Vec<SettingError>> { fn on_resume(&self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new(); let mut errors = Vec::new();
for cpu in &self.cpus { for cpu in &self.cpus {
cpu.on_resume().unwrap_or_else(|mut e| errors.append(&mut e)); cpu.on_resume()
.unwrap_or_else(|mut e| errors.append(&mut e));
} }
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
@ -90,7 +85,7 @@ impl Cpus {
fn system_smt_capabilities() -> (bool, bool) { fn system_smt_capabilities() -> (bool, bool) {
match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) { match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) {
Ok(val) => (val.trim().to_lowercase() == "on", true), Ok(val) => (val.trim().to_lowercase() == "on", true),
Err(_) => (false, false) Err(_) => (false, false),
} }
} }
@ -98,11 +93,22 @@ impl Cpus {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.reset(); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.reset();
let (oc_limits, is_default) = OverclockLimits::load_or_default(); let (oc_limits, is_default) = OverclockLimits::load_or_default();
let oc_limits = oc_limits.cpus; let oc_limits = oc_limits.cpus;
let driver = if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }; let driver = if is_default {
crate::persist::DriverJson::SteamDeck
} else {
crate::persist::DriverJson::SteamDeckAdvance
};
if let Some(max_cpu) = Self::cpu_count() { if let Some(max_cpu) = Self::cpu_count() {
let mut sys_cpus = Vec::with_capacity(max_cpu); let mut sys_cpus = Vec::with_capacity(max_cpu);
for i in 0..max_cpu { for i in 0..max_cpu {
sys_cpus.push(Cpu::system_default(i, oc_limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_default())); sys_cpus.push(Cpu::system_default(
i,
oc_limits
.cpus
.get(i)
.map(|x| x.to_owned())
.unwrap_or_default(),
));
} }
let (_, can_smt) = Self::system_smt_capabilities(); let (_, can_smt) = Self::system_smt_capabilities();
Self { Self {
@ -128,7 +134,11 @@ impl Cpus {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.reset(); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.reset();
let (oc_limits, is_default) = OverclockLimits::load_or_default(); let (oc_limits, is_default) = OverclockLimits::load_or_default();
let oc_limits = oc_limits.cpus; let oc_limits = oc_limits.cpus;
let driver = if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }; let driver = if is_default {
crate::persist::DriverJson::SteamDeck
} else {
crate::persist::DriverJson::SteamDeckAdvance
};
let (_, can_smt) = Self::system_smt_capabilities(); let (_, can_smt) = Self::system_smt_capabilities();
let mut result = Vec::with_capacity(other.len()); let mut result = Vec::with_capacity(other.len());
let max_cpus = Self::cpu_count(); let max_cpus = Self::cpu_count();
@ -140,7 +150,16 @@ impl Cpus {
break; break;
} }
} }
let new_cpu = Cpu::from_json(cpu, version, i, oc_limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_default()); let new_cpu = Cpu::from_json(
cpu,
version,
i,
oc_limits
.cpus
.get(i)
.map(|x| x.to_owned())
.unwrap_or_default(),
);
result.push(new_cpu); result.push(new_cpu);
} }
if let Some(max_cpus) = max_cpus { if let Some(max_cpus) = max_cpus {
@ -170,11 +189,14 @@ impl TCpus for Cpus {
count: self.cpus.len(), count: self.cpus.len(),
smt_capable: self.smt_capable, smt_capable: self.smt_capable,
governors: if self.limits.global_governors { governors: if self.limits.global_governors {
self.cpus.iter() self.cpus
.iter()
.next() .next()
.map(|x| x.governors()) .map(|x| x.governors())
.unwrap_or_else(|| Vec::with_capacity(0)) .unwrap_or_else(|| Vec::with_capacity(0))
} else { Vec::with_capacity(0) }, } else {
Vec::with_capacity(0)
},
} }
} }
@ -244,41 +266,52 @@ impl Cpu {
if let Some(clock_limits) = &self.clock_limits { if let Some(clock_limits) = &self.clock_limits {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(true, self.index); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(true, self.index);
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?; POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?;
log::debug!("Setting CPU {} (min, max) clockspeed to ({}, {})", self.index, clock_limits.min, clock_limits.max); log::debug!(
"Setting CPU {} (min, max) clockspeed to ({}, {})",
self.index,
clock_limits.min,
clock_limits.max
);
self.state.clock_limits_set = true; self.state.clock_limits_set = true;
// max clock // max clock
let payload_max = format!("p {} 1 {}\n", self.index / 2, clock_limits.max); let payload_max = format!("p {} 1 {}\n", self.index / 2, clock_limits.max);
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max).map_err( usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max)
|e| SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
&payload_max, CPU_CLOCK_LIMITS_PATH, e &payload_max, CPU_CLOCK_LIMITS_PATH, e
), ),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
}, })
).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
// min clock // min clock
let valid_min = if clock_limits.min < self.limits.clock_min.min {self.limits.clock_min.min} else {clock_limits.min}; let valid_min = if clock_limits.min < self.limits.clock_min.min {
self.limits.clock_min.min
} else {
clock_limits.min
};
let payload_min = format!("p {} 0 {}\n", self.index / 2, valid_min); let payload_min = format!("p {} 0 {}\n", self.index / 2, valid_min);
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min).map_err( usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min)
|e| SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
&payload_min, CPU_CLOCK_LIMITS_PATH, e &payload_min, CPU_CLOCK_LIMITS_PATH, e
), ),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
}, })
).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n") usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else(
.unwrap_or_else(|e| { |e| {
errors.push(SettingError { errors.push(SettingError {
msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e), msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
}); });
}); },
} else if self.state.clock_limits_set || );
(self.state.is_resuming && !self.limits.skip_resume_reclock) } else if self.state.clock_limits_set
|| POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { || (self.state.is_resuming && !self.limits.skip_resume_reclock)
|| POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual()
{
self.state.clock_limits_set = false; self.state.clock_limits_set = false;
if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?; POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?;
@ -286,45 +319,51 @@ impl Cpu {
log::debug!("Setting CPU {} to default clockspeed", self.index); log::debug!("Setting CPU {} to default clockspeed", self.index);
// max clock // max clock
let payload_max = format!("p {} 1 {}\n", self.index / 2, self.limits.clock_max.max); let payload_max = format!("p {} 1 {}\n", self.index / 2, self.limits.clock_max.max);
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max).map_err( usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max)
|e| SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
&payload_max, CPU_CLOCK_LIMITS_PATH, e &payload_max, CPU_CLOCK_LIMITS_PATH, e
), ),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
}, })
).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
// min clock // min clock
let payload_min = format!("p {} 0 {}\n", self.index / 2, self.limits.clock_min.min); let payload_min = format!("p {} 0 {}\n", self.index / 2, self.limits.clock_min.min);
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min).map_err( usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min)
|e| SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
&payload_min, CPU_CLOCK_LIMITS_PATH, e &payload_min, CPU_CLOCK_LIMITS_PATH, e
), ),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
}, })
).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n") usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else(
.unwrap_or_else(|e| { |e| {
errors.push(SettingError { errors.push(SettingError {
msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e), msg: format!(
"Failed to write `c` to `{}`: {}",
CPU_CLOCK_LIMITS_PATH, e
),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
}); });
}); },
);
} }
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(false, self.index); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(false, self.index);
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level().unwrap_or_else(|mut e| errors.append(&mut e)); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT
.enforce_level()
.unwrap_or_else(|mut e| errors.append(&mut e));
} }
// commit changes (if no errors have already occured) // commit changes (if no errors have already occured)
if errors.is_empty() { if errors.is_empty() {
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| {
vec![SettingError { vec![SettingError {
msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e), msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
}] }]
}) })
} else { } else {
Err(errors) Err(errors)
} }
@ -333,14 +372,15 @@ impl Cpu {
fn set_all(&mut self) -> Result<(), Vec<SettingError>> { fn set_all(&mut self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new(); let mut errors = Vec::new();
// set cpu online/offline // set cpu online/offline
if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled if self.index != 0 && self.state.do_set_online {
// cpu0 cannot be disabled
let online_path = cpu_online_path(self.index); let online_path = cpu_online_path(self.index);
usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| { usdpl_back::api::files::write_single(&online_path, self.online as u8)
SettingError { .map_err(|e| SettingError {
msg: format!("Failed to write to `{}`: {}", &online_path, e), msg: format!("Failed to write to `{}`: {}", &online_path, e),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
} }
self.set_force_performance_related() self.set_force_performance_related()
@ -349,15 +389,15 @@ impl Cpu {
// set governor // set governor
if self.index == 0 || self.online { if self.index == 0 || self.online {
let governor_path = cpu_governor_path(self.index); let governor_path = cpu_governor_path(self.index);
usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| { usdpl_back::api::files::write_single(&governor_path, &self.governor)
SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
&self.governor, &governor_path, e &self.governor, &governor_path, e
), ),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
} }
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
@ -368,8 +408,12 @@ impl Cpu {
fn clamp_all(&mut self) { fn clamp_all(&mut self) {
if let Some(clock_limits) = &mut self.clock_limits { if let Some(clock_limits) = &mut self.clock_limits {
clock_limits.min = clock_limits.min.clamp(self.limits.clock_min.min, self.limits.clock_min.max); clock_limits.min = clock_limits
clock_limits.max = clock_limits.max.clamp(self.limits.clock_max.min, self.limits.clock_max.max); .min
.clamp(self.limits.clock_min.min, self.limits.clock_min.max);
clock_limits.max = clock_limits
.max
.clamp(self.limits.clock_max.min, self.limits.clock_max.max);
} }
} }
@ -400,11 +444,11 @@ impl Cpu {
crate::api::CpuLimits { crate::api::CpuLimits {
clock_min_limits: Some(RangeLimit { clock_min_limits: Some(RangeLimit {
min: self.limits.clock_max.min, // allows min to be set by max (it's weird, blame the kernel) min: self.limits.clock_max.min, // allows min to be set by max (it's weird, blame the kernel)
max: self.limits.clock_min.max max: self.limits.clock_min.max,
}), }),
clock_max_limits: Some(RangeLimit { clock_max_limits: Some(RangeLimit {
min: self.limits.clock_max.min, min: self.limits.clock_max.min,
max: self.limits.clock_max.max max: self.limits.clock_max.max,
}), }),
clock_step: self.limits.clock_step, clock_step: self.limits.clock_step,
governors: self.governors(), governors: self.governors(),
@ -413,13 +457,14 @@ impl Cpu {
fn governors(&self) -> Vec<String> { fn governors(&self) -> Vec<String> {
// NOTE: this eats errors // NOTE: this eats errors
let gov_str: String = match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) { let gov_str: String =
Ok(s) => s, match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) {
Err(e) => { Ok(s) => s,
log::warn!("Error getting available CPU governors: {}", e); Err(e) => {
return vec![]; log::warn!("Error getting available CPU governors: {}", e);
} return vec![];
}; }
};
gov_str.split(' ').map(|s| s.to_owned()).collect() gov_str.split(' ').map(|s| s.to_owned()).collect()
} }
} }
@ -485,7 +530,6 @@ fn cpu_governor_path(index: usize) -> String {
) )
} }
#[inline] #[inline]
fn cpu_available_governors_path(index: usize) -> String { fn cpu_available_governors_path(index: usize) -> String {
format!( format!(

View file

@ -1,12 +1,12 @@
use std::convert::Into; use std::convert::Into;
use crate::api::RangeLimit; use super::oc_limits::{GpuLimits, OverclockLimits};
use crate::settings::{MinMax, min_max_from_json};
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::TGpu;
use crate::persist::GpuJson;
use super::oc_limits::{OverclockLimits, GpuLimits};
use super::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT; use super::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT;
use crate::api::RangeLimit;
use crate::persist::GpuJson;
use crate::settings::TGpu;
use crate::settings::{min_max_from_json, MinMax};
use crate::settings::{OnResume, OnSet, SettingError};
const SLOW_PPT: u8 = 1; const SLOW_PPT: u8 = 1;
const FAST_PPT: u8 = 2; const FAST_PPT: u8 = 2;
@ -30,7 +30,11 @@ impl Gpu {
#[inline] #[inline]
pub fn from_json(other: GpuJson, version: u64) -> Self { pub fn from_json(other: GpuJson, version: u64) -> Self {
let (oc_limits, is_default) = OverclockLimits::load_or_default(); let (oc_limits, is_default) = OverclockLimits::load_or_default();
let driver = if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }; let driver = if is_default {
crate::persist::DriverJson::SteamDeck
} else {
crate::persist::DriverJson::SteamDeckAdvance
};
match version { match version {
0 => Self { 0 => Self {
fast_ppt: other.fast_ppt, fast_ppt: other.fast_ppt,
@ -62,70 +66,80 @@ impl Gpu {
self.state.clock_limits_set = true; self.state.clock_limits_set = true;
// max clock // max clock
let payload_max = format!("s 1 {}\n", clock_limits.max); let payload_max = format!("s 1 {}\n", clock_limits.max);
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max).map_err( usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max)
|e| SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
&payload_max, GPU_CLOCK_LIMITS_PATH, e &payload_max, GPU_CLOCK_LIMITS_PATH, e
), ),
setting: crate::settings::SettingVariant::Gpu, setting: crate::settings::SettingVariant::Gpu,
}, })
).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
// min clock // min clock
let payload_min = format!("s 0 {}\n", clock_limits.min); let payload_min = format!("s 0 {}\n", clock_limits.min);
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min).map_err( usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min)
|e| SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
&payload_min, GPU_CLOCK_LIMITS_PATH, e &payload_min, GPU_CLOCK_LIMITS_PATH, e
), ),
setting: crate::settings::SettingVariant::Gpu, setting: crate::settings::SettingVariant::Gpu,
},
).unwrap_or_else(|e| errors.push(e));
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else(|e| {
errors.push(SettingError {
msg: format!("Failed to write `c` to `{}`: {}", GPU_CLOCK_LIMITS_PATH, e),
setting: crate::settings::SettingVariant::Gpu,
}) })
}); .unwrap_or_else(|e| errors.push(e));
} else if self.state.clock_limits_set || usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else(
(self.state.is_resuming && !self.limits.skip_resume_reclock) |e| {
|| POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { errors.push(SettingError {
msg: format!("Failed to write `c` to `{}`: {}", GPU_CLOCK_LIMITS_PATH, e),
setting: crate::settings::SettingVariant::Gpu,
})
},
);
} else if self.state.clock_limits_set
|| (self.state.is_resuming && !self.limits.skip_resume_reclock)
|| POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual()
{
self.state.clock_limits_set = false; self.state.clock_limits_set = false;
if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?; POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?;
// disable manual clock limits // disable manual clock limits
// max clock // max clock
let payload_max = format!("s 1 {}\n", self.limits.clock_max.max); let payload_max = format!("s 1 {}\n", self.limits.clock_max.max);
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max).map_err( usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max)
|e| SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
&payload_max, GPU_CLOCK_LIMITS_PATH, e &payload_max, GPU_CLOCK_LIMITS_PATH, e
), ),
setting: crate::settings::SettingVariant::Gpu, setting: crate::settings::SettingVariant::Gpu,
}, })
).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
// min clock // min clock
let payload_min = format!("s 0 {}\n", self.limits.clock_min.min); let payload_min = format!("s 0 {}\n", self.limits.clock_min.min);
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min).map_err( usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min)
|e| SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
&payload_min, GPU_CLOCK_LIMITS_PATH, e &payload_min, GPU_CLOCK_LIMITS_PATH, e
), ),
setting: crate::settings::SettingVariant::Gpu, setting: crate::settings::SettingVariant::Gpu,
},
).unwrap_or_else(|e| errors.push(e));
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else(|e| {
errors.push(SettingError {
msg: format!("Failed to write `c` to `{}`: {}", GPU_CLOCK_LIMITS_PATH, e),
setting: crate::settings::SettingVariant::Gpu,
}) })
}); .unwrap_or_else(|e| errors.push(e));
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else(
|e| {
errors.push(SettingError {
msg: format!(
"Failed to write `c` to `{}`: {}",
GPU_CLOCK_LIMITS_PATH, e
),
setting: crate::settings::SettingVariant::Gpu,
})
},
);
} }
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.slow_memory); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.slow_memory);
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level().unwrap_or_else(|mut e| errors.append(&mut e)); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT
.enforce_level()
.unwrap_or_else(|mut e| errors.append(&mut e));
} }
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
@ -139,24 +153,28 @@ impl Gpu {
// enable/disable downclock of GPU memory (to 400Mhz?) // enable/disable downclock of GPU memory (to 400Mhz?)
if self.slow_memory { if self.slow_memory {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(true); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(true);
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level().unwrap_or_else(|mut e| errors.append(&mut e)); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT
.enforce_level()
.unwrap_or_else(|mut e| errors.append(&mut e));
usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8) usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8)
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
errors.push(SettingError { errors.push(SettingError {
msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e), msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e),
setting: crate::settings::SettingVariant::Gpu, setting: crate::settings::SettingVariant::Gpu,
});
}); });
});
} else if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { } else if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() {
usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8) usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8)
.unwrap_or_else(|e| { .unwrap_or_else(|e| {
errors.push(SettingError { errors.push(SettingError {
msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e), msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e),
setting: crate::settings::SettingVariant::Gpu, setting: crate::settings::SettingVariant::Gpu,
});
}); });
});
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.clock_limits.is_some()); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.clock_limits.is_some());
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level().unwrap_or_else(|mut e| errors.append(&mut e)); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT
.enforce_level()
.unwrap_or_else(|mut e| errors.append(&mut e));
} }
self.set_clocks() self.set_clocks()
.unwrap_or_else(|mut e| errors.append(&mut e)); .unwrap_or_else(|mut e| errors.append(&mut e));
@ -182,28 +200,32 @@ impl Gpu {
// set fast PPT // set fast PPT
if let Some(fast_ppt) = &self.fast_ppt { if let Some(fast_ppt) = &self.fast_ppt {
let fast_ppt_path = gpu_power_path(FAST_PPT); let fast_ppt_path = gpu_power_path(FAST_PPT);
usdpl_back::api::files::write_single(&fast_ppt_path, fast_ppt).map_err(|e| { usdpl_back::api::files::write_single(&fast_ppt_path, fast_ppt)
SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
fast_ppt, &fast_ppt_path, e fast_ppt, &fast_ppt_path, e
), ),
setting: crate::settings::SettingVariant::Gpu, setting: crate::settings::SettingVariant::Gpu,
} })
}).unwrap_or_else(|e| {errors.push(e);}); .unwrap_or_else(|e| {
errors.push(e);
});
} }
// set slow PPT // set slow PPT
if let Some(slow_ppt) = &self.slow_ppt { if let Some(slow_ppt) = &self.slow_ppt {
let slow_ppt_path = gpu_power_path(SLOW_PPT); let slow_ppt_path = gpu_power_path(SLOW_PPT);
usdpl_back::api::files::write_single(&slow_ppt_path, slow_ppt).map_err(|e| { usdpl_back::api::files::write_single(&slow_ppt_path, slow_ppt)
SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
slow_ppt, &slow_ppt_path, e slow_ppt, &slow_ppt_path, e
), ),
setting: crate::settings::SettingVariant::Gpu, setting: crate::settings::SettingVariant::Gpu,
} })
}).unwrap_or_else(|e| {errors.push(e);}); .unwrap_or_else(|e| {
errors.push(e);
});
} }
self.set_force_performance_related() self.set_force_performance_related()
.unwrap_or_else(|mut e| errors.append(&mut e)); .unwrap_or_else(|mut e| errors.append(&mut e));
@ -216,20 +238,18 @@ impl Gpu {
fn clamp_all(&mut self) { fn clamp_all(&mut self) {
if let Some(fast_ppt) = &mut self.fast_ppt { if let Some(fast_ppt) = &mut self.fast_ppt {
*fast_ppt = (*fast_ppt).clamp( *fast_ppt = (*fast_ppt).clamp(self.limits.fast_ppt.min, self.limits.fast_ppt.max);
self.limits.fast_ppt.min,
self.limits.fast_ppt.max,
);
} }
if let Some(slow_ppt) = &mut self.slow_ppt { if let Some(slow_ppt) = &mut self.slow_ppt {
*slow_ppt = (*slow_ppt).clamp( *slow_ppt = (*slow_ppt).clamp(self.limits.slow_ppt.min, self.limits.slow_ppt.max);
self.limits.slow_ppt.min,
self.limits.slow_ppt.max,
);
} }
if let Some(clock_limits) = &mut self.clock_limits { if let Some(clock_limits) = &mut self.clock_limits {
clock_limits.min = clock_limits.min.clamp(self.limits.clock_min.min, self.limits.clock_min.max); clock_limits.min = clock_limits
clock_limits.max = clock_limits.max.clamp(self.limits.clock_max.min, self.limits.clock_max.max); .min
.clamp(self.limits.clock_min.min, self.limits.clock_min.max);
clock_limits.max = clock_limits
.max
.clamp(self.limits.clock_max.min, self.limits.clock_max.max);
} }
} }
@ -242,7 +262,11 @@ impl Gpu {
slow_memory: false, slow_memory: false,
limits: oc_limits.gpu, limits: oc_limits.gpu,
state: crate::state::steam_deck::Gpu::default(), state: crate::state::steam_deck::Gpu::default(),
driver_mode: if is_default { crate::persist::DriverJson::SteamDeck } else { crate::persist::DriverJson::SteamDeckAdvance }, driver_mode: if is_default {
crate::persist::DriverJson::SteamDeck
} else {
crate::persist::DriverJson::SteamDeckAdvance
},
} }
} }
} }
@ -314,7 +338,10 @@ impl TGpu for Gpu {
} }
fn get_ppt(&self) -> (Option<u64>, Option<u64>) { fn get_ppt(&self) -> (Option<u64>, Option<u64>) {
(self.fast_ppt.map(|x| x / self.limits.ppt_divisor), self.slow_ppt.map(|x| x / self.limits.ppt_divisor)) (
self.fast_ppt.map(|x| x / self.limits.ppt_divisor),
self.slow_ppt.map(|x| x / self.limits.ppt_divisor),
)
} }
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) { fn clock_limits(&mut self, limits: Option<MinMax<u64>>) {

View file

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::settings::MinMax; use crate::settings::MinMax;
use serde::{Deserialize, Serialize};
const OC_LIMITS_FILEPATH: &str = "pt_oc.json"; const OC_LIMITS_FILEPATH: &str = "pt_oc.json";
@ -29,22 +29,36 @@ impl OverclockLimits {
let mut file = match std::fs::File::open(&path) { let mut file = match std::fs::File::open(&path) {
Ok(f) => f, Ok(f) => f,
Err(e) => { Err(e) => {
log::warn!("Steam Deck limits file {} err: {} (using default fallback)", path.display(), e); log::warn!(
"Steam Deck limits file {} err: {} (using default fallback)",
path.display(),
e
);
return (Self::default(), true); return (Self::default(), true);
}, }
}; };
match serde_json::from_reader(&mut file) { match serde_json::from_reader(&mut file) {
Ok(result) => { Ok(result) => {
log::debug!("Steam Deck limits file {} successfully loaded", path.display()); log::debug!(
"Steam Deck limits file {} successfully loaded",
path.display()
);
(result, false) (result, false)
}, }
Err(e) => { Err(e) => {
log::warn!("Steam Deck limits file {} json err: {} (using default fallback)", path.display(), e); log::warn!(
"Steam Deck limits file {} json err: {} (using default fallback)",
path.display(),
e
);
(Self::default(), true) (Self::default(), true)
} }
} }
} else { } else {
log::info!("Steam Deck limits file {} not found (using default fallback)", path.display()); log::info!(
"Steam Deck limits file {} not found (using default fallback)",
path.display()
);
(Self::default(), true) (Self::default(), true)
} }
} }
@ -58,7 +72,10 @@ pub(super) struct BatteryLimits {
impl Default for BatteryLimits { impl Default for BatteryLimits {
fn default() -> Self { fn default() -> Self {
Self { Self {
charge_rate: MinMax { min: 250, max: 2500 }, charge_rate: MinMax {
min: 250,
max: 2500,
},
} }
} }
} }
@ -89,8 +106,14 @@ pub(super) struct CpuLimits {
impl Default for CpuLimits { impl Default for CpuLimits {
fn default() -> Self { fn default() -> Self {
Self { Self {
clock_min: MinMax { min: 1400, max: 3500 }, clock_min: MinMax {
clock_max: MinMax { min: 400, max: 3500 }, min: 1400,
max: 3500,
},
clock_max: MinMax {
min: 400,
max: 3500,
},
clock_step: 100, clock_step: 100,
skip_resume_reclock: false, skip_resume_reclock: false,
} }
@ -112,12 +135,24 @@ pub(super) struct GpuLimits {
impl Default for GpuLimits { impl Default for GpuLimits {
fn default() -> Self { fn default() -> Self {
Self { Self {
fast_ppt: MinMax { min: 1000000, max: 30_000_000 }, fast_ppt: MinMax {
slow_ppt: MinMax { min: 1000000, max: 29_000_000 }, min: 1000000,
max: 30_000_000,
},
slow_ppt: MinMax {
min: 1000000,
max: 29_000_000,
},
ppt_divisor: 1_000_000, ppt_divisor: 1_000_000,
ppt_step: 1, ppt_step: 1,
clock_min: MinMax { min: 400, max: 1600 }, clock_min: MinMax {
clock_max: MinMax { min: 400, max: 1600 }, min: 400,
max: 1600,
},
clock_max: MinMax {
min: 400,
max: 1600,
},
clock_step: 100, clock_step: 100,
skip_resume_reclock: false, skip_resume_reclock: false,
} }

View file

@ -10,7 +10,8 @@ use crate::settings::SettingError;
const DEFAULT_BITS: u64 = 0; const DEFAULT_BITS: u64 = 0;
/// Global usage tracker for the sysfs file by the same name /// Global usage tracker for the sysfs file by the same name
pub static POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT: PDFPLManager = PDFPLManager(AtomicU64::new(DEFAULT_BITS)); pub static POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT: PDFPLManager =
PDFPLManager(AtomicU64::new(DEFAULT_BITS));
pub struct PDFPLManager(AtomicU64); pub struct PDFPLManager(AtomicU64);
@ -58,41 +59,45 @@ impl PDFPLManager {
pub fn enforce_level(&self) -> Result<(), Vec<SettingError>> { pub fn enforce_level(&self) -> Result<(), Vec<SettingError>> {
let needs = self.needs_manual(); let needs = self.needs_manual();
let mut errors = Vec::new(); let mut errors = Vec::new();
let mode: String = usdpl_back::api::files::read_single(DPM_FORCE_LIMITS_PATH.to_owned()).map_err(|e| { let mode: String = usdpl_back::api::files::read_single(DPM_FORCE_LIMITS_PATH.to_owned())
vec![SettingError { .map_err(|e| {
msg: format!( vec![SettingError {
"Failed to read `{}`: {}", msg: format!("Failed to read `{}`: {}", DPM_FORCE_LIMITS_PATH, e),
DPM_FORCE_LIMITS_PATH, e setting: crate::settings::SettingVariant::General,
), }]
setting: crate::settings::SettingVariant::General, })?;
}]
})?;
if mode != "manual" && needs { if mode != "manual" && needs {
log::info!("Setting `{}` to manual", DPM_FORCE_LIMITS_PATH); log::info!("Setting `{}` to manual", DPM_FORCE_LIMITS_PATH);
// set manual control // set manual control
usdpl_back::api::files::write_single(DPM_FORCE_LIMITS_PATH, "manual").map_err(|e| { usdpl_back::api::files::write_single(DPM_FORCE_LIMITS_PATH, "manual")
errors.push(SettingError { .map_err(|e| {
msg: format!( errors.push(SettingError {
"Failed to write `manual` to `{}`: {}", msg: format!(
DPM_FORCE_LIMITS_PATH, e "Failed to write `manual` to `{}`: {}",
), DPM_FORCE_LIMITS_PATH, e
setting: crate::settings::SettingVariant::General, ),
setting: crate::settings::SettingVariant::General,
})
}) })
}).unwrap_or(()); .unwrap_or(());
} else if mode != "auto" && !needs { } else if mode != "auto" && !needs {
log::info!("Setting `{}` to auto", DPM_FORCE_LIMITS_PATH); log::info!("Setting `{}` to auto", DPM_FORCE_LIMITS_PATH);
// unset manual control // unset manual control
usdpl_back::api::files::write_single(DPM_FORCE_LIMITS_PATH, "auto").map_err(|e| { usdpl_back::api::files::write_single(DPM_FORCE_LIMITS_PATH, "auto")
errors.push(SettingError { .map_err(|e| {
msg: format!( errors.push(SettingError {
"Failed to write `auto` to `{}`: {}", msg: format!(
DPM_FORCE_LIMITS_PATH, e "Failed to write `auto` to `{}`: {}",
), DPM_FORCE_LIMITS_PATH, e
setting: crate::settings::SettingVariant::General, ),
setting: crate::settings::SettingVariant::General,
})
}) })
}).unwrap_or(()); .unwrap_or(());
} }
if let Ok(mode_now) = usdpl_back::api::files::read_single::<_, String, _>(DPM_FORCE_LIMITS_PATH.to_owned()) { if let Ok(mode_now) =
usdpl_back::api::files::read_single::<_, String, _>(DPM_FORCE_LIMITS_PATH.to_owned())
{
log::debug!("Mode for `{}` is now `{}`", DPM_FORCE_LIMITS_PATH, mode_now); log::debug!("Mode for `{}` is now `{}`", DPM_FORCE_LIMITS_PATH, mode_now);
} else { } else {
log::debug!("Error getting new mode for debugging purposes"); log::debug!("Error getting new mode for debugging purposes");

View file

@ -6,7 +6,7 @@
#![allow(dead_code)] #![allow(dead_code)]
use std::fs::OpenOptions; use std::fs::OpenOptions;
use std::io::{Error, Seek, SeekFrom, Read, Write}; use std::io::{Error, Read, Seek, SeekFrom, Write};
#[inline] #[inline]
fn write2(p0: u8, p1: u8) -> Result<usize, Error> { fn write2(p0: u8, p1: u8) -> Result<usize, Error> {
@ -27,17 +27,13 @@ fn write_read(p0: u8) -> Result<u8, Error> {
} }
fn write_to(location: u64, value: u8) -> Result<usize, Error> { fn write_to(location: u64, value: u8) -> Result<usize, Error> {
let mut file = OpenOptions::new() let mut file = OpenOptions::new().write(true).open("/dev/port")?;
.write(true)
.open("/dev/port")?;
file.seek(SeekFrom::Start(location))?; file.seek(SeekFrom::Start(location))?;
file.write(&[value]) file.write(&[value])
} }
fn read_from(location: u64) -> Result<u8, Error> { fn read_from(location: u64) -> Result<u8, Error> {
let mut file = OpenOptions::new() let mut file = OpenOptions::new().read(true).open("/dev/port")?;
.read(true)
.open("/dev/port")?;
file.seek(SeekFrom::Start(location))?; file.seek(SeekFrom::Start(location))?;
let mut buffer = [0]; let mut buffer = [0];
file.read(&mut buffer)?; file.read(&mut buffer)?;
@ -61,21 +57,26 @@ fn wait_ready_for_read() -> Result<(), Error> {
} }
pub fn set_led(red_unused: bool, green_aka_white: bool, blue_unused: bool) -> Result<usize, Error> { pub fn set_led(red_unused: bool, green_aka_white: bool, blue_unused: bool) -> Result<usize, Error> {
let payload: u8 = 0x80 | (red_unused as u8 & 1) | ((green_aka_white as u8 & 1) << 1) | ((blue_unused as u8 & 1) << 2); let payload: u8 = 0x80
| (red_unused as u8 & 1)
| ((green_aka_white as u8 & 1) << 1)
| ((blue_unused as u8 & 1) << 2);
//log::info!("Payload: {:b}", payload); //log::info!("Payload: {:b}", payload);
write2(Setting::LEDStatus as _, payload) write2(Setting::LEDStatus as _, payload)
} }
const THINGS: &[u8] = &[ const THINGS: &[u8] = &[
1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0,
1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1,
1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0,
0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
]; ];
const TIME_UNIT: std::time::Duration = std::time::Duration::from_millis(200); const TIME_UNIT: std::time::Duration = std::time::Duration::from_millis(200);
pub fn flash_led() { pub fn flash_led() {
let old_led_state = write_read(Setting::LEDStatus as _).map_err(|e| log::error!("Failed to read LED status: {}", e)); let old_led_state = write_read(Setting::LEDStatus as _)
.map_err(|e| log::error!("Failed to read LED status: {}", e));
for &code in THINGS { for &code in THINGS {
let on = code != 0; let on = code != 0;
if let Err(e) = set_led(on, on, false) { if let Err(e) = set_led(on, on, false) {
@ -85,7 +86,9 @@ pub fn flash_led() {
} }
if let Ok(old_led_state) = old_led_state { if let Ok(old_led_state) = old_led_state {
log::debug!("Restoring LED state to {:#02b}", old_led_state); log::debug!("Restoring LED state to {:#02b}", old_led_state);
write2(Setting::LEDStatus as _, old_led_state).map_err(|e| log::error!("Failed to restore LED status: {}", e)).unwrap(); write2(Setting::LEDStatus as _, old_led_state)
.map_err(|e| log::error!("Failed to restore LED status: {}", e))
.unwrap();
} }
} }

View file

@ -1,6 +1,6 @@
use std::fmt::Debug;
use super::SettingError;
use super::MinMax; use super::MinMax;
use super::SettingError;
use std::fmt::Debug;
pub trait OnSet { pub trait OnSet {
fn on_set(&mut self) -> Result<(), Vec<SettingError>>; fn on_set(&mut self) -> Result<(), Vec<SettingError>>;
@ -14,7 +14,7 @@ pub trait OnResume {
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub enum PowerMode { pub enum PowerMode {
PluggedIn, PluggedIn,
PluggedOut, // unplugged PluggedOut, // unplugged
BatteryCharge(f64), // battery fill amount: 0 = empty, 1 = full BatteryCharge(f64), // battery fill amount: 0 = empty, 1 = full
} }
@ -135,7 +135,7 @@ pub trait TBattery: OnSet + OnResume + OnPowerEvent + Debug + Send {
log::warn!("Power event check using default trait implementation"); log::warn!("Power event check using default trait implementation");
let mut events = Vec::new(); let mut events = Vec::new();
if let (Some(full), Some(now)) = (self.read_charge_full(), self.read_charge_now()) { if let (Some(full), Some(now)) = (self.read_charge_full(), self.read_charge_now()) {
events.push(PowerMode::BatteryCharge(now/full)); events.push(PowerMode::BatteryCharge(now / full));
} }
Ok(events) Ok(events)
} }

View file

@ -1,8 +1,8 @@
use std::convert::Into; use std::convert::Into;
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::TBattery;
use crate::persist::BatteryJson; use crate::persist::BatteryJson;
use crate::settings::TBattery;
use crate::settings::{OnResume, OnSet, SettingError};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Battery; pub struct Battery;
@ -47,31 +47,39 @@ impl TBattery for Battery {
self.clone().into() self.clone().into()
} }
fn charge_rate(&mut self, _rate: Option<u64>) { fn charge_rate(&mut self, _rate: Option<u64>) {}
}
fn get_charge_rate(&self) -> Option<u64> { fn get_charge_rate(&self) -> Option<u64> {
None None
} }
fn charge_mode(&mut self, _rate: Option<String>) { fn charge_mode(&mut self, _rate: Option<String>) {}
}
fn get_charge_mode(&self) -> Option<String> { fn get_charge_mode(&self) -> Option<String> {
None None
} }
fn read_charge_full(&self) -> Option<f64> { None } fn read_charge_full(&self) -> Option<f64> {
None
}
fn read_charge_now(&self) -> Option<f64> { None } fn read_charge_now(&self) -> Option<f64> {
None
}
fn read_charge_design(&self) -> Option<f64> { None } fn read_charge_design(&self) -> Option<f64> {
None
}
fn read_current_now(&self) -> Option<f64> { None } fn read_current_now(&self) -> Option<f64> {
None
}
fn charge_limit(&mut self, _limit: Option<f64>) {} fn charge_limit(&mut self, _limit: Option<f64>) {}
fn get_charge_limit(&self) -> Option<f64> { None } fn get_charge_limit(&self) -> Option<f64> {
None
}
fn provider(&self) -> crate::persist::DriverJson { fn provider(&self) -> crate::persist::DriverJson {
crate::persist::DriverJson::Unknown crate::persist::DriverJson::Unknown

View file

@ -1,9 +1,9 @@
use std::convert::Into; use std::convert::Into;
use crate::persist::CpuJson;
use crate::settings::MinMax; use crate::settings::MinMax;
use crate::settings::{OnResume, OnSet, SettingError}; use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::{TCpus, TCpu}; use crate::settings::{TCpu, TCpus};
use crate::persist::CpuJson;
const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present";
const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control";
@ -21,25 +21,23 @@ impl OnSet for Cpus {
if self.smt_capable { if self.smt_capable {
// toggle SMT // toggle SMT
if self.smt { if self.smt {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "on").map_err(|e| { usdpl_back::api::files::write_single(CPU_SMT_PATH, "on")
SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!("Failed to write `on` to `{}`: {}", CPU_SMT_PATH, e),
"Failed to write `on` to `{}`: {}",
CPU_SMT_PATH, e
),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| {errors.push(e);}); .unwrap_or_else(|e| {
errors.push(e);
});
} else { } else {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| { usdpl_back::api::files::write_single(CPU_SMT_PATH, "off")
SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!("Failed to write `off` to `{}`: {}", CPU_SMT_PATH, e),
"Failed to write `off` to `{}`: {}",
CPU_SMT_PATH, e
),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| {errors.push(e);}); .unwrap_or_else(|e| {
errors.push(e);
});
} }
} }
for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() { for (i, cpu) in self.cpus.as_mut_slice().iter_mut().enumerate() {
@ -58,7 +56,8 @@ impl OnResume for Cpus {
fn on_resume(&self) -> Result<(), Vec<SettingError>> { fn on_resume(&self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new(); let mut errors = Vec::new();
for cpu in &self.cpus { for cpu in &self.cpus {
cpu.on_resume().unwrap_or_else(|mut e| errors.append(&mut e)); cpu.on_resume()
.unwrap_or_else(|mut e| errors.append(&mut e));
} }
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
@ -87,7 +86,7 @@ impl Cpus {
fn system_smt_capabilities() -> (bool, bool) { fn system_smt_capabilities() -> (bool, bool) {
match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) { match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) {
Ok(val) => (val.trim().to_lowercase() == "on", true), Ok(val) => (val.trim().to_lowercase() == "on", true),
Err(_) => (false, false) Err(_) => (false, false),
} }
} }
@ -183,7 +182,6 @@ pub struct Cpu {
state: crate::state::steam_deck::Cpu, state: crate::state::steam_deck::Cpu,
} }
impl Cpu { impl Cpu {
#[inline] #[inline]
pub fn from_json(other: CpuJson, version: u64, i: usize) -> Self { pub fn from_json(other: CpuJson, version: u64, i: usize) -> Self {
@ -206,28 +204,29 @@ impl Cpu {
fn set_all(&mut self) -> Result<(), Vec<SettingError>> { fn set_all(&mut self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new(); let mut errors = Vec::new();
// set cpu online/offline // set cpu online/offline
if self.index != 0 && self.state.do_set_online { // cpu0 cannot be disabled if self.index != 0 && self.state.do_set_online {
// cpu0 cannot be disabled
let online_path = cpu_online_path(self.index); let online_path = cpu_online_path(self.index);
usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| { usdpl_back::api::files::write_single(&online_path, self.online as u8)
SettingError { .map_err(|e| SettingError {
msg: format!("Failed to write to `{}`: {}", &online_path, e), msg: format!("Failed to write to `{}`: {}", &online_path, e),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
} }
// set governor // set governor
if self.index == 0 || self.online { if self.index == 0 || self.online {
let governor_path = cpu_governor_path(self.index); let governor_path = cpu_governor_path(self.index);
usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| { usdpl_back::api::files::write_single(&governor_path, &self.governor)
SettingError { .map_err(|e| SettingError {
msg: format!( msg: format!(
"Failed to write `{}` to `{}`: {}", "Failed to write `{}` to `{}`: {}",
&self.governor, &governor_path, e &self.governor, &governor_path, e
), ),
setting: crate::settings::SettingVariant::Cpu, setting: crate::settings::SettingVariant::Cpu,
} })
}).unwrap_or_else(|e| errors.push(e)); .unwrap_or_else(|e| errors.push(e));
} }
if errors.is_empty() { if errors.is_empty() {
Ok(()) Ok(())
@ -238,7 +237,8 @@ impl Cpu {
fn from_sys(cpu_index: usize) -> Self { fn from_sys(cpu_index: usize) -> Self {
Self { Self {
online: usdpl_back::api::files::read_single(cpu_online_path(cpu_index)).unwrap_or(1u8) != 0, online: usdpl_back::api::files::read_single(cpu_online_path(cpu_index)).unwrap_or(1u8)
!= 0,
governor: usdpl_back::api::files::read_single(cpu_governor_path(cpu_index)) governor: usdpl_back::api::files::read_single(cpu_governor_path(cpu_index))
.unwrap_or("schedutil".to_owned()), .unwrap_or("schedutil".to_owned()),
index: cpu_index, index: cpu_index,
@ -295,8 +295,7 @@ impl TCpu for Cpu {
&self.governor &self.governor
} }
fn clock_limits(&mut self, _limits: Option<MinMax<u64>>) { fn clock_limits(&mut self, _limits: Option<MinMax<u64>>) {}
}
fn get_clock_limits(&self) -> Option<&MinMax<u64>> { fn get_clock_limits(&self) -> Option<&MinMax<u64>> {
None None

View file

@ -1,9 +1,9 @@
use std::convert::Into; use std::convert::Into;
use crate::settings::MinMax;
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::TGpu;
use crate::persist::GpuJson; use crate::persist::GpuJson;
use crate::settings::MinMax;
use crate::settings::TGpu;
use crate::settings::{OnResume, OnSet, SettingError};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Gpu { pub struct Gpu {
@ -13,15 +13,11 @@ pub struct Gpu {
impl Gpu { impl Gpu {
#[inline] #[inline]
pub fn from_json(_other: GpuJson, _version: u64) -> Self { pub fn from_json(_other: GpuJson, _version: u64) -> Self {
Self { Self { slow_memory: false }
slow_memory: false,
}
} }
pub fn system_default() -> Self { pub fn system_default() -> Self {
Self { Self { slow_memory: false }
slow_memory: false,
}
} }
} }
@ -71,15 +67,13 @@ impl TGpu for Gpu {
self.clone().into() self.clone().into()
} }
fn ppt(&mut self, _fast: Option<u64>, _slow: Option<u64>) { fn ppt(&mut self, _fast: Option<u64>, _slow: Option<u64>) {}
}
fn get_ppt(&self) -> (Option<u64>, Option<u64>) { fn get_ppt(&self) -> (Option<u64>, Option<u64>) {
(None, None) (None, None)
} }
fn clock_limits(&mut self, _limits: Option<MinMax<u64>>) { fn clock_limits(&mut self, _limits: Option<MinMax<u64>>) {}
}
fn get_clock_limits(&self) -> Option<&MinMax<u64>> { fn get_clock_limits(&self) -> Option<&MinMax<u64>> {
None None

View file

@ -1,7 +1,7 @@
pub fn guess_smt(cpus: &Vec<crate::persist::CpuJson>) -> bool { pub fn guess_smt(cpus: &Vec<crate::persist::CpuJson>) -> bool {
let mut guess = true; let mut guess = true;
for i in (0..cpus.len()).step_by(2) { for i in (0..cpus.len()).step_by(2) {
guess &= cpus[i].online == cpus[i+1].online; guess &= cpus[i].online == cpus[i + 1].online;
} }
guess guess
} }

View file

@ -1,8 +1,8 @@
use std::fmt::Display; use std::fmt::Display;
//use std::sync::{LockResult, MutexGuard}; //use std::sync::{LockResult, MutexGuard};
//use std::fs::{Permissions, metadata}; //use std::fs::{Permissions, metadata};
use std::io::{Read, Write};
use std::os::unix::fs::PermissionsExt; use std::os::unix::fs::PermissionsExt;
use std::io::{Write, Read};
pub fn unwrap_maybe_fatal<T: Sized, E: Display>(result: Result<T, E>, message: &str) -> T { pub fn unwrap_maybe_fatal<T: Sized, E: Display>(result: Result<T, E>, message: &str) -> T {
match result { match result {
@ -36,21 +36,36 @@ pub fn settings_dir() -> std::path::PathBuf {
pub fn chown_settings_dir() -> std::io::Result<()> { pub fn chown_settings_dir() -> std::io::Result<()> {
let dir = settings_dir(); let dir = settings_dir();
#[cfg(feature = "decky")] #[cfg(feature = "decky")]
let deck_user = usdpl_back::api::decky::user().map_err(|_| std::io::Error::new(std::io::ErrorKind::NotFound, "Decky missing deck user's username"))?; let deck_user = usdpl_back::api::decky::user().map_err(|_| {
std::io::Error::new(
std::io::ErrorKind::NotFound,
"Decky missing deck user's username",
)
})?;
#[cfg(not(feature = "decky"))] #[cfg(not(feature = "decky"))]
let deck_user = "deck".to_owned(); let deck_user = "deck".to_owned();
// FIXME this shouldn't need to invoke a command // FIXME this shouldn't need to invoke a command
let output = std::process::Command::new("id") let output = std::process::Command::new("id")
.args(["-u", &deck_user]) .args(["-u", &deck_user])
.output()?; .output()?;
let uid: u32 = String::from_utf8_lossy(&output.stdout).parse().unwrap_or(1000); let uid: u32 = String::from_utf8_lossy(&output.stdout)
log::info!("chmod/chown ~/.config/powertools for user `{}` ({})", deck_user, uid); .parse()
.unwrap_or(1000);
log::info!(
"chmod/chown ~/.config/powertools for user `{}` ({})",
deck_user,
uid
);
let permissions = PermissionsExt::from_mode(0o755); let permissions = PermissionsExt::from_mode(0o755);
std::fs::set_permissions(&dir, permissions)?; std::fs::set_permissions(&dir, permissions)?;
// FIXME once merged into stable https://github.com/rust-lang/rust/issues/88989 // FIXME once merged into stable https://github.com/rust-lang/rust/issues/88989
//std::os::unix::fs::chown(&dir, Some(uid), Some(uid)) //std::os::unix::fs::chown(&dir, Some(uid), Some(uid))
std::process::Command::new("chown") std::process::Command::new("chown")
.args(["-R", &format!("{}:{}", deck_user, deck_user), &dir.to_str().unwrap_or(".")]) .args([
"-R",
&format!("{}:{}", deck_user, deck_user),
&dir.to_str().unwrap_or("."),
])
.output()?; .output()?;
Ok(()) Ok(())
} }
@ -61,8 +76,7 @@ fn version_filepath() -> std::path::PathBuf {
pub fn save_version_file() -> std::io::Result<usize> { pub fn save_version_file() -> std::io::Result<usize> {
let path = version_filepath(); let path = version_filepath();
std::fs::File::create(path)? std::fs::File::create(path)?.write(crate::consts::PACKAGE_VERSION.as_bytes())
.write(crate::consts::PACKAGE_VERSION.as_bytes())
} }
pub fn read_version_file() -> String { pub fn read_version_file() -> String {
@ -77,7 +91,7 @@ pub fn read_version_file() -> String {
crate::consts::PACKAGE_VERSION.to_owned() crate::consts::PACKAGE_VERSION.to_owned()
} }
} }
}, }
Err(e) => { Err(e) => {
log::warn!("Cannot read version file: {}", e); log::warn!("Cannot read version file: {}", e);
crate::consts::PACKAGE_VERSION.to_owned() crate::consts::PACKAGE_VERSION.to_owned()