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> {
#[inline]
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)]
pub struct GeneralLimits {
}
pub struct GeneralLimits {}
#[derive(Serialize, Deserialize)]
pub struct GpuLimits {

View file

@ -1,29 +1,33 @@
//use usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable;
pub struct AsyncIsh<In: Send + 'static,
pub struct AsyncIsh<
In: Send + 'static,
Out: Send + 'static,
TS: (Fn(super::ApiParameterType) -> Result<In, String>) + Send + Sync,
Gen: (Fn() -> SG) + Send + Sync,
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 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
}
#[async_trait::async_trait]
impl <In: Send + 'static,
Out: Send + 'static,
TS: (Fn(super::ApiParameterType) -> Result<In, String>) + Send + Sync,
Gen: (Fn() -> SG) + Send + Sync,
SG: (Fn(In) -> Out) + Send + Sync + 'static,
TG: (Fn(Out) -> super::ApiParameterType) + Send + Sync>
AsyncCallable for AsyncIsh<In, Out, TS, Gen, SG, TG> {
impl<
In: Send + 'static,
Out: Send + 'static,
TS: (Fn(super::ApiParameterType) -> Result<In, String>) + Send + Sync,
Gen: (Fn() -> SG) + Send + Sync,
SG: (Fn(In) -> Out) + Send + Sync + 'static,
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 {
let t_to_set = match (self.trans_setter)(params) {
Ok(t) => t,
Err(e) => return vec![e.into()]
Err(e) => return vec![e.into()],
};
let setter = (self.set_get)();
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,
G: (Fn() -> T) + Send + Sync + 'static,
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync> {
pub set_get: Gen, // probably has locks (i.e. slow)
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync,
> {
pub set_get: Gen, // probably has locks (i.e. slow)
pub trans_getter: TG, // assumed to be pretty fast
}
#[async_trait::async_trait]
impl <T: Send + 'static,
Gen: (Fn() -> G) + Send + Sync,
G: (Fn() -> T) + Send + Sync + 'static,
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync>
AsyncCallable for AsyncIshGetter<T, Gen, G, TG> {
impl<
T: Send + 'static,
Gen: (Fn() -> G) + Send + Sync,
G: (Fn() -> T) + Send + Sync + 'static,
TG: (Fn(T) -> super::ApiParameterType) + Send + Sync,
> AsyncCallable for AsyncIshGetter<T, Gen, G, TG>
{
async fn call(&self, _params: super::ApiParameterType) -> super::ApiParameterType {
let getter = (self.set_get)();
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]
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 {
(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 usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable;
@ -6,24 +6,27 @@ use usdpl_back::AsyncCallable;
use super::handler::{ApiMessage, BatteryMessage};
/// Current current (ha!) web method
pub fn current_now(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn current_now(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = 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");
let callback =
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")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |result| {
super::utility::map_optional_result(Ok(result))
}
trans_getter: |result| super::utility::map_optional_result(Ok(result)),
}
}
@ -33,68 +36,77 @@ pub fn current_now(
}*/
/// Charge now web method
pub fn charge_now(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn charge_now(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = 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");
let callback =
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")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |result| {
super::utility::map_optional_result(Ok(result))
}
trans_getter: |result| super::utility::map_optional_result(Ok(result)),
}
}
/// Charge full web method
pub fn charge_full(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn charge_full(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = 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");
let callback =
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")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |result| {
super::utility::map_optional_result(Ok(result))
}
trans_getter: |result| super::utility::map_optional_result(Ok(result)),
}
}
/// Charge design web method
pub fn charge_design(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn charge_design(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = 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");
let callback =
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")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |result| {
super::utility::map_optional_result(Ok(result))
}
trans_getter: |result| super::utility::map_optional_result(Ok(result)),
}
}
@ -103,11 +115,15 @@ pub fn set_charge_rate(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |rate: f64|
sender.lock()
let setter = move |rate: f64| {
sender
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::SetChargeRate(Some(rate as u64))))
.expect("set_charge_rate send failed");
.send(ApiMessage::Battery(BatteryMessage::SetChargeRate(Some(
rate as u64,
))))
.expect("set_charge_rate send failed")
};
move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(new_val)) = params_in.get(0) {
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 getter = move || {
let (tx, rx) = mpsc::channel();
let callback = 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");
let callback =
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")
};
move |_: super::ApiParameterType| {
vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)]
}
move |_: super::ApiParameterType| vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)]
}
/// Generate unset battery charge rate web method
@ -139,7 +160,13 @@ pub fn unset_charge_rate(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
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| {
setter();
vec![true.into()]
@ -151,11 +178,15 @@ pub fn set_charge_mode(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |mode: String|
sender.lock()
let setter = move |mode: String| {
sender
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::SetChargeMode(Some(mode))))
.expect("set_charge_mode send failed");
.send(ApiMessage::Battery(BatteryMessage::SetChargeMode(Some(
mode,
))))
.expect("set_charge_mode send failed")
};
move |params_in: super::ApiParameterType| {
if let Some(Primitive::String(new_val)) = params_in.get(0) {
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 getter = move || {
let (tx, rx) = mpsc::channel();
let callback = move |mode: Option<String>| 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");
let callback = move |mode: Option<String>| {
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")
};
move |_: super::ApiParameterType| {
vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)]
}
move |_: super::ApiParameterType| vec![getter().map(|x| x.into()).unwrap_or(Primitive::Empty)]
}
/// Generate unset battery charge mode web method
@ -187,7 +224,13 @@ pub fn unset_charge_mode(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
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| {
setter();
vec![true.into()]
@ -200,7 +243,11 @@ pub fn on_unplugged(
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
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()]
}
}
@ -211,7 +258,11 @@ pub fn on_plugged(
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
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()]
}
}
@ -221,11 +272,15 @@ pub fn set_charge_limit(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |limit: f64|
sender.lock()
let setter = move |limit: f64| {
sender
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::SetChargeLimit(Some(limit))))
.expect("set_charge_limit send failed");
.send(ApiMessage::Battery(BatteryMessage::SetChargeLimit(Some(
limit,
))))
.expect("set_charge_limit send failed")
};
move |params_in: super::ApiParameterType| {
if let Some(&Primitive::F64(new_val)) = params_in.get(0) {
setter(new_val);
@ -241,11 +296,13 @@ pub fn unset_charge_limit(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let unsetter = move ||
sender.lock()
let unsetter = move || {
sender
.lock()
.unwrap()
.send(ApiMessage::Battery(BatteryMessage::SetChargeLimit(None)))
.expect("unset_charge_limit send failed");
.expect("unset_charge_limit send failed")
};
move |_: super::ApiParameterType| {
unsetter();
vec![true.into()]
@ -253,23 +310,27 @@ pub fn unset_charge_limit(
}
/// Charge design web method
pub fn get_charge_limit(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn get_charge_limit(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = move |val: Option<f64>| 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");
let callback = move |val: Option<f64>| {
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")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |result| {
super::utility::map_optional_result(Ok(result))
}
trans_getter: |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 usdpl_back::core::serdes::Primitive;
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 super::handler::{ApiMessage, CpuMessage};
@ -12,13 +12,11 @@ pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType {
super::utility::map_result(
crate::settings::steam_deck::Cpus::cpu_count()
.map(|x| x as u64)
.ok_or_else(
|| SettingError {
msg: "Failed to parse CPU count".to_owned(),
setting: SettingVariant::Cpu,
}
)
)
.ok_or_else(|| SettingError {
msg: "Failed to parse CPU count".to_owned(),
setting: SettingVariant::Cpu,
}),
)
}
/// Generate set CPU online web method
@ -26,10 +24,13 @@ pub fn set_cpu_online(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, value: bool|
sender.lock()
let setter = move |index: usize, value: bool| {
sender
.lock()
.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| {
if let Some(&Primitive::F64(index)) = params_in.get(0) {
//let mut settings_lock = unwrap_lock(settings.lock(), "cpu");
@ -49,10 +50,13 @@ pub fn set_cpus_online(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |values: Vec<bool>|
sender.lock()
let setter = move |values: Vec<bool>| {
sender
.lock()
.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| {
let mut result = 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(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn set_smt(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move |smt: bool| {
let (tx, rx) = mpsc::channel();
let callback = 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");
let callback =
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")
}
};
@ -118,41 +125,48 @@ pub fn set_smt(
output.push(status.into());
}
output
}
},
}
}
pub fn get_smt(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn get_smt(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
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")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |result| {
vec![result.into()]
}
trans_getter: |result| vec![result.into()],
}
}
pub fn get_cpus_online(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn get_cpus_online(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<bool>| 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");
let callback = move |values: Vec<bool>| {
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")
}
};
@ -164,7 +178,7 @@ pub fn get_cpus_online(
output.push(status.into());
}
output
}
},
}
}
@ -172,25 +186,29 @@ pub fn set_clock_limits(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, value: MinMax<u64>|
sender.lock()
let setter = move |index: usize, value: MinMax<u64>| {
sender
.lock()
.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| {
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(max)) = params_in.get(2) {
let safe_max = if max < min {
min
} else {
max
};
let safe_min = if min > max {
max
} else {
min
};
setter(index as usize, MinMax {min: safe_min as u64, max: safe_max as u64});
let safe_max = if max < min { min } else { max };
let safe_min = if min > max { max } else { min };
setter(
index as usize,
MinMax {
min: safe_min as u64,
max: safe_max as u64,
},
);
vec![safe_min.into(), safe_max.into()]
} else {
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 getter = move |index: usize| {
let (tx, rx) = mpsc::channel();
let callback = move |values: Option<MinMax<u64>>| 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");
let callback = move |values: Option<MinMax<u64>>| {
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")
};
move |params_in: super::ApiParameterType| {
@ -231,10 +259,13 @@ pub fn unset_clock_limits(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize|
sender.lock()
let setter = move |index: usize| {
sender
.lock()
.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| {
if let Some(&Primitive::F64(index)) = params_in.get(0) {
setter(index as usize);
@ -249,10 +280,13 @@ pub fn set_cpu_governor(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |index: usize, governor: String|
sender.lock()
let setter = move |index: usize, governor: String| {
sender
.lock()
.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| {
if let Some(&Primitive::F64(index)) = params_in.get(0) {
if let Some(Primitive::String(governor)) = params_in.get(1) {
@ -271,10 +305,13 @@ pub fn set_cpus_governors(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |governors: Vec<String>|
sender.lock()
let setter = move |governors: Vec<String>| {
sender
.lock()
.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| {
let mut result = 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 getter = move || {
let (tx, rx) = mpsc::channel();
let callback = move |values: Vec<String>| 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");
let callback = move |values: Vec<String>| {
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")
};
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 usdpl_back::core::serdes::Primitive;
use usdpl_back::AsyncCallable;
@ -11,10 +11,13 @@ pub fn set_persistent(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |pers: bool|
sender.lock()
let setter = move |pers: bool| {
sender
.lock()
.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| {
if let Some(&Primitive::Bool(new_val)) = params_in.get(0) {
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 getter = move || {
let (tx, rx) = mpsc::channel();
let callback = 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");
let callback =
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")
};
move |_: super::ApiParameterType| {
vec![getter().into()]
}
move |_: super::ApiParameterType| vec![getter().into()]
}
/// Generate load app settings from file web method
@ -47,10 +55,13 @@ pub fn load_settings(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |path: i64, name: String|
sender.lock()
let setter = move |path: i64, name: String| {
sender
.lock()
.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| {
if let Some(Primitive::F64(id)) = params_in.get(0) {
if let Some(Primitive::String(name)) = params_in.get(1) {
@ -73,10 +84,13 @@ pub fn load_default_settings(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move ||
sender.lock()
let setter = move || {
sender
.lock()
.unwrap()
.send(ApiMessage::LoadMainSettings).expect("load_default_settings send failed");
.send(ApiMessage::LoadMainSettings)
.expect("load_default_settings send failed")
};
move |_: super::ApiParameterType| {
setter();
vec![true.into()]
@ -99,10 +113,13 @@ pub fn load_system_settings(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move ||
sender.lock()
let setter = move || {
sender
.lock()
.unwrap()
.send(ApiMessage::LoadSystemSettings).expect("load_default_settings send failed");
.send(ApiMessage::LoadSystemSettings)
.expect("load_default_settings send failed")
};
move |_: super::ApiParameterType| {
setter();
vec![true.into()]
@ -121,68 +138,75 @@ pub fn load_system_settings(
}
/// Generate get current settings name
pub fn get_name(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn get_name(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = 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");
let callback =
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")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |result| {
vec![result.into()]
}
trans_getter: |result| vec![result.into()],
}
}
/// Generate get current settings name
pub fn get_path(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn get_path(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
let callback = move |name: std::path::PathBuf| 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");
let callback = move |name: std::path::PathBuf| {
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")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |result| {
vec![result.to_string_lossy().to_string().into()]
}
trans_getter: |result| vec![result.to_string_lossy().to_string().into()],
}
}
/// Generate wait for all locks to be available web method
pub fn lock_unlock_all(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn lock_unlock_all(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move || {
let (tx, rx) = mpsc::channel();
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")
}
};
super::async_utils::AsyncIshGetter {
set_get: getter,
trans_getter: |_| {
vec![true.into()]
}
trans_getter: |_| 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 getter = move || {
let (tx, rx) = mpsc::channel();
let callback = move |value: super::SettingsLimits| tx.send(value).expect("get_limits callback send failed");
sender.lock().unwrap().send(ApiMessage::GetLimits(Box::new(callback))).expect("get_limits send failed");
let callback = move |value: super::SettingsLimits| {
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")
};
move |_: super::ApiParameterType| {
@ -203,16 +233,20 @@ pub fn get_limits(
}
/// Generate get current driver name
pub fn get_provider(
sender: Sender<ApiMessage>,
) -> impl AsyncCallable {
pub fn get_provider(sender: Sender<ApiMessage>) -> impl AsyncCallable {
let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety
let getter = move || {
let sender2 = sender.clone();
move |provider_name: String| {
let (tx, rx) = mpsc::channel();
let callback = move |name: crate::persist::DriverJson| 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");
let callback = move |name: crate::persist::DriverJson| {
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")
}
};
@ -225,9 +259,7 @@ pub fn get_provider(
}
},
set_get: getter,
trans_getter: |result| {
vec![format!("{:?}", result).into()]
}
trans_getter: |result| vec![format!("{:?}", result).into()],
}
}
@ -277,14 +309,15 @@ pub fn force_apply(
sender: Sender<ApiMessage>,
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
let setter = move |_: ()|
sender.lock()
let setter = move |_: ()| {
sender
.lock()
.unwrap()
.send(ApiMessage::General(GeneralMessage::ApplyNow))
.expect("force_apply send failed");
.expect("force_apply send failed")
};
move |_params_in: super::ApiParameterType| {
setter(());
vec![true.into()]
}
}

View file

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

View file

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

View file

@ -1,10 +1,10 @@
mod api_types;
mod async_utils;
pub mod battery;
pub mod cpu;
pub mod general;
pub mod gpu;
pub mod handler;
mod async_utils;
mod utility;
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) => {
log::debug!("Mapping error to primitive: {}", e);
vec![e.msg.into()]
},
}
}
}
#[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 {
Ok(val) => match val {
Some(val) => vec![val.into()],
@ -24,7 +26,7 @@ pub fn map_optional_result<T: Into<Primitive>>(result: Result<Option<T>, Setting
Err(e) => {
log::debug!("Mapping error to primitive: {}", e);
vec![e.msg.into()]
},
}
}
}

View file

@ -22,17 +22,18 @@ fn main() -> Result<(), ()> {
#[cfg(debug_assertions)]
let log_filepath = usdpl_back::api::dirs::home()
.unwrap_or_else(|| "/tmp/".into())
.join(PACKAGE_NAME.to_owned()+".log");
.join(PACKAGE_NAME.to_owned() + ".log");
#[cfg(not(debug_assertions))]
let log_filepath = std::path::Path::new("/tmp").join(format!("{}.log", PACKAGE_NAME));
#[cfg(debug_assertions)]
let old_log_filepath = usdpl_back::api::dirs::home()
.unwrap_or_else(|| "/tmp/".into())
.join(PACKAGE_NAME.to_owned()+".log.old");
.join(PACKAGE_NAME.to_owned() + ".log.old");
#[cfg(debug_assertions)]
{
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(
@ -53,8 +54,14 @@ fn main() -> Result<(), ()> {
println!("Logging to: {:?}", log_filepath);
log::info!("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());
println!("Current dir `{}`", std::env::current_dir().unwrap().display());
log::info!(
"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());
@ -66,11 +73,20 @@ fn main() -> Result<(), ()> {
}
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))
.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()));
let mut loaded_settings =
persist::SettingsJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE))
.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);
@ -83,19 +99,33 @@ fn main() -> Result<(), ()> {
let instance = Instance::new(PORT)
.register("V_INFO", |_: Vec<Primitive>| {
#[cfg(debug_assertions)]
{vec![format!("v{}-dbg", PACKAGE_VERSION).into()]}
{
vec![format!("v{}-dbg", PACKAGE_VERSION).into()]
}
#[cfg(not(debug_assertions))]
{vec![format!("v{}-rls", PACKAGE_VERSION).into()]}
})
.register("NAME", |_: Vec<Primitive>| {
vec![PACKAGE_NAME.into()]
{
vec![format!("v{}-rls", PACKAGE_VERSION).into()]
}
})
.register("NAME", |_: Vec<Primitive>| vec![PACKAGE_NAME.into()])
.register("LOG", api::general::log_it())
// battery API functions
.register_async("BATTERY_current_now", api::battery::current_now(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_async(
"BATTERY_current_now",
api::battery::current_now(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(
"BATTERY_set_charge_rate",
api::battery::set_charge_rate(api_sender.clone()),
@ -136,138 +166,124 @@ fn main() -> Result<(), ()> {
.register("CPU_count", api::cpu::max_cpus)
.register(
"CPU_set_online",
api::cpu::set_cpu_online(api_sender.clone())
api::cpu::set_cpu_online(api_sender.clone()),
)
.register(
"CPU_set_onlines",
api::cpu::set_cpus_online(api_sender.clone())
api::cpu::set_cpus_online(api_sender.clone()),
)
.register_async(
"CPU_get_onlines",
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())
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(
"CPU_set_clock_limits",
api::cpu::set_clock_limits(api_sender.clone())
api::cpu::set_clock_limits(api_sender.clone()),
)
.register(
"CPU_get_clock_limits",
api::cpu::get_clock_limits(api_sender.clone())
api::cpu::get_clock_limits(api_sender.clone()),
)
.register(
"CPU_unset_clock_limits",
api::cpu::unset_clock_limits(api_sender.clone())
api::cpu::unset_clock_limits(api_sender.clone()),
)
.register(
"CPU_set_governor",
api::cpu::set_cpu_governor(api_sender.clone())
api::cpu::set_cpu_governor(api_sender.clone()),
)
.register(
"CPU_set_governors",
api::cpu::set_cpus_governors(api_sender.clone())
api::cpu::set_cpus_governors(api_sender.clone()),
)
.register(
"CPU_get_governors",
api::cpu::get_cpu_governors(api_sender.clone())
api::cpu::get_cpu_governors(api_sender.clone()),
)
// gpu API functions
.register(
"GPU_set_ppt",
api::gpu::set_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("GPU_set_ppt", api::gpu::set_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(
"GPU_set_clock_limits",
api::gpu::set_clock_limits(api_sender.clone())
api::gpu::set_clock_limits(api_sender.clone()),
)
.register_async(
"GPU_get_clock_limits",
api::gpu::get_clock_limits(api_sender.clone())
api::gpu::get_clock_limits(api_sender.clone()),
)
.register(
"GPU_unset_clock_limits",
api::gpu::unset_clock_limits(api_sender.clone())
api::gpu::unset_clock_limits(api_sender.clone()),
)
.register(
"GPU_set_slow_memory",
api::gpu::set_slow_memory(api_sender.clone())
api::gpu::set_slow_memory(api_sender.clone()),
)
.register_async(
"GPU_get_slow_memory",
api::gpu::get_slow_memory(api_sender.clone())
api::gpu::get_slow_memory(api_sender.clone()),
)
// general API functions
.register(
"GENERAL_set_persistent",
api::general::set_persistent(api_sender.clone())
api::general::set_persistent(api_sender.clone()),
)
.register(
"GENERAL_get_persistent",
api::general::get_persistent(api_sender.clone())
api::general::get_persistent(api_sender.clone()),
)
.register(
"GENERAL_load_settings",
api::general::load_settings(api_sender.clone())
api::general::load_settings(api_sender.clone()),
)
.register(
"GENERAL_load_default_settings",
api::general::load_default_settings(api_sender.clone())
api::general::load_default_settings(api_sender.clone()),
)
.register(
"GENERAL_load_system_settings",
api::general::load_system_settings(api_sender.clone())
api::general::load_system_settings(api_sender.clone()),
)
.register_async(
"GENERAL_get_name",
api::general::get_name(api_sender.clone())
api::general::get_name(api_sender.clone()),
)
.register_async(
"GENERAL_get_path",
api::general::get_path(api_sender.clone())
api::general::get_path(api_sender.clone()),
)
.register_async(
"GENERAL_wait_for_unlocks",
api::general::lock_unlock_all(api_sender.clone())
api::general::lock_unlock_all(api_sender.clone()),
)
.register_blocking(
"GENERAL_get_limits",
api::general::get_limits(api_sender.clone())
api::general::get_limits(api_sender.clone()),
)
.register_async(
"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_apply_now",
api::general::force_apply(api_sender.clone())
api::general::force_apply(api_sender.clone()),
)
.register(
"GENERAL_on_pluggedin",
api::battery::on_plugged(api_sender.clone())
api::battery::on_plugged(api_sender.clone()),
)
.register(
"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() {
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 {
log::info!("Startup Settings.on_set() success");
}
@ -278,6 +294,5 @@ fn main() -> Result<(), ()> {
api_worker::spawn(loaded_settings, api_handler);
instance
.run_blocking()
instance.run_blocking()
}

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
use std::sync::mpsc::Sender;
use std::thread::{self, JoinHandle};
use std::time::{Duration, Instant};
use std::sync::mpsc::Sender;
use crate::api::handler::ApiMessage;
//use crate::utility::unwrap_maybe_fatal;
@ -11,7 +11,7 @@ pub fn spawn(sender: Sender<ApiMessage>) -> JoinHandle<()> {
thread::spawn(move || {
log::info!("resume_worker starting...");
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();
loop {
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) {
// has just resumed from sleep
log::info!("Resume detected");
sender.send(ApiMessage::OnResume).expect("resume_worker send failed");
sender
.send(ApiMessage::OnResume)
.expect("resume_worker send failed");
log::debug!(
"OnResume completed after sleeping for {}s",
old_start.as_secs_f32()

View file

@ -2,25 +2,31 @@ use std::fs::File;
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::settings::{TGeneral, TCpus, TGpu, TBattery, Driver, General};
use crate::settings::{Driver, General, TBattery, TCpus, TGeneral, TGpu};
fn get_limits() -> limits_core::json::Base {
let limits_path = super::utility::limits_path();
match File::open(&limits_path) {
Ok(f) => {
match serde_json::from_reader(f) {
Ok(lim) => lim,
Err(e) => {
log::warn!("Failed to parse limits file `{}`, cannot use for auto_detect: {}", limits_path.display(), e);
limits_core::json::Base::default()
}
Ok(f) => match serde_json::from_reader(f) {
Ok(lim) => lim,
Err(e) => {
log::warn!(
"Failed to parse limits file `{}`, cannot use for auto_detect: {}",
limits_path.display(),
e
);
limits_core::json::Base::default()
}
},
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()
}
}
@ -28,22 +34,34 @@ fn get_limits() -> limits_core::json::Base {
#[inline]
pub fn auto_detect_provider() -> DriverJson {
let provider = auto_detect0(None, crate::utility::settings_dir().join("autodetect.json"), "".to_owned())
.battery
.provider();
let provider = auto_detect0(
None,
crate::utility::settings_dir().join("autodetect.json"),
"".to_owned(),
)
.battery
.provider();
//log::info!("Detected device automatically, compatible driver: {:?}", provider);
provider
}
/// 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 cpu_info: String = usdpl_back::api::files::read_single("/proc/cpuinfo").unwrap_or_default();
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);
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);
let limits = get_limits();
@ -60,26 +78,27 @@ pub fn auto_detect0(settings_opt: Option<SettingsJson>, json_path: std::path::Pa
.multi_line(true)
.build()
.expect("Invalid DMI regex");
matches &=pattern.is_match(&dmi_info);
matches &= pattern.is_match(&dmi_info);
}
if let Some(cpuinfo) = &conditions.cpuinfo {
let pattern = RegexBuilder::new(cpuinfo)
.multi_line(true)
.build()
.expect("Invalid CPU regex");
matches &=pattern.is_match(&cpu_info);
matches &= pattern.is_match(&cpu_info);
}
if let Some(os) = &conditions.os {
let pattern = RegexBuilder::new(os)
.multi_line(true)
.build()
.expect("Invalid OS regex");
matches &=pattern.is_match(&os_info);
matches &= pattern.is_match(&os_info);
}
if let Some(cmd) = &conditions.command {
match std::process::Command::new("bash")
.args(["-c", cmd])
.status() {
.status()
{
Ok(status) => matches &= status.code().map(|c| c == 0).unwrap_or(false),
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 {
Limits::Cpu(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::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)),
CpuLimit::SteamDeck => {
Box::new(crate::settings::steam_deck::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);
},
}
Limits::Gpu(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::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)),
GpuLimit::SteamDeck => {
Box::new(crate::settings::steam_deck::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);
},
}
Limits::Battery(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::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),
BatteryLimit::SteamDeck => {
Box::new(crate::settings::steam_deck::Battery::from_json(
settings.battery.clone(),
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);
}
@ -131,37 +222,66 @@ pub fn auto_detect0(settings_opt: Option<SettingsJson>, json_path: std::path::Pa
match limit {
Limits::Cpu(cpus) => {
let cpu_driver: Box<dyn TCpus> = match cpus {
CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::system_default()),
CpuLimit::SteamDeckAdvance => 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()),
CpuLimit::SteamDeck => {
Box::new(crate::settings::steam_deck::Cpus::system_default())
}
CpuLimit::SteamDeckAdvance => {
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);
},
}
Limits::Gpu(gpu) => {
let driver: Box<dyn TGpu> = match gpu {
GpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Gpu::system_default()),
GpuLimit::SteamDeckAdvance => 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()),
GpuLimit::SteamDeck => {
Box::new(crate::settings::steam_deck::Gpu::system_default())
}
GpuLimit::SteamDeckAdvance => {
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);
},
}
Limits::Battery(batt) => {
let driver: Box<dyn TBattery> = match batt {
BatteryLimit::SteamDeck => Box::new(crate::settings::steam_deck::Battery::system_default()),
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),
BatteryLimit::SteamDeck => {
Box::new(crate::settings::steam_deck::Battery::system_default())
}
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);
}
}
}
}
}
}
@ -197,9 +317,15 @@ impl DriverBuilder {
fn build(self) -> Driver {
Driver {
general: self.general,
cpus: self.cpus.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))
cpus: self
.cpus
.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<()> {
thread::spawn(move || {
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();
loop {
thread::sleep(sleep_dur);
if (limits_path.exists() && limits_path.is_file()) || !limits_path.exists() {
// try to load limits from file, fallback to built-in default
let base = match std::fs::File::open(&limits_path) {
Ok(f) => {
match serde_json::from_reader(f) {
Ok(b) => b,
Err(e) => {
log::error!("Cannot parse {}: {}", limits_path.display(), e);
Base::default()
}
Ok(f) => match serde_json::from_reader(f) {
Ok(b) => b,
Err(e) => {
log::error!("Cannot parse {}: {}", limits_path.display(), e);
Base::default()
}
},
Err(e) => {
@ -31,17 +29,18 @@ pub fn spawn() -> JoinHandle<()> {
};
if let Some(refresh) = &base.refresh {
// try to retrieve newer version
match ureq::get(refresh)
.call() {
match ureq::get(refresh).call() {
Ok(response) => {
let json_res: std::io::Result<Base> = response.into_json();
match json_res {
Ok(new_base) => {
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),
}
} else {
@ -67,13 +66,11 @@ pub fn get_limits_blocking() -> Base {
let limits_path = super::utility::limits_path();
if limits_path.is_file() {
match std::fs::File::open(&limits_path) {
Ok(f) => {
match serde_json::from_reader(f) {
Ok(b) => b,
Err(e) => {
log::error!("Cannot parse {}: {}", limits_path.display(), e);
Base::default()
}
Ok(f) => match serde_json::from_reader(f) {
Ok(b) => b,
Err(e) => {
log::error!("Cannot parse {}: {}", limits_path.display(), e);
Base::default()
}
},
Err(e) => {
@ -86,17 +83,18 @@ pub fn get_limits_blocking() -> Base {
{
let refresh = Base::default().refresh.unwrap();
match ureq::get(&refresh) // try to retrieve newer version
.call() {
.call()
{
Ok(response) => {
let json_res: std::io::Result<Base> = response.into_json();
match json_res {
Ok(new_base) => {
save_base(&new_base, &limits_path);
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),
}
}
@ -108,12 +106,14 @@ pub fn get_limits_blocking() -> Base {
fn save_base(new_base: &Base, path: impl AsRef<std::path::Path>) {
let limits_path = path.as_ref();
match std::fs::File::create(&limits_path) {
Ok(f) => {
match serde_json::to_writer_pretty(f, &new_base) {
Ok(_) => log::info!("Successfully saved new limits to {}", limits_path.display()),
Err(e) => log::error!("Failed to save limits json to file `{}`: {}", limits_path.display(), e),
}
Ok(f) => match serde_json::to_writer_pretty(f, &new_base) {
Ok(_) => log::info!("Successfully saved new limits to {}", limits_path.display()),
Err(e) => log::error!(
"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;
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 super::{TGeneral, TCpus, TGpu, TBattery, SettingError, General, auto_detect0};
pub struct Driver {
pub general: Box<dyn TGeneral>,
@ -9,7 +9,10 @@ pub struct 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 {
0 => Self::version0(settings, json_path)?,
_ => Self {
@ -19,14 +22,26 @@ impl Driver {
name: settings.name,
driver: DriverJson::SteamDeck,
}),
cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, 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)),
cpus: Box::new(super::steam_deck::Cpus::from_json(
settings.cpus,
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();
if let Some(provider) = &settings.provider {
match provider {
@ -37,9 +52,18 @@ impl Driver {
name: settings.name,
driver: DriverJson::SteamDeck,
}),
cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, 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)),
cpus: Box::new(super::steam_deck::Cpus::from_json(
settings.cpus,
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
DriverJson::SteamDeckAdvance => Ok(Self {
@ -49,13 +73,28 @@ impl Driver {
name: settings.name,
driver: DriverJson::SteamDeckAdvance,
}),
cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, 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)),
cpus: Box::new(super::steam_deck::Cpus::from_json(
settings.cpus,
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::Unknown => Ok(super::detect::auto_detect0(Some(settings), json_path, name)),
DriverJson::AutoDetect => Ok(super::detect::auto_detect0(Some(settings), json_path, name)),
DriverJson::Generic | DriverJson::GenericAMD => {
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 {
Ok(super::detect::auto_detect0(Some(settings), json_path, name))
@ -73,9 +112,11 @@ pub fn maybe_do_button() {
match super::auto_detect_provider() {
DriverJson::SteamDeck | DriverJson::SteamDeckAdvance => {
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::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::{OnResume, OnSet, SettingError};
use super::{TGeneral, TGpu, TCpus, TBattery};
use super::{TBattery, TCpus, TGeneral, TGpu};
use crate::persist::SettingsJson;
//use crate::utility::unwrap_lock;
@ -52,7 +52,7 @@ impl crate::settings::OnPowerEvent for General {}
impl TGeneral for General {
fn limits(&self) -> crate::api::GeneralLimits {
crate::api::GeneralLimits { }
crate::api::GeneralLimits {}
}
fn get_persistent(&self) -> bool {
@ -97,17 +97,25 @@ impl OnSet for Settings {
let mut errors = Vec::new();
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");
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");
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");
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");
if errors.is_empty() {
Ok(())
Ok(())
} else {
Err(errors)
}
@ -120,14 +128,20 @@ impl Settings {
let name_bup = other.name.clone();
match super::Driver::init(other, json_path.clone()) {
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 {
general: x.general,
cpus: x.cpus,
gpu: x.gpu,
battery: x.battery,
}
},
}
Err(e) => {
log::error!("Driver init error: {}", e);
Self::system_default(json_path, name_bup)
@ -153,7 +167,12 @@ impl Settings {
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);
if json_path.exists() {
let settings_json = SettingsJson::open(&json_path).map_err(|e| SettingError {
@ -161,7 +180,11 @@ impl Settings {
setting: SettingVariant::General,
})?;
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.name(name);
} else {
@ -172,7 +195,7 @@ impl Settings {
self.cpus = x.cpus;
self.gpu = x.gpu;
self.battery = x.battery;
},
}
Err(e) => {
log::error!("Driver init error: {}", e);
self.general.name(name);
@ -193,7 +216,7 @@ impl Settings {
self.general.path(filename);
Ok(*self.general.persistent())
}
/*
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);
@ -243,17 +266,25 @@ impl OnResume for Settings {
let mut errors = Vec::new();
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");
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");
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");
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");
if errors.is_empty() {
Ok(())
Ok(())
} else {
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>> {
let mut errors = Vec::new();
self.general.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));
self.general
.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() {
Ok(())
Ok(())
} else {
Err(errors)
}

View file

@ -2,9 +2,9 @@ use std::convert::Into;
use limits_core::json::GenericBatteryLimit;
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::TBattery;
use crate::persist::BatteryJson;
use crate::settings::TBattery;
use crate::settings::{OnResume, OnSet, SettingError};
#[derive(Debug, Clone)]
pub struct Battery {
@ -39,16 +39,16 @@ impl Battery {
pub fn from_limits(limits: limits_core::json::GenericBatteryLimit) -> Self {
// TODO
Self {
limits
}
Self { 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
Self {
limits
}
Self { limits }
}
}
@ -83,15 +83,13 @@ impl TBattery for Battery {
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> {
None
}
fn charge_mode(&mut self, _rate: Option<String>) {
}
fn charge_mode(&mut self, _rate: Option<String>) {}
fn get_charge_mode(&self) -> Option<String> {
None
@ -133,7 +131,9 @@ impl TBattery for Battery {
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 {
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 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 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_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 {
// toggle SMT
if self.smt {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "on").map_err(|e| {
SettingError {
msg: format!(
"Failed to write `on` to `{}`: {}",
CPU_SMT_PATH, e
),
usdpl_back::api::files::write_single(CPU_SMT_PATH, "on")
.map_err(|e| SettingError {
msg: format!("Failed to write `on` to `{}`: {}", CPU_SMT_PATH, e),
setting: crate::settings::SettingVariant::Cpu,
}
}).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
} else {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| {
SettingError {
msg: format!(
"Failed to write `off` to `{}`: {}",
CPU_SMT_PATH, e
),
usdpl_back::api::files::write_single(CPU_SMT_PATH, "off")
.map_err(|e| SettingError {
msg: format!("Failed to write `off` to `{}`: {}", CPU_SMT_PATH, e),
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() {
@ -61,7 +55,8 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + OnResume> OnResume for Cpus<C> {
fn on_resume(&self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new();
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() {
Ok(())
@ -88,7 +83,7 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> Cpus<C> {
fn system_smt_capabilities() -> (bool, bool) {
match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) {
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 mut result = Vec::with_capacity(other.len());
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> {
fn on_power_event(&mut self, new_mode: crate::settings::PowerMode) -> Result<(), Vec<SettingError>> {
impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + crate::settings::OnPowerEvent>
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();
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() {
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 {
crate::api::CpusLimits {
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> {
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> {
@ -228,7 +238,12 @@ impl FromGenericCpuInfo for Cpu {
}
#[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() {
other.clock_limits.map(|x| min_max_from_json(x, version))
} else {
@ -259,28 +274,29 @@ impl Cpu {
fn set_all(&mut self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new();
// 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);
usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| {
SettingError {
usdpl_back::api::files::write_single(&online_path, self.online as u8)
.map_err(|e| SettingError {
msg: format!("Failed to write to `{}`: {}", &online_path, e),
setting: crate::settings::SettingVariant::Cpu,
}
}).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
}
// set governor
if self.index == 0 || self.online {
let governor_path = cpu_governor_path(self.index);
usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| {
SettingError {
usdpl_back::api::files::write_single(&governor_path, &self.governor)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
&self.governor, &governor_path, e
),
setting: crate::settings::SettingVariant::Cpu,
}
}).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
}
if errors.is_empty() {
Ok(())
@ -301,13 +317,14 @@ impl Cpu {
fn governors(&self) -> Vec<String> {
// NOTE: this eats errors
let gov_str: String = match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) {
Ok(s) => s,
Err(e) => {
log::warn!("Error getting available CPU governors: {}", e);
return vec![];
},
};
let gov_str: String =
match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) {
Ok(s) => s,
Err(e) => {
log::warn!("Error getting available CPU governors: {}", e);
return vec![];
}
};
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 crate::settings::{MinMax, min_max_from_json};
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::TGpu;
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)]
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() {
other.clock_limits.map(|x| min_max_from_json(x, version))
} else {
@ -48,8 +52,16 @@ impl Gpu {
};
Self {
slow_memory: false,
fast_ppt: if limits.fast_ppt.is_some() {other.fast_ppt} else {None},
slow_ppt: if limits.slow_ppt.is_some() {other.slow_ppt} else {None},
fast_ppt: if limits.fast_ppt.is_some() {
other.fast_ppt
} else {
None
},
slow_ppt: if limits.slow_ppt.is_some() {
other.slow_ppt
} else {
None
},
clock_limits: clock_lims,
limits,
}

View file

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

View file

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

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 driver::Driver;
pub use general::{SettingVariant, Settings, General};
pub use min_max::{MinMax, min_max_from_json};
pub use general::{General, SettingVariant, Settings};
pub use min_max::{min_max_from_json, MinMax};
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)]
mod tests {

View file

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

View file

@ -1,12 +1,12 @@
use std::convert::Into;
use crate::api::RangeLimit;
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::oc_limits::{CpuLimits, CpusLimits, OverclockLimits};
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_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control";
@ -26,25 +26,19 @@ impl OnSet for Cpus {
if self.smt_capable {
// toggle SMT
if self.smt {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "on").map_err(|e| {
SettingError {
msg: format!(
"Failed to write `on` to `{}`: {}",
CPU_SMT_PATH, e
),
usdpl_back::api::files::write_single(CPU_SMT_PATH, "on")
.map_err(|e| SettingError {
msg: format!("Failed to write `on` to `{}`: {}", CPU_SMT_PATH, e),
setting: crate::settings::SettingVariant::Cpu,
}
}).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
} else {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| {
SettingError {
msg: format!(
"Failed to write `off` to `{}`: {}",
CPU_SMT_PATH, e
),
usdpl_back::api::files::write_single(CPU_SMT_PATH, "off")
.map_err(|e| SettingError {
msg: format!("Failed to write `off` to `{}`: {}", CPU_SMT_PATH, e),
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() {
@ -63,7 +57,8 @@ impl OnResume for Cpus {
fn on_resume(&self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new();
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() {
Ok(())
@ -90,7 +85,7 @@ impl Cpus {
fn system_smt_capabilities() -> (bool, bool) {
match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) {
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();
let (oc_limits, is_default) = OverclockLimits::load_or_default();
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() {
let mut sys_cpus = Vec::with_capacity(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();
Self {
@ -128,7 +134,11 @@ impl Cpus {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.reset();
let (oc_limits, is_default) = OverclockLimits::load_or_default();
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 mut result = Vec::with_capacity(other.len());
let max_cpus = Self::cpu_count();
@ -140,7 +150,16 @@ impl Cpus {
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);
}
if let Some(max_cpus) = max_cpus {
@ -170,11 +189,14 @@ impl TCpus for Cpus {
count: self.cpus.len(),
smt_capable: self.smt_capable,
governors: if self.limits.global_governors {
self.cpus.iter()
self.cpus
.iter()
.next()
.map(|x| x.governors())
.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 {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(true, self.index);
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;
// max clock
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(
|e| SettingError {
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
&payload_max, CPU_CLOCK_LIMITS_PATH, e
),
setting: crate::settings::SettingVariant::Cpu,
},
).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
// 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);
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min).map_err(
|e| SettingError {
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
&payload_min, CPU_CLOCK_LIMITS_PATH, e
),
setting: crate::settings::SettingVariant::Cpu,
},
).unwrap_or_else(|e| errors.push(e));
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n")
.unwrap_or_else(|e| {
})
.unwrap_or_else(|e| errors.push(e));
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else(
|e| {
errors.push(SettingError {
msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e),
setting: crate::settings::SettingVariant::Cpu,
});
});
} else if self.state.clock_limits_set ||
(self.state.is_resuming && !self.limits.skip_resume_reclock)
|| POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() {
},
);
} 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;
if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?;
@ -286,45 +319,51 @@ impl Cpu {
log::debug!("Setting CPU {} to default clockspeed", self.index);
// max clock
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(
|e| SettingError {
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
&payload_max, CPU_CLOCK_LIMITS_PATH, e
),
setting: crate::settings::SettingVariant::Cpu,
},
).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
// min clock
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(
|e| SettingError {
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
&payload_min, CPU_CLOCK_LIMITS_PATH, e
),
setting: crate::settings::SettingVariant::Cpu,
},
).unwrap_or_else(|e| errors.push(e));
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n")
.unwrap_or_else(|e| {
})
.unwrap_or_else(|e| errors.push(e));
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else(
|e| {
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,
});
});
},
);
}
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)
if errors.is_empty() {
usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| {
vec![SettingError {
msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e),
setting: crate::settings::SettingVariant::Cpu,
}]
})
vec![SettingError {
msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e),
setting: crate::settings::SettingVariant::Cpu,
}]
})
} else {
Err(errors)
}
@ -333,14 +372,15 @@ impl Cpu {
fn set_all(&mut self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new();
// 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);
usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| {
SettingError {
usdpl_back::api::files::write_single(&online_path, self.online as u8)
.map_err(|e| SettingError {
msg: format!("Failed to write to `{}`: {}", &online_path, e),
setting: crate::settings::SettingVariant::Cpu,
}
}).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
}
self.set_force_performance_related()
@ -349,15 +389,15 @@ impl Cpu {
// set governor
if self.index == 0 || self.online {
let governor_path = cpu_governor_path(self.index);
usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| {
SettingError {
usdpl_back::api::files::write_single(&governor_path, &self.governor)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
&self.governor, &governor_path, e
),
setting: crate::settings::SettingVariant::Cpu,
}
}).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
}
if errors.is_empty() {
Ok(())
@ -368,8 +408,12 @@ impl Cpu {
fn clamp_all(&mut self) {
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.max = clock_limits.max.clamp(self.limits.clock_max.min, self.limits.clock_max.max);
clock_limits.min = clock_limits
.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 {
clock_min_limits: Some(RangeLimit {
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 {
min: self.limits.clock_max.min,
max: self.limits.clock_max.max
max: self.limits.clock_max.max,
}),
clock_step: self.limits.clock_step,
governors: self.governors(),
@ -413,13 +457,14 @@ impl Cpu {
fn governors(&self) -> Vec<String> {
// NOTE: this eats errors
let gov_str: String = match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) {
Ok(s) => s,
Err(e) => {
log::warn!("Error getting available CPU governors: {}", e);
return vec![];
}
};
let gov_str: String =
match usdpl_back::api::files::read_single(cpu_available_governors_path(self.index)) {
Ok(s) => s,
Err(e) => {
log::warn!("Error getting available CPU governors: {}", e);
return vec![];
}
};
gov_str.split(' ').map(|s| s.to_owned()).collect()
}
}
@ -485,7 +530,6 @@ fn cpu_governor_path(index: usize) -> String {
)
}
#[inline]
fn cpu_available_governors_path(index: usize) -> String {
format!(

View file

@ -1,12 +1,12 @@
use std::convert::Into;
use crate::api::RangeLimit;
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::oc_limits::{GpuLimits, OverclockLimits};
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 FAST_PPT: u8 = 2;
@ -30,7 +30,11 @@ impl Gpu {
#[inline]
pub fn from_json(other: GpuJson, version: u64) -> Self {
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 {
0 => Self {
fast_ppt: other.fast_ppt,
@ -62,70 +66,80 @@ impl Gpu {
self.state.clock_limits_set = true;
// max clock
let payload_max = format!("s 1 {}\n", clock_limits.max);
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max).map_err(
|e| SettingError {
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
&payload_max, GPU_CLOCK_LIMITS_PATH, e
),
setting: crate::settings::SettingVariant::Gpu,
},
).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
// min clock
let payload_min = format!("s 0 {}\n", clock_limits.min);
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min).map_err(
|e| SettingError {
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
&payload_min, 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,
})
});
} else if self.state.clock_limits_set ||
(self.state.is_resuming && !self.limits.skip_resume_reclock)
|| POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() {
.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,
})
},
);
} 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;
if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() {
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?;
// disable manual clock limits
// max clock
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(
|e| SettingError {
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
&payload_max, GPU_CLOCK_LIMITS_PATH, e
),
setting: crate::settings::SettingVariant::Gpu,
},
).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
// min clock
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(
|e| SettingError {
usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
&payload_min, 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,
})
});
.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.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() {
Ok(())
@ -139,24 +153,28 @@ impl Gpu {
// enable/disable downclock of GPU memory (to 400Mhz?)
if self.slow_memory {
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)
.unwrap_or_else(|e| {
errors.push(SettingError {
msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e),
setting: crate::settings::SettingVariant::Gpu,
.unwrap_or_else(|e| {
errors.push(SettingError {
msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e),
setting: crate::settings::SettingVariant::Gpu,
});
});
});
} 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)
.unwrap_or_else(|e| {
errors.push(SettingError {
msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e),
setting: crate::settings::SettingVariant::Gpu,
.unwrap_or_else(|e| {
errors.push(SettingError {
msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e),
setting: crate::settings::SettingVariant::Gpu,
});
});
});
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()
.unwrap_or_else(|mut e| errors.append(&mut e));
@ -182,28 +200,32 @@ impl Gpu {
// set fast PPT
if let Some(fast_ppt) = &self.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| {
SettingError {
usdpl_back::api::files::write_single(&fast_ppt_path, fast_ppt)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
fast_ppt, &fast_ppt_path, e
),
setting: crate::settings::SettingVariant::Gpu,
}
}).unwrap_or_else(|e| {errors.push(e);});
})
.unwrap_or_else(|e| {
errors.push(e);
});
}
// set slow PPT
if let Some(slow_ppt) = &self.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| {
SettingError {
usdpl_back::api::files::write_single(&slow_ppt_path, slow_ppt)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
slow_ppt, &slow_ppt_path, e
),
setting: crate::settings::SettingVariant::Gpu,
}
}).unwrap_or_else(|e| {errors.push(e);});
})
.unwrap_or_else(|e| {
errors.push(e);
});
}
self.set_force_performance_related()
.unwrap_or_else(|mut e| errors.append(&mut e));
@ -216,20 +238,18 @@ impl Gpu {
fn clamp_all(&mut self) {
if let Some(fast_ppt) = &mut self.fast_ppt {
*fast_ppt = (*fast_ppt).clamp(
self.limits.fast_ppt.min,
self.limits.fast_ppt.max,
);
*fast_ppt = (*fast_ppt).clamp(self.limits.fast_ppt.min, self.limits.fast_ppt.max);
}
if let Some(slow_ppt) = &mut self.slow_ppt {
*slow_ppt = (*slow_ppt).clamp(
self.limits.slow_ppt.min,
self.limits.slow_ppt.max,
);
*slow_ppt = (*slow_ppt).clamp(self.limits.slow_ppt.min, self.limits.slow_ppt.max);
}
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.max = clock_limits.max.clamp(self.limits.clock_max.min, self.limits.clock_max.max);
clock_limits.min = clock_limits
.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,
limits: oc_limits.gpu,
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>) {
(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>>) {

View file

@ -1,5 +1,5 @@
use serde::{Deserialize, Serialize};
use crate::settings::MinMax;
use serde::{Deserialize, Serialize};
const OC_LIMITS_FILEPATH: &str = "pt_oc.json";
@ -29,22 +29,36 @@ impl OverclockLimits {
let mut file = match std::fs::File::open(&path) {
Ok(f) => f,
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);
},
}
};
match serde_json::from_reader(&mut file) {
Ok(result) => {
log::debug!("Steam Deck limits file {} successfully loaded", path.display());
log::debug!(
"Steam Deck limits file {} successfully loaded",
path.display()
);
(result, false)
},
}
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)
}
}
} 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)
}
}
@ -58,7 +72,10 @@ pub(super) struct BatteryLimits {
impl Default for BatteryLimits {
fn default() -> 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 {
fn default() -> Self {
Self {
clock_min: MinMax { min: 1400, max: 3500 },
clock_max: MinMax { min: 400, max: 3500 },
clock_min: MinMax {
min: 1400,
max: 3500,
},
clock_max: MinMax {
min: 400,
max: 3500,
},
clock_step: 100,
skip_resume_reclock: false,
}
@ -112,12 +135,24 @@ pub(super) struct GpuLimits {
impl Default for GpuLimits {
fn default() -> Self {
Self {
fast_ppt: MinMax { min: 1000000, max: 30_000_000 },
slow_ppt: MinMax { min: 1000000, max: 29_000_000 },
fast_ppt: MinMax {
min: 1000000,
max: 30_000_000,
},
slow_ppt: MinMax {
min: 1000000,
max: 29_000_000,
},
ppt_divisor: 1_000_000,
ppt_step: 1,
clock_min: MinMax { min: 400, max: 1600 },
clock_max: MinMax { min: 400, max: 1600 },
clock_min: MinMax {
min: 400,
max: 1600,
},
clock_max: MinMax {
min: 400,
max: 1600,
},
clock_step: 100,
skip_resume_reclock: false,
}

View file

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

View file

@ -6,7 +6,7 @@
#![allow(dead_code)]
use std::fs::OpenOptions;
use std::io::{Error, Seek, SeekFrom, Read, Write};
use std::io::{Error, Read, Seek, SeekFrom, Write};
#[inline]
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> {
let mut file = OpenOptions::new()
.write(true)
.open("/dev/port")?;
let mut file = OpenOptions::new().write(true).open("/dev/port")?;
file.seek(SeekFrom::Start(location))?;
file.write(&[value])
}
fn read_from(location: u64) -> Result<u8, Error> {
let mut file = OpenOptions::new()
.read(true)
.open("/dev/port")?;
let mut file = OpenOptions::new().read(true).open("/dev/port")?;
file.seek(SeekFrom::Start(location))?;
let mut buffer = [0];
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> {
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);
write2(Setting::LEDStatus as _, payload)
}
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, 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,
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, 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, 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, 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);
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 {
let on = code != 0;
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 {
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::SettingError;
use std::fmt::Debug;
pub trait OnSet {
fn on_set(&mut self) -> Result<(), Vec<SettingError>>;
@ -14,7 +14,7 @@ pub trait OnResume {
#[derive(Clone, Copy, Debug)]
pub enum PowerMode {
PluggedIn,
PluggedOut, // unplugged
PluggedOut, // unplugged
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");
let mut events = Vec::new();
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)
}

View file

@ -1,8 +1,8 @@
use std::convert::Into;
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::TBattery;
use crate::persist::BatteryJson;
use crate::settings::TBattery;
use crate::settings::{OnResume, OnSet, SettingError};
#[derive(Debug, Clone)]
pub struct Battery;
@ -47,31 +47,39 @@ impl TBattery for Battery {
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> {
None
}
fn charge_mode(&mut self, _rate: Option<String>) {
}
fn charge_mode(&mut self, _rate: Option<String>) {}
fn get_charge_mode(&self) -> Option<String> {
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 get_charge_limit(&self) -> Option<f64> { None }
fn get_charge_limit(&self) -> Option<f64> {
None
}
fn provider(&self) -> crate::persist::DriverJson {
crate::persist::DriverJson::Unknown

View file

@ -1,9 +1,9 @@
use std::convert::Into;
use crate::persist::CpuJson;
use crate::settings::MinMax;
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::{TCpus, TCpu};
use crate::persist::CpuJson;
use crate::settings::{TCpu, TCpus};
const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present";
const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control";
@ -21,25 +21,23 @@ impl OnSet for Cpus {
if self.smt_capable {
// toggle SMT
if self.smt {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "on").map_err(|e| {
SettingError {
msg: format!(
"Failed to write `on` to `{}`: {}",
CPU_SMT_PATH, e
),
usdpl_back::api::files::write_single(CPU_SMT_PATH, "on")
.map_err(|e| SettingError {
msg: format!("Failed to write `on` to `{}`: {}", CPU_SMT_PATH, e),
setting: crate::settings::SettingVariant::Cpu,
}
}).unwrap_or_else(|e| {errors.push(e);});
})
.unwrap_or_else(|e| {
errors.push(e);
});
} else {
usdpl_back::api::files::write_single(CPU_SMT_PATH, "off").map_err(|e| {
SettingError {
msg: format!(
"Failed to write `off` to `{}`: {}",
CPU_SMT_PATH, e
),
usdpl_back::api::files::write_single(CPU_SMT_PATH, "off")
.map_err(|e| SettingError {
msg: format!("Failed to write `off` to `{}`: {}", CPU_SMT_PATH, e),
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() {
@ -58,7 +56,8 @@ impl OnResume for Cpus {
fn on_resume(&self) -> Result<(), Vec<SettingError>> {
let mut errors = Vec::new();
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() {
Ok(())
@ -87,7 +86,7 @@ impl Cpus {
fn system_smt_capabilities() -> (bool, bool) {
match usdpl_back::api::files::read_single::<_, String, _>(CPU_SMT_PATH) {
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,
}
impl Cpu {
#[inline]
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>> {
let mut errors = Vec::new();
// 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);
usdpl_back::api::files::write_single(&online_path, self.online as u8).map_err(|e| {
SettingError {
usdpl_back::api::files::write_single(&online_path, self.online as u8)
.map_err(|e| SettingError {
msg: format!("Failed to write to `{}`: {}", &online_path, e),
setting: crate::settings::SettingVariant::Cpu,
}
}).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
}
// set governor
if self.index == 0 || self.online {
let governor_path = cpu_governor_path(self.index);
usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| {
SettingError {
usdpl_back::api::files::write_single(&governor_path, &self.governor)
.map_err(|e| SettingError {
msg: format!(
"Failed to write `{}` to `{}`: {}",
&self.governor, &governor_path, e
),
setting: crate::settings::SettingVariant::Cpu,
}
}).unwrap_or_else(|e| errors.push(e));
})
.unwrap_or_else(|e| errors.push(e));
}
if errors.is_empty() {
Ok(())
@ -238,7 +237,8 @@ impl Cpu {
fn from_sys(cpu_index: usize) -> 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))
.unwrap_or("schedutil".to_owned()),
index: cpu_index,
@ -295,8 +295,7 @@ impl TCpu for Cpu {
&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>> {
None

View file

@ -1,9 +1,9 @@
use std::convert::Into;
use crate::settings::MinMax;
use crate::settings::{OnResume, OnSet, SettingError};
use crate::settings::TGpu;
use crate::persist::GpuJson;
use crate::settings::MinMax;
use crate::settings::TGpu;
use crate::settings::{OnResume, OnSet, SettingError};
#[derive(Debug, Clone)]
pub struct Gpu {
@ -13,15 +13,11 @@ pub struct Gpu {
impl Gpu {
#[inline]
pub fn from_json(_other: GpuJson, _version: u64) -> Self {
Self {
slow_memory: false,
}
Self { slow_memory: false }
}
pub fn system_default() -> Self {
Self {
slow_memory: false,
}
Self { slow_memory: false }
}
}
@ -71,15 +67,13 @@ impl TGpu for Gpu {
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>) {
(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>> {
None

View file

@ -1,7 +1,7 @@
pub fn guess_smt(cpus: &Vec<crate::persist::CpuJson>) -> bool {
let mut guess = true;
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
}

View file

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