cargo fmt and fix profile variant loading
This commit is contained in:
parent
85a9fc8f7e
commit
59a0727f88
40 changed files with 1640 additions and 720 deletions
|
@ -67,4 +67,5 @@ pub struct GpuLimits {
|
||||||
pub struct VariantInfo {
|
pub struct VariantInfo {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
pub id_num: u64,
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,13 @@ pub fn load_settings(
|
||||||
sender
|
sender
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.send(ApiMessage::LoadSettings(id, name, variant, variant_name.unwrap_or_else(|| crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned())))
|
.send(ApiMessage::LoadSettings(
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
variant,
|
||||||
|
variant_name
|
||||||
|
.unwrap_or_else(|| crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned()),
|
||||||
|
))
|
||||||
.expect("load_settings send failed")
|
.expect("load_settings send failed")
|
||||||
};
|
};
|
||||||
move |params_in: super::ApiParameterType| {
|
move |params_in: super::ApiParameterType| {
|
||||||
|
@ -67,16 +73,20 @@ pub fn load_settings(
|
||||||
if let Some(Primitive::String(name)) = params_in.get(1) {
|
if let Some(Primitive::String(name)) = params_in.get(1) {
|
||||||
if let Some(Primitive::String(variant_id)) = params_in.get(2) {
|
if let Some(Primitive::String(variant_id)) = params_in.get(2) {
|
||||||
if let Some(Primitive::String(variant_name)) = params_in.get(3) {
|
if let Some(Primitive::String(variant_name)) = params_in.get(3) {
|
||||||
setter(id.parse().unwrap_or_default(),
|
setter(
|
||||||
name.to_owned(),
|
id.parse().unwrap_or_default(),
|
||||||
variant_id.parse().unwrap_or_default(),
|
name.to_owned(),
|
||||||
Some(variant_name.to_owned()));
|
variant_id.parse().unwrap_or_default(),
|
||||||
|
Some(variant_name.to_owned()),
|
||||||
|
);
|
||||||
vec![true.into()]
|
vec![true.into()]
|
||||||
} else {
|
} else {
|
||||||
setter(id.parse().unwrap_or_default(),
|
setter(
|
||||||
name.to_owned(),
|
id.parse().unwrap_or_default(),
|
||||||
variant_id.parse().unwrap_or_default(),
|
name.to_owned(),
|
||||||
None);
|
variant_id.parse().unwrap_or_default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
vec![true.into()]
|
vec![true.into()]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -101,26 +111,32 @@ pub fn load_variant(
|
||||||
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType {
|
||||||
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
|
let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety
|
||||||
let setter = move |variant: u64, variant_name: Option<String>| {
|
let setter = move |variant: u64, variant_name: Option<String>| {
|
||||||
|
log::debug!("load_variant(variant: {}, variant_name: {:?})", variant, variant_name);
|
||||||
sender
|
sender
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.send(ApiMessage::LoadVariant(variant, variant_name.unwrap_or_else(|| crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned())))
|
.send(ApiMessage::LoadVariant(
|
||||||
.expect("load_settings send failed")
|
variant,
|
||||||
|
variant_name
|
||||||
|
.unwrap_or_else(|| "".to_owned()),
|
||||||
|
))
|
||||||
|
.expect("load_variant send failed")
|
||||||
};
|
};
|
||||||
move |params_in: super::ApiParameterType| {
|
move |params_in: super::ApiParameterType| {
|
||||||
if let Some(Primitive::String(variant_id)) = params_in.get(0) {
|
if let Some(Primitive::String(variant_id)) = params_in.get(0) {
|
||||||
if let Some(Primitive::String(variant_name)) = params_in.get(1) {
|
if let Some(Primitive::String(variant_name)) = params_in.get(1) {
|
||||||
setter(variant_id.parse().unwrap_or(u64::MAX),
|
setter(
|
||||||
Some(variant_name.to_owned()));
|
variant_id.parse().unwrap_or(u64::MAX),
|
||||||
|
Some(variant_name.to_owned()),
|
||||||
|
);
|
||||||
vec![true.into()]
|
vec![true.into()]
|
||||||
} else {
|
} else {
|
||||||
setter(variant_id.parse().unwrap_or_default(),
|
setter(variant_id.parse().unwrap_or(u64::MAX), None);
|
||||||
None);
|
|
||||||
vec![true.into()]
|
vec![true.into()]
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::warn!("load_settings missing variant id parameter");
|
log::warn!("load_variant missing variant id parameter");
|
||||||
vec!["load_settings missing variant id parameter".into()]
|
vec!["load_variant missing variant id parameter".into()]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,32 +391,60 @@ pub fn get_periodicals(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
let sender2 = sender.clone();
|
let sender2 = sender.clone();
|
||||||
move || {
|
move || {
|
||||||
let (rx_curr, callback_curr) = build_comms("battery current callback send failed");
|
let (rx_curr, callback_curr) = build_comms("battery current callback send failed");
|
||||||
let (rx_charge_now, callback_charge_now) = build_comms("battery charge now callback send failed");
|
let (rx_charge_now, callback_charge_now) =
|
||||||
let (rx_charge_full, callback_charge_full) = build_comms("battery charge full callback send failed");
|
build_comms("battery charge now callback send failed");
|
||||||
let (rx_charge_power, callback_charge_power) = build_comms("battery charge power callback send failed");
|
let (rx_charge_full, callback_charge_full) =
|
||||||
|
build_comms("battery charge full callback send failed");
|
||||||
|
let (rx_charge_power, callback_charge_power) =
|
||||||
|
build_comms("battery charge power callback send failed");
|
||||||
|
|
||||||
let (rx_path, callback_path) = build_comms("general get path (periodical) send failed");
|
let (rx_path, callback_path) = build_comms("general get path (periodical) send failed");
|
||||||
|
|
||||||
let sender_locked = sender2
|
let sender_locked = sender2.lock().unwrap();
|
||||||
.lock()
|
let curr = wait_for_response(
|
||||||
.unwrap();
|
&*sender_locked,
|
||||||
let curr = wait_for_response(&*sender_locked, rx_curr,
|
rx_curr,
|
||||||
ApiMessage::Battery(super::handler::BatteryMessage::ReadCurrentNow(callback_curr)), "battery current");
|
ApiMessage::Battery(super::handler::BatteryMessage::ReadCurrentNow(
|
||||||
let charge_now = wait_for_response(&*sender_locked, rx_charge_now,
|
callback_curr,
|
||||||
ApiMessage::Battery(super::handler::BatteryMessage::ReadChargeNow(callback_charge_now)), "battery charge now");
|
)),
|
||||||
let charge_full = wait_for_response(&*sender_locked, rx_charge_full,
|
"battery current",
|
||||||
ApiMessage::Battery(super::handler::BatteryMessage::ReadChargeFull(callback_charge_full)), "battery charge full");
|
);
|
||||||
let charge_power = wait_for_response(&*sender_locked, rx_charge_power,
|
let charge_now = wait_for_response(
|
||||||
ApiMessage::Battery(super::handler::BatteryMessage::ReadChargePower(callback_charge_power)), "battery charge power");
|
&*sender_locked,
|
||||||
|
rx_charge_now,
|
||||||
|
ApiMessage::Battery(super::handler::BatteryMessage::ReadChargeNow(
|
||||||
|
callback_charge_now,
|
||||||
|
)),
|
||||||
|
"battery charge now",
|
||||||
|
);
|
||||||
|
let charge_full = wait_for_response(
|
||||||
|
&*sender_locked,
|
||||||
|
rx_charge_full,
|
||||||
|
ApiMessage::Battery(super::handler::BatteryMessage::ReadChargeFull(
|
||||||
|
callback_charge_full,
|
||||||
|
)),
|
||||||
|
"battery charge full",
|
||||||
|
);
|
||||||
|
let charge_power = wait_for_response(
|
||||||
|
&*sender_locked,
|
||||||
|
rx_charge_power,
|
||||||
|
ApiMessage::Battery(super::handler::BatteryMessage::ReadChargePower(
|
||||||
|
callback_charge_power,
|
||||||
|
)),
|
||||||
|
"battery charge power",
|
||||||
|
);
|
||||||
|
|
||||||
let settings_path = wait_for_response(&*sender_locked, rx_path,
|
let settings_path = wait_for_response(
|
||||||
ApiMessage::General(GeneralMessage::GetPath(callback_path)), "general get path");
|
&*sender_locked,
|
||||||
|
rx_path,
|
||||||
|
ApiMessage::General(GeneralMessage::GetPath(callback_path)),
|
||||||
|
"general get path",
|
||||||
|
);
|
||||||
vec![
|
vec![
|
||||||
super::utility::map_optional(curr),
|
super::utility::map_optional(curr),
|
||||||
super::utility::map_optional(charge_now),
|
super::utility::map_optional(charge_now),
|
||||||
super::utility::map_optional(charge_full),
|
super::utility::map_optional(charge_full),
|
||||||
super::utility::map_optional(charge_power),
|
super::utility::map_optional(charge_power),
|
||||||
|
|
||||||
super::utility::map_optional(settings_path.to_str()),
|
super::utility::map_optional(settings_path.to_str()),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -411,13 +455,20 @@ pub fn get_periodicals(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_comms<'a, T: Send + 'a>(msg: &'static str) -> (mpsc::Receiver<T>, Box<dyn FnOnce(T) + Send + 'a>) {
|
fn build_comms<'a, T: Send + 'a>(
|
||||||
|
msg: &'static str,
|
||||||
|
) -> (mpsc::Receiver<T>, Box<dyn FnOnce(T) + Send + 'a>) {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
let callback = move |t: T| tx.send(t).expect(msg);
|
let callback = move |t: T| tx.send(t).expect(msg);
|
||||||
(rx, Box::new(callback))
|
(rx, Box::new(callback))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_for_response<T>(sender: &Sender<ApiMessage>, rx: mpsc::Receiver<T>, api_msg: ApiMessage, op: &str) -> T {
|
fn wait_for_response<T>(
|
||||||
|
sender: &Sender<ApiMessage>,
|
||||||
|
rx: mpsc::Receiver<T>,
|
||||||
|
api_msg: ApiMessage,
|
||||||
|
op: &str,
|
||||||
|
) -> T {
|
||||||
sender.send(api_msg).expect(&format!("{} send failed", op));
|
sender.send(api_msg).expect(&format!("{} send failed", op));
|
||||||
rx.recv().expect(&format!("{} callback recv failed", op))
|
rx.recv().expect(&format!("{} callback recv failed", op))
|
||||||
}
|
}
|
||||||
|
@ -429,8 +480,10 @@ pub fn get_all_variants(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
let sender2 = sender.clone();
|
let sender2 = sender.clone();
|
||||||
move || {
|
move || {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
let callback =
|
let callback = move |variants: Vec<super::VariantInfo>| {
|
||||||
move |variants: Vec<super::VariantInfo>| tx.send(variants).expect("get_all_variants callback send failed");
|
tx.send(variants)
|
||||||
|
.expect("get_all_variants callback send failed")
|
||||||
|
};
|
||||||
sender2
|
sender2
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -438,7 +491,9 @@ pub fn get_all_variants(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
Box::new(callback),
|
Box::new(callback),
|
||||||
)))
|
)))
|
||||||
.expect("get_all_variants send failed");
|
.expect("get_all_variants send failed");
|
||||||
rx.recv().expect("get_all_variants callback recv failed")
|
let mut results = rx.recv().expect("get_all_variants callback recv failed");
|
||||||
|
results.sort_by_key(|info| info.id_num); // sort by variant id
|
||||||
|
results
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
super::async_utils::AsyncIshGetter {
|
super::async_utils::AsyncIshGetter {
|
||||||
|
@ -446,7 +501,10 @@ pub fn get_all_variants(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
trans_getter: |result| {
|
trans_getter: |result| {
|
||||||
let mut output = Vec::with_capacity(result.len());
|
let mut output = Vec::with_capacity(result.len());
|
||||||
for status in result.iter() {
|
for status in result.iter() {
|
||||||
output.push(Primitive::Json(serde_json::to_string(status).expect("Failed to serialize variant info to JSON")));
|
output.push(Primitive::Json(
|
||||||
|
serde_json::to_string(status)
|
||||||
|
.expect("Failed to serialize variant info to JSON"),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
output
|
output
|
||||||
},
|
},
|
||||||
|
@ -460,8 +518,10 @@ pub fn get_current_variant(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
let sender2 = sender.clone();
|
let sender2 = sender.clone();
|
||||||
move || {
|
move || {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
let callback =
|
let callback = move |variant: super::VariantInfo| {
|
||||||
move |variant: super::VariantInfo| tx.send(variant).expect("get_all_variants callback send failed");
|
tx.send(variant)
|
||||||
|
.expect("get_all_variants callback send failed")
|
||||||
|
};
|
||||||
sender2
|
sender2
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
@ -475,7 +535,9 @@ pub fn get_current_variant(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
super::async_utils::AsyncIshGetter {
|
super::async_utils::AsyncIshGetter {
|
||||||
set_get: getter,
|
set_get: getter,
|
||||||
trans_getter: |result| {
|
trans_getter: |result| {
|
||||||
vec![Primitive::Json(serde_json::to_string(&result).expect("Failed to serialize variant info to JSON"))]
|
vec![Primitive::Json(
|
||||||
|
serde_json::to_string(&result).expect("Failed to serialize variant info to JSON"),
|
||||||
|
)]
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,10 @@ impl BatteryMessage {
|
||||||
|
|
||||||
/// Message instructs the driver to modify settings
|
/// Message instructs the driver to modify settings
|
||||||
fn is_modify(&self) -> bool {
|
fn is_modify(&self) -> bool {
|
||||||
matches!(self, Self::SetChargeRate(_) | Self::SetChargeMode(_) | Self::SetChargeLimit(_))
|
matches!(
|
||||||
|
self,
|
||||||
|
Self::SetChargeRate(_) | Self::SetChargeMode(_) | Self::SetChargeLimit(_)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,7 +234,10 @@ pub enum GeneralMessage {
|
||||||
GetPath(Callback<std::path::PathBuf>),
|
GetPath(Callback<std::path::PathBuf>),
|
||||||
GetCurrentVariant(Callback<super::VariantInfo>),
|
GetCurrentVariant(Callback<super::VariantInfo>),
|
||||||
GetAllVariants(Callback<Vec<super::VariantInfo>>),
|
GetAllVariants(Callback<Vec<super::VariantInfo>>),
|
||||||
AddVariant(crate::persist::SettingsJson, Callback<Vec<super::VariantInfo>>),
|
AddVariant(
|
||||||
|
crate::persist::SettingsJson,
|
||||||
|
Callback<Vec<super::VariantInfo>>,
|
||||||
|
),
|
||||||
ApplyNow,
|
ApplyNow,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,11 +254,14 @@ impl GeneralMessage {
|
||||||
Self::AddVariant(variant, cb) => match settings.add_variant(variant) {
|
Self::AddVariant(variant, cb) => match settings.add_variant(variant) {
|
||||||
Ok(variants) => cb(variants),
|
Ok(variants) => cb(variants),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
print_errors("GeneralMessage::AddVariant => TGeneral::add_variant", vec![e]);
|
print_errors(
|
||||||
|
"GeneralMessage::AddVariant => TGeneral::add_variant",
|
||||||
|
vec![e],
|
||||||
|
);
|
||||||
cb(Vec::with_capacity(0))
|
cb(Vec::with_capacity(0))
|
||||||
},
|
}
|
||||||
},
|
},
|
||||||
Self::ApplyNow => {},
|
Self::ApplyNow => {}
|
||||||
}
|
}
|
||||||
dirty
|
dirty
|
||||||
}
|
}
|
||||||
|
@ -300,13 +309,21 @@ impl ApiMessageHandler {
|
||||||
// save
|
// save
|
||||||
log::debug!("api_worker is saving...");
|
log::debug!("api_worker is saving...");
|
||||||
let is_persistent = *settings.general.persistent();
|
let is_persistent = *settings.general.persistent();
|
||||||
let save_path =
|
let save_path = crate::utility::settings_dir().join(settings.general.get_path());
|
||||||
crate::utility::settings_dir().join(settings.general.get_path());
|
|
||||||
if is_persistent {
|
if is_persistent {
|
||||||
let settings_clone = settings.json();
|
let settings_clone = settings.json();
|
||||||
let save_json: SettingsJson = settings_clone.into();
|
let save_json: SettingsJson = settings_clone.into();
|
||||||
if let Err(e) = crate::persist::FileJson::update_variant_or_create(&save_path, settings.general.get_app_id(), save_json, settings.general.get_name().to_owned()) {
|
if let Err(e) = crate::persist::FileJson::update_variant_or_create(
|
||||||
log::error!("Failed to create/update settings file {}: {}", save_path.display(), e);
|
&save_path,
|
||||||
|
settings.general.get_app_id(),
|
||||||
|
save_json,
|
||||||
|
settings.general.get_name().to_owned(),
|
||||||
|
) {
|
||||||
|
log::error!(
|
||||||
|
"Failed to create/update settings file {}: {}",
|
||||||
|
save_path.display(),
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
//unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings");
|
//unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings");
|
||||||
log::debug!("Saved settings to {}", save_path.display());
|
log::debug!("Saved settings to {}", save_path.display());
|
||||||
|
@ -393,8 +410,15 @@ impl ApiMessageHandler {
|
||||||
ApiMessage::LoadVariant(variant_id, variant_name) => {
|
ApiMessage::LoadVariant(variant_id, variant_name) => {
|
||||||
let path = settings.general.get_path();
|
let path = settings.general.get_path();
|
||||||
let app_id = settings.general.get_app_id();
|
let app_id = settings.general.get_app_id();
|
||||||
match settings.load_file(path.into(), app_id, settings.general.get_name().to_owned(), variant_id, variant_name, false) {
|
match settings.load_file(
|
||||||
Ok(success) => log::info!("Loaded settings file? {}", success),
|
path.into(),
|
||||||
|
app_id,
|
||||||
|
settings.general.get_name().to_owned(),
|
||||||
|
variant_id,
|
||||||
|
variant_name,
|
||||||
|
false,
|
||||||
|
) {
|
||||||
|
Ok(success) => log::info!("Loaded variant settings file? {}", success),
|
||||||
Err(e) => log::warn!("Load file err: {}", e),
|
Err(e) => log::warn!("Load file err: {}", e),
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
|
@ -414,7 +438,11 @@ impl ApiMessageHandler {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
ApiMessage::LoadSystemSettings => {
|
ApiMessage::LoadSystemSettings => {
|
||||||
settings.load_system_default(settings.general.get_name().to_owned(), settings.general.get_variant_id(), settings.general.get_variant_info().name);
|
settings.load_system_default(
|
||||||
|
settings.general.get_name().to_owned(),
|
||||||
|
settings.general.get_variant_id(),
|
||||||
|
settings.general.get_variant_info().name,
|
||||||
|
);
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
ApiMessage::GetLimits(cb) => {
|
ApiMessage::GetLimits(cb) => {
|
||||||
|
@ -434,13 +462,18 @@ impl ApiMessageHandler {
|
||||||
_ => settings.general.provider(),
|
_ => settings.general.provider(),
|
||||||
});
|
});
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
ApiMessage::UploadCurrentVariant(steam_id, steam_username) => {
|
ApiMessage::UploadCurrentVariant(steam_id, steam_username) => {
|
||||||
//TODO
|
//TODO
|
||||||
let steam_app_id = settings.general.get_app_id();
|
let steam_app_id = settings.general.get_app_id();
|
||||||
super::web::upload_settings(steam_app_id, steam_id, steam_username, settings.json());
|
super::web::upload_settings(
|
||||||
|
steam_app_id,
|
||||||
|
steam_id,
|
||||||
|
steam_username,
|
||||||
|
settings.json(),
|
||||||
|
);
|
||||||
false
|
false
|
||||||
},
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,17 @@
|
||||||
use std::sync::{atomic::{AtomicU64, Ordering}, Arc};
|
use std::sync::{
|
||||||
|
atomic::{AtomicU64, Ordering},
|
||||||
|
Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use usdpl_back::AsyncCallable;
|
|
||||||
use usdpl_back::core::serdes::Primitive;
|
use usdpl_back::core::serdes::Primitive;
|
||||||
|
use usdpl_back::AsyncCallable;
|
||||||
|
|
||||||
use limits_core::json::DeveloperMessage;
|
use limits_core::json::DeveloperMessage;
|
||||||
|
|
||||||
use crate::MESSAGE_SEEN_ID_FILE;
|
|
||||||
use crate::utility::settings_dir;
|
use crate::utility::settings_dir;
|
||||||
|
use crate::MESSAGE_SEEN_ID_FILE;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct ApiMessage {
|
pub struct ApiMessage {
|
||||||
|
@ -34,7 +37,10 @@ impl std::convert::From<DeveloperMessage> for ApiMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_dev_messages() -> Vec<ApiMessage> {
|
fn get_dev_messages() -> Vec<ApiMessage> {
|
||||||
crate::settings::get_dev_messages().drain(..).map(|msg| ApiMessage::from(msg)).collect()
|
crate::settings::get_dev_messages()
|
||||||
|
.drain(..)
|
||||||
|
.map(|msg| ApiMessage::from(msg))
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MessageHandler {
|
pub struct MessageHandler {
|
||||||
|
@ -43,8 +49,12 @@ pub struct MessageHandler {
|
||||||
|
|
||||||
impl MessageHandler {
|
impl MessageHandler {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let last_seen_id = if let Ok(last_seen_id_bytes) = std::fs::read(settings_dir().join(MESSAGE_SEEN_ID_FILE)) {
|
let last_seen_id = if let Ok(last_seen_id_bytes) =
|
||||||
if last_seen_id_bytes.len() >= 8 /* bytes in u64 */ {
|
std::fs::read(settings_dir().join(MESSAGE_SEEN_ID_FILE))
|
||||||
|
{
|
||||||
|
if last_seen_id_bytes.len() >= 8
|
||||||
|
/* bytes in u64 */
|
||||||
|
{
|
||||||
u64::from_le_bytes([
|
u64::from_le_bytes([
|
||||||
last_seen_id_bytes[0],
|
last_seen_id_bytes[0],
|
||||||
last_seen_id_bytes[1],
|
last_seen_id_bytes[1],
|
||||||
|
@ -73,7 +83,7 @@ impl MessageHandler {
|
||||||
},
|
},
|
||||||
AsyncMessageDismisser {
|
AsyncMessageDismisser {
|
||||||
seen: self.seen.clone(),
|
seen: self.seen.clone(),
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,8 +93,17 @@ pub struct AsyncMessageGetter {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsyncMessageGetter {
|
impl AsyncMessageGetter {
|
||||||
fn remove_before_id(id: u64, messages: impl Iterator<Item=ApiMessage>) -> impl Iterator<Item=ApiMessage> {
|
fn remove_before_id(
|
||||||
messages.skip_while(move |msg| if let Some(msg_id) = msg.id { msg_id <= id } else { true })
|
id: u64,
|
||||||
|
messages: impl Iterator<Item = ApiMessage>,
|
||||||
|
) -> impl Iterator<Item = ApiMessage> {
|
||||||
|
messages.skip_while(move |msg| {
|
||||||
|
if let Some(msg_id) = msg.id {
|
||||||
|
msg_id <= id
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,12 +14,17 @@ pub fn search_by_app_id() -> impl AsyncCallable {
|
||||||
let req_url = format!("{}/api/setting/by_app_id/{}", BASE_URL, steam_app_id);
|
let req_url = format!("{}/api/setting/by_app_id/{}", BASE_URL, steam_app_id);
|
||||||
match ureq::get(&req_url).call() {
|
match ureq::get(&req_url).call() {
|
||||||
Ok(response) => {
|
Ok(response) => {
|
||||||
let json_res: std::io::Result<Vec<community_settings_core::v1::Metadata>> = response.into_json();
|
let json_res: std::io::Result<Vec<community_settings_core::v1::Metadata>> =
|
||||||
|
response.into_json();
|
||||||
match json_res {
|
match json_res {
|
||||||
Ok(search_results) => {
|
Ok(search_results) => {
|
||||||
// search results may be quite large, so let's do the JSON string conversion in the background (blocking) thread
|
// search results may be quite large, so let's do the JSON string conversion in the background (blocking) thread
|
||||||
match serde_json::to_string(&search_results) {
|
match serde_json::to_string(&search_results) {
|
||||||
Err(e) => log::error!("Cannot convert search results from `{}` to JSON: {}", req_url, e),
|
Err(e) => log::error!(
|
||||||
|
"Cannot convert search results from `{}` to JSON: {}",
|
||||||
|
req_url,
|
||||||
|
e
|
||||||
|
),
|
||||||
Ok(s) => return s,
|
Ok(s) => return s,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,41 +51,58 @@ pub fn search_by_app_id() -> impl AsyncCallable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn web_config_to_settings_json(meta: community_settings_core::v1::Metadata) -> crate::persist::SettingsJson {
|
fn web_config_to_settings_json(
|
||||||
|
meta: community_settings_core::v1::Metadata,
|
||||||
|
) -> crate::persist::SettingsJson {
|
||||||
crate::persist::SettingsJson {
|
crate::persist::SettingsJson {
|
||||||
version: crate::persist::LATEST_VERSION,
|
version: crate::persist::LATEST_VERSION,
|
||||||
name: meta.name,
|
name: meta.name,
|
||||||
variant: u64::MAX, // TODO maybe change this to use the 64 low bits of id (u64::MAX will cause it to generate a new id when added to file variant map
|
variant: u64::MAX, // TODO maybe change this to use the 64 low bits of id (u64::MAX will cause it to generate a new id when added to file variant map
|
||||||
persistent: true,
|
persistent: true,
|
||||||
cpus: meta.config.cpus.into_iter().map(|cpu| crate::persist::CpuJson {
|
cpus: meta
|
||||||
online: cpu.online,
|
.config
|
||||||
clock_limits: cpu.clock_limits.map(|lim| crate::persist::MinMaxJson {
|
.cpus
|
||||||
min: lim.min,
|
.into_iter()
|
||||||
max: lim.max,
|
.map(|cpu| crate::persist::CpuJson {
|
||||||
}),
|
online: cpu.online,
|
||||||
governor: cpu.governor,
|
clock_limits: cpu.clock_limits.map(|lim| crate::persist::MinMaxJson {
|
||||||
root: None,
|
min: lim.min,
|
||||||
}).collect(),
|
max: lim.max,
|
||||||
|
}),
|
||||||
|
governor: cpu.governor,
|
||||||
|
root: None,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
gpu: crate::persist::GpuJson {
|
gpu: crate::persist::GpuJson {
|
||||||
fast_ppt: meta.config.gpu.fast_ppt,
|
fast_ppt: meta.config.gpu.fast_ppt,
|
||||||
slow_ppt: meta.config.gpu.slow_ppt,
|
slow_ppt: meta.config.gpu.slow_ppt,
|
||||||
tdp: meta.config.gpu.tdp,
|
tdp: meta.config.gpu.tdp,
|
||||||
tdp_boost: meta.config.gpu.tdp_boost,
|
tdp_boost: meta.config.gpu.tdp_boost,
|
||||||
clock_limits: meta.config.gpu.clock_limits.map(|lim| crate::persist::MinMaxJson {
|
clock_limits: meta
|
||||||
min: lim.min,
|
.config
|
||||||
max: lim.max,
|
.gpu
|
||||||
}),
|
.clock_limits
|
||||||
|
.map(|lim| crate::persist::MinMaxJson {
|
||||||
|
min: lim.min,
|
||||||
|
max: lim.max,
|
||||||
|
}),
|
||||||
memory_clock: meta.config.gpu.memory_clock,
|
memory_clock: meta.config.gpu.memory_clock,
|
||||||
root: None,
|
root: None,
|
||||||
},
|
},
|
||||||
battery: crate::persist::BatteryJson {
|
battery: crate::persist::BatteryJson {
|
||||||
charge_rate: meta.config.battery.charge_rate,
|
charge_rate: meta.config.battery.charge_rate,
|
||||||
charge_mode: meta.config.battery.charge_mode,
|
charge_mode: meta.config.battery.charge_mode,
|
||||||
events: meta.config.battery.events.into_iter().map(|be| crate::persist::BatteryEventJson {
|
events: meta
|
||||||
charge_rate: be.charge_rate,
|
.config
|
||||||
charge_mode: be.charge_mode,
|
.battery
|
||||||
trigger: be.trigger,
|
.events
|
||||||
}).collect(),
|
.into_iter()
|
||||||
|
.map(|be| crate::persist::BatteryEventJson {
|
||||||
|
charge_rate: be.charge_rate,
|
||||||
|
charge_mode: be.charge_mode,
|
||||||
|
trigger: be.trigger,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
root: None,
|
root: None,
|
||||||
},
|
},
|
||||||
provider: Some(crate::persist::DriverJson::AutoDetect),
|
provider: Some(crate::persist::DriverJson::AutoDetect),
|
||||||
|
@ -89,20 +111,33 @@ fn web_config_to_settings_json(meta: community_settings_core::v1::Metadata) -> c
|
||||||
|
|
||||||
fn download_config(id: u128) -> std::io::Result<community_settings_core::v1::Metadata> {
|
fn download_config(id: u128) -> std::io::Result<community_settings_core::v1::Metadata> {
|
||||||
let req_url = format!("{}/api/setting/by_id/{}", BASE_URL, id);
|
let req_url = format!("{}/api/setting/by_id/{}", BASE_URL, id);
|
||||||
let response = ureq::get(&req_url).call()
|
let response = ureq::get(&req_url).call().map_err(|e| {
|
||||||
.map_err(|e| {
|
log::warn!("GET to {} failed: {}", req_url, e);
|
||||||
log::warn!("GET to {} failed: {}", req_url, e);
|
std::io::Error::new(std::io::ErrorKind::ConnectionAborted, e)
|
||||||
std::io::Error::new(std::io::ErrorKind::ConnectionAborted, e)
|
})?;
|
||||||
})?;
|
|
||||||
response.into_json()
|
response.into_json()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn upload_settings(id: u64, user_id: String, username: String, settings: crate::persist::SettingsJson) {
|
pub fn upload_settings(
|
||||||
log::info!("Uploading settings {} by {} ({})", settings.name, username, user_id);
|
id: u64,
|
||||||
|
user_id: String,
|
||||||
|
username: String,
|
||||||
|
settings: crate::persist::SettingsJson,
|
||||||
|
) {
|
||||||
|
log::info!(
|
||||||
|
"Uploading settings {} by {} ({})",
|
||||||
|
settings.name,
|
||||||
|
username,
|
||||||
|
user_id
|
||||||
|
);
|
||||||
let user_id: u64 = match user_id.parse() {
|
let user_id: u64 = match user_id.parse() {
|
||||||
Ok(id) => id,
|
Ok(id) => id,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to parse `{}` as u64: {} (aborted upload_settings very early)", user_id, e);
|
log::error!(
|
||||||
|
"Failed to parse `{}` as u64: {} (aborted upload_settings very early)",
|
||||||
|
user_id,
|
||||||
|
e
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -112,7 +147,12 @@ pub fn upload_settings(id: u64, user_id: String, username: String, settings: cra
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn settings_to_web_config(app_id: u32, user_id: u64, username: String, settings: crate::persist::SettingsJson) -> community_settings_core::v1::Metadata {
|
fn settings_to_web_config(
|
||||||
|
app_id: u32,
|
||||||
|
user_id: u64,
|
||||||
|
username: String,
|
||||||
|
settings: crate::persist::SettingsJson,
|
||||||
|
) -> community_settings_core::v1::Metadata {
|
||||||
community_settings_core::v1::Metadata {
|
community_settings_core::v1::Metadata {
|
||||||
name: settings.name,
|
name: settings.name,
|
||||||
steam_app_id: app_id,
|
steam_app_id: app_id,
|
||||||
|
@ -121,33 +161,46 @@ fn settings_to_web_config(app_id: u32, user_id: u64, username: String, settings:
|
||||||
tags: vec!["wip".to_owned()],
|
tags: vec!["wip".to_owned()],
|
||||||
id: "".to_owned(),
|
id: "".to_owned(),
|
||||||
config: community_settings_core::v1::Config {
|
config: community_settings_core::v1::Config {
|
||||||
cpus: settings.cpus.into_iter().map(|cpu| community_settings_core::v1::Cpu {
|
cpus: settings
|
||||||
online: cpu.online,
|
.cpus
|
||||||
clock_limits: cpu.clock_limits.map(|lim| community_settings_core::v1::MinMax {
|
.into_iter()
|
||||||
min: lim.min,
|
.map(|cpu| community_settings_core::v1::Cpu {
|
||||||
max: lim.max,
|
online: cpu.online,
|
||||||
}),
|
clock_limits: cpu
|
||||||
governor: cpu.governor,
|
.clock_limits
|
||||||
}).collect(),
|
.map(|lim| community_settings_core::v1::MinMax {
|
||||||
|
min: lim.min,
|
||||||
|
max: lim.max,
|
||||||
|
}),
|
||||||
|
governor: cpu.governor,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
gpu: community_settings_core::v1::Gpu {
|
gpu: community_settings_core::v1::Gpu {
|
||||||
fast_ppt: settings.gpu.fast_ppt,
|
fast_ppt: settings.gpu.fast_ppt,
|
||||||
slow_ppt: settings.gpu.slow_ppt,
|
slow_ppt: settings.gpu.slow_ppt,
|
||||||
tdp: settings.gpu.tdp,
|
tdp: settings.gpu.tdp,
|
||||||
tdp_boost: settings.gpu.tdp_boost,
|
tdp_boost: settings.gpu.tdp_boost,
|
||||||
clock_limits: settings.gpu.clock_limits.map(|lim| community_settings_core::v1::MinMax {
|
clock_limits: settings.gpu.clock_limits.map(|lim| {
|
||||||
min: lim.min,
|
community_settings_core::v1::MinMax {
|
||||||
max: lim.max,
|
min: lim.min,
|
||||||
|
max: lim.max,
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
memory_clock: settings.gpu.memory_clock,
|
memory_clock: settings.gpu.memory_clock,
|
||||||
},
|
},
|
||||||
battery: community_settings_core::v1::Battery {
|
battery: community_settings_core::v1::Battery {
|
||||||
charge_rate: settings.battery.charge_rate,
|
charge_rate: settings.battery.charge_rate,
|
||||||
charge_mode: settings.battery.charge_mode,
|
charge_mode: settings.battery.charge_mode,
|
||||||
events: settings.battery.events.into_iter().map(|batt_ev| community_settings_core::v1::BatteryEvent {
|
events: settings
|
||||||
trigger: batt_ev.trigger,
|
.battery
|
||||||
charge_rate: batt_ev.charge_rate,
|
.events
|
||||||
charge_mode: batt_ev.charge_mode,
|
.into_iter()
|
||||||
}).collect(),
|
.map(|batt_ev| community_settings_core::v1::BatteryEvent {
|
||||||
|
trigger: batt_ev.trigger,
|
||||||
|
charge_rate: batt_ev.charge_rate,
|
||||||
|
charge_mode: batt_ev.charge_mode,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -173,15 +226,20 @@ pub fn download_new_config(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
match download_config(id) {
|
match download_config(id) {
|
||||||
Ok(meta) => {
|
Ok(meta) => {
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
let callback =
|
let callback = move |values: Vec<super::VariantInfo>| {
|
||||||
move |values: Vec<super::VariantInfo>| tx.send(values).expect("download_new_config callback send failed");
|
tx.send(values)
|
||||||
|
.expect("download_new_config callback send failed")
|
||||||
|
};
|
||||||
sender2
|
sender2
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.send(ApiMessage::General(GeneralMessage::AddVariant(web_config_to_settings_json(meta), Box::new(callback))))
|
.send(ApiMessage::General(GeneralMessage::AddVariant(
|
||||||
|
web_config_to_settings_json(meta),
|
||||||
|
Box::new(callback),
|
||||||
|
)))
|
||||||
.expect("download_new_config send failed");
|
.expect("download_new_config send failed");
|
||||||
return rx.recv().expect("download_new_config callback recv failed");
|
return rx.recv().expect("download_new_config callback recv failed");
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Invalid response from download: {}", e);
|
log::error!("Invalid response from download: {}", e);
|
||||||
}
|
}
|
||||||
|
@ -194,7 +252,10 @@ pub fn download_new_config(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
if let Some(Primitive::String(id)) = params.get(0) {
|
if let Some(Primitive::String(id)) = params.get(0) {
|
||||||
match id.parse::<u128>() {
|
match id.parse::<u128>() {
|
||||||
Ok(id) => Ok(id),
|
Ok(id) => Ok(id),
|
||||||
Err(e) => Err(format!("download_new_config non-u128 string parameter 0: {} (got `{}`)", e, id))
|
Err(e) => Err(format!(
|
||||||
|
"download_new_config non-u128 string parameter 0: {} (got `{}`)",
|
||||||
|
e, id
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err("download_new_config missing/invalid parameter 0".to_owned())
|
Err("download_new_config missing/invalid parameter 0".to_owned())
|
||||||
|
@ -204,7 +265,10 @@ pub fn download_new_config(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
||||||
trans_getter: |result| {
|
trans_getter: |result| {
|
||||||
let mut output = Vec::with_capacity(result.len());
|
let mut output = Vec::with_capacity(result.len());
|
||||||
for status in result.iter() {
|
for status in result.iter() {
|
||||||
output.push(Primitive::Json(serde_json::to_string(status).expect("Failed to serialize variant info to JSON")));
|
output.push(Primitive::Json(
|
||||||
|
serde_json::to_string(status)
|
||||||
|
.expect("Failed to serialize variant info to JSON"),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
output
|
output
|
||||||
},
|
},
|
||||||
|
@ -238,8 +302,6 @@ pub fn upload_current_variant(sender: Sender<ApiMessage>) -> impl AsyncCallable
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
set_get: getter,
|
set_get: getter,
|
||||||
trans_getter: |result| {
|
trans_getter: |result| vec![result.into()],
|
||||||
vec![result.into()]
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,5 +10,4 @@ pub const DEFAULT_SETTINGS_VARIANT_NAME: &str = "Primary";
|
||||||
pub const LIMITS_FILE: &str = "limits_cache.ron";
|
pub const LIMITS_FILE: &str = "limits_cache.ron";
|
||||||
pub const LIMITS_OVERRIDE_FILE: &str = "limits_override.ron";
|
pub const LIMITS_OVERRIDE_FILE: &str = "limits_override.ron";
|
||||||
|
|
||||||
|
|
||||||
pub const MESSAGE_SEEN_ID_FILE: &str = "seen_message.bin";
|
pub const MESSAGE_SEEN_ID_FILE: &str = "seen_message.bin";
|
||||||
|
|
|
@ -76,14 +76,29 @@ fn main() -> Result<(), ()> {
|
||||||
|
|
||||||
let mut loaded_settings =
|
let mut loaded_settings =
|
||||||
persist::FileJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE))
|
persist::FileJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE))
|
||||||
.map(|mut file| file.variants.remove(&0)
|
.map(|mut file| {
|
||||||
.map(|settings| settings::Settings::from_json(DEFAULT_SETTINGS_NAME.into(), settings, DEFAULT_SETTINGS_FILE.into(), 0))
|
let mut keys: Vec<u64> = file.variants.keys().map(|x| *x).collect();
|
||||||
.unwrap_or_else(|| settings::Settings::system_default(
|
keys.sort();
|
||||||
DEFAULT_SETTINGS_FILE.into(),
|
keys.get(0)
|
||||||
0,
|
.and_then(|id| file.variants.remove(id))
|
||||||
DEFAULT_SETTINGS_NAME.into(),
|
.map(|settings| {
|
||||||
0,
|
settings::Settings::from_json(
|
||||||
DEFAULT_SETTINGS_VARIANT_NAME.into())))
|
DEFAULT_SETTINGS_NAME.into(),
|
||||||
|
settings,
|
||||||
|
DEFAULT_SETTINGS_FILE.into(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
settings::Settings::system_default(
|
||||||
|
DEFAULT_SETTINGS_FILE.into(),
|
||||||
|
0,
|
||||||
|
DEFAULT_SETTINGS_NAME.into(),
|
||||||
|
0,
|
||||||
|
DEFAULT_SETTINGS_VARIANT_NAME.into(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
settings::Settings::system_default(
|
settings::Settings::system_default(
|
||||||
DEFAULT_SETTINGS_FILE.into(),
|
DEFAULT_SETTINGS_FILE.into(),
|
||||||
|
@ -96,7 +111,8 @@ fn main() -> Result<(), ()> {
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
"Detected device automatically {:?}, using driver: {:?} (This can be overriden)",
|
"Detected device automatically {:?}, using driver: {:?} (This can be overriden)",
|
||||||
crate::settings::auto_detect_provider(), loaded_settings.cpus.provider()
|
crate::settings::auto_detect_provider(),
|
||||||
|
loaded_settings.cpus.provider()
|
||||||
);
|
);
|
||||||
|
|
||||||
log::debug!("Settings: {:?}", loaded_settings);
|
log::debug!("Settings: {:?}", loaded_settings);
|
||||||
|
@ -307,29 +323,26 @@ fn main() -> Result<(), ()> {
|
||||||
)
|
)
|
||||||
.register_async(
|
.register_async(
|
||||||
"GENERAL_get_periodicals",
|
"GENERAL_get_periodicals",
|
||||||
api::general::get_periodicals(api_sender.clone())
|
api::general::get_periodicals(api_sender.clone()),
|
||||||
)
|
)
|
||||||
.register_async(
|
.register_async(
|
||||||
"GENERAL_get_all_variants",
|
"GENERAL_get_all_variants",
|
||||||
api::general::get_all_variants(api_sender.clone())
|
api::general::get_all_variants(api_sender.clone()),
|
||||||
)
|
)
|
||||||
.register_async(
|
.register_async(
|
||||||
"GENERAL_get_current_variant",
|
"GENERAL_get_current_variant",
|
||||||
api::general::get_current_variant(api_sender.clone())
|
api::general::get_current_variant(api_sender.clone()),
|
||||||
)
|
)
|
||||||
.register_async("MESSAGE_get", message_getter)
|
.register_async("MESSAGE_get", message_getter)
|
||||||
.register_async("MESSAGE_dismiss", message_dismisser)
|
.register_async("MESSAGE_dismiss", message_dismisser)
|
||||||
.register_async(
|
.register_async("WEB_search_by_app", api::web::search_by_app_id())
|
||||||
"WEB_search_by_app",
|
|
||||||
api::web::search_by_app_id()
|
|
||||||
)
|
|
||||||
.register_async(
|
.register_async(
|
||||||
"WEB_download_new",
|
"WEB_download_new",
|
||||||
api::web::download_new_config(api_sender.clone())
|
api::web::download_new_config(api_sender.clone()),
|
||||||
)
|
)
|
||||||
.register_async(
|
.register_async(
|
||||||
"WEB_upload_new",
|
"WEB_upload_new",
|
||||||
api::web::upload_current_variant(api_sender.clone())
|
api::web::upload_current_variant(api_sender.clone()),
|
||||||
);
|
);
|
||||||
|
|
||||||
utility::ioperm_power_ec();
|
utility::ioperm_power_ec();
|
||||||
|
|
|
@ -22,7 +22,8 @@ impl FileJson {
|
||||||
std::fs::create_dir_all(parent).map_err(SerdeError::Io)?;
|
std::fs::create_dir_all(parent).map_err(SerdeError::Io)?;
|
||||||
}
|
}
|
||||||
let mut file = std::fs::File::create(path).map_err(SerdeError::Io)?;
|
let mut file = std::fs::File::create(path).map_err(SerdeError::Io)?;
|
||||||
ron::ser::to_writer_pretty(&mut file, &self, crate::utility::ron_pretty_config()).map_err(|e| SerdeError::Serde(e.into()))
|
ron::ser::to_writer_pretty(&mut file, &self, crate::utility::ron_pretty_config())
|
||||||
|
.map_err(|e| SerdeError::Serde(e.into()))
|
||||||
} else {
|
} else {
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
// remove settings file when persistence is turned off, to prevent it from be loaded next time.
|
// remove settings file when persistence is turned off, to prevent it from be loaded next time.
|
||||||
|
@ -39,37 +40,61 @@ impl FileJson {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_available_id(&self) -> u64 {
|
fn next_available_id(&self) -> u64 {
|
||||||
self.variants.keys()
|
self.variants.keys().max().map(|k| k + 1).unwrap_or(0)
|
||||||
.max()
|
|
||||||
.map(|k| k+1)
|
|
||||||
.unwrap_or(0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_variant_or_create<P: AsRef<std::path::Path>>(path: P, app_id: u64, mut setting: SettingsJson, given_name: String) -> Result<Self, SerdeError> {
|
pub fn update_variant_or_create<P: AsRef<std::path::Path>>(
|
||||||
if !setting.persistent {
|
path: P,
|
||||||
return Self::open(path)
|
app_id: u64,
|
||||||
}
|
mut setting: SettingsJson,
|
||||||
|
app_name: String,
|
||||||
|
) -> Result<(Self, SettingsJson), SerdeError> {
|
||||||
|
// returns (Self, updated/created variant id)
|
||||||
let path = path.as_ref();
|
let path = path.as_ref();
|
||||||
|
if !setting.persistent {
|
||||||
let file = if path.exists() {
|
|
||||||
let mut file = Self::open(path)?;
|
let mut file = Self::open(path)?;
|
||||||
|
|
||||||
|
if file.variants.contains_key(&setting.variant) {
|
||||||
|
file.variants.remove(&setting.variant);
|
||||||
|
file.save(path)?;
|
||||||
|
}
|
||||||
|
return Ok((file, setting));
|
||||||
|
}
|
||||||
|
|
||||||
|
let (file, variant_id) = if path.exists() {
|
||||||
|
let mut file = Self::open(path)?;
|
||||||
|
// Generate new (available) id if max
|
||||||
if setting.variant == u64::MAX {
|
if setting.variant == u64::MAX {
|
||||||
setting.variant = file.next_available_id();
|
setting.variant = file.next_available_id();
|
||||||
}
|
}
|
||||||
file.variants.insert(setting.variant, setting);
|
// Generate new name if empty
|
||||||
file
|
if setting.name.is_empty() {
|
||||||
|
setting.name = format!("Variant {}", setting.variant);
|
||||||
|
}
|
||||||
|
log::debug!("Inserting setting variant `{}` ({}) for app `{}` ({})", setting.name, setting.variant, file.name, app_id);
|
||||||
|
file.variants.insert(setting.variant, setting.clone());
|
||||||
|
(file, setting)
|
||||||
} else {
|
} else {
|
||||||
|
// Generate new id if max
|
||||||
|
if setting.variant == u64::MAX {
|
||||||
|
setting.variant = 1;
|
||||||
|
}
|
||||||
|
// Generate new name if empty
|
||||||
|
if setting.name.is_empty() {
|
||||||
|
setting.name = format!("Variant {}", setting.variant);
|
||||||
|
}
|
||||||
|
log::debug!("Creating new setting variant `{}` ({}) for app `{}` ({})", setting.name, setting.variant, app_name, app_id);
|
||||||
let mut setting_variants = HashMap::with_capacity(1);
|
let mut setting_variants = HashMap::with_capacity(1);
|
||||||
setting_variants.insert(setting.variant, setting);
|
setting_variants.insert(setting.variant, setting.clone());
|
||||||
Self {
|
(Self {
|
||||||
version: 0,
|
version: 0,
|
||||||
app_id: app_id,
|
app_id: app_id,
|
||||||
name: given_name,
|
name: app_name,
|
||||||
variants: setting_variants,
|
variants: setting_variants,
|
||||||
}
|
}, setting)
|
||||||
};
|
};
|
||||||
|
|
||||||
file.save(path)?;
|
file.save(path)?;
|
||||||
Ok(file)
|
Ok((file, variant_id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{BatteryJson, CpuJson, DriverJson, GpuJson};
|
use super::{BatteryJson, CpuJson, DriverJson, GpuJson};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct SettingsJson {
|
pub struct SettingsJson {
|
||||||
pub version: u64,
|
pub version: u64,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
|
@ -5,7 +5,7 @@ use regex::RegexBuilder;
|
||||||
use limits_core::json_v2::{BatteryLimitType, CpuLimitType, GpuLimitType, Limits};
|
use limits_core::json_v2::{BatteryLimitType, CpuLimitType, GpuLimitType, Limits};
|
||||||
|
|
||||||
use crate::persist::{DriverJson, SettingsJson};
|
use crate::persist::{DriverJson, SettingsJson};
|
||||||
use crate::settings::{Driver, General, TBattery, TCpus, TGeneral, TGpu, ProviderBuilder};
|
use crate::settings::{Driver, General, ProviderBuilder, TBattery, TCpus, TGeneral, TGpu};
|
||||||
|
|
||||||
fn get_limits() -> limits_core::json_v2::Base {
|
fn get_limits() -> limits_core::json_v2::Base {
|
||||||
let limits_path = super::utility::limits_path();
|
let limits_path = super::utility::limits_path();
|
||||||
|
@ -151,20 +151,22 @@ pub fn auto_detect0(
|
||||||
if let Some(settings) = &settings_opt {
|
if let Some(settings) = &settings_opt {
|
||||||
*general_driver.persistent() = true;
|
*general_driver.persistent() = true;
|
||||||
let cpu_driver: Box<dyn TCpus> = match relevant_limits.cpu.provider {
|
let cpu_driver: Box<dyn TCpus> = match relevant_limits.cpu.provider {
|
||||||
CpuLimitType::SteamDeck => {
|
CpuLimitType::SteamDeck => Box::new(
|
||||||
Box::new(crate::settings::steam_deck::Cpus::from_json_and_limits(
|
crate::settings::steam_deck::Cpus::from_json_and_limits(
|
||||||
settings.cpus.clone(),
|
settings.cpus.clone(),
|
||||||
settings.version,
|
settings.version,
|
||||||
relevant_limits.cpu.limits,
|
relevant_limits.cpu.limits,
|
||||||
).variant(super::super::steam_deck::Model::LCD))
|
)
|
||||||
}
|
.variant(super::super::steam_deck::Model::LCD),
|
||||||
CpuLimitType::SteamDeckOLED => {
|
),
|
||||||
Box::new(crate::settings::steam_deck::Cpus::from_json_and_limits(
|
CpuLimitType::SteamDeckOLED => Box::new(
|
||||||
|
crate::settings::steam_deck::Cpus::from_json_and_limits(
|
||||||
settings.cpus.clone(),
|
settings.cpus.clone(),
|
||||||
settings.version,
|
settings.version,
|
||||||
relevant_limits.cpu.limits,
|
relevant_limits.cpu.limits,
|
||||||
).variant(super::super::steam_deck::Model::OLED))
|
)
|
||||||
}
|
.variant(super::super::steam_deck::Model::OLED),
|
||||||
|
),
|
||||||
CpuLimitType::Generic => Box::new(crate::settings::generic::Cpus::<
|
CpuLimitType::Generic => Box::new(crate::settings::generic::Cpus::<
|
||||||
crate::settings::generic::Cpu,
|
crate::settings::generic::Cpu,
|
||||||
>::from_json_and_limits(
|
>::from_json_and_limits(
|
||||||
|
@ -172,20 +174,20 @@ pub fn auto_detect0(
|
||||||
settings.version,
|
settings.version,
|
||||||
relevant_limits.cpu.limits,
|
relevant_limits.cpu.limits,
|
||||||
)),
|
)),
|
||||||
CpuLimitType::GenericAMD => Box::new(
|
CpuLimitType::GenericAMD => {
|
||||||
crate::settings::generic_amd::Cpus::from_json_and_limits(
|
Box::new(crate::settings::generic_amd::Cpus::from_json_and_limits(
|
||||||
settings.cpus.clone(),
|
settings.cpus.clone(),
|
||||||
settings.version,
|
settings.version,
|
||||||
relevant_limits.cpu.limits,
|
relevant_limits.cpu.limits,
|
||||||
),
|
))
|
||||||
),
|
}
|
||||||
CpuLimitType::Unknown => {
|
CpuLimitType::Unknown => {
|
||||||
Box::new(crate::settings::unknown::Cpus::from_json_and_limits(
|
Box::new(crate::settings::unknown::Cpus::from_json_and_limits(
|
||||||
settings.cpus.clone(),
|
settings.cpus.clone(),
|
||||||
settings.version,
|
settings.version,
|
||||||
relevant_limits.cpu.limits,
|
relevant_limits.cpu.limits,
|
||||||
))
|
))
|
||||||
},
|
}
|
||||||
CpuLimitType::DevMode => {
|
CpuLimitType::DevMode => {
|
||||||
Box::new(crate::settings::dev_mode::Cpus::from_json_and_limits(
|
Box::new(crate::settings::dev_mode::Cpus::from_json_and_limits(
|
||||||
settings.cpus.clone(),
|
settings.cpus.clone(),
|
||||||
|
@ -196,20 +198,22 @@ pub fn auto_detect0(
|
||||||
};
|
};
|
||||||
|
|
||||||
let gpu_driver: Box<dyn TGpu> = match relevant_limits.gpu.provider {
|
let gpu_driver: Box<dyn TGpu> = match relevant_limits.gpu.provider {
|
||||||
GpuLimitType::SteamDeck => {
|
GpuLimitType::SteamDeck => Box::new(
|
||||||
Box::new(crate::settings::steam_deck::Gpu::from_json_and_limits(
|
crate::settings::steam_deck::Gpu::from_json_and_limits(
|
||||||
settings.gpu.clone(),
|
settings.gpu.clone(),
|
||||||
settings.version,
|
settings.version,
|
||||||
relevant_limits.gpu.limits,
|
relevant_limits.gpu.limits,
|
||||||
).variant(super::super::steam_deck::Model::LCD))
|
)
|
||||||
}
|
.variant(super::super::steam_deck::Model::LCD),
|
||||||
GpuLimitType::SteamDeckOLED => {
|
),
|
||||||
Box::new(crate::settings::steam_deck::Gpu::from_json_and_limits(
|
GpuLimitType::SteamDeckOLED => Box::new(
|
||||||
|
crate::settings::steam_deck::Gpu::from_json_and_limits(
|
||||||
settings.gpu.clone(),
|
settings.gpu.clone(),
|
||||||
settings.version,
|
settings.version,
|
||||||
relevant_limits.gpu.limits,
|
relevant_limits.gpu.limits,
|
||||||
).variant(super::super::steam_deck::Model::OLED))
|
)
|
||||||
}
|
.variant(super::super::steam_deck::Model::OLED),
|
||||||
|
),
|
||||||
GpuLimitType::Generic => {
|
GpuLimitType::Generic => {
|
||||||
Box::new(crate::settings::generic::Gpu::from_json_and_limits(
|
Box::new(crate::settings::generic::Gpu::from_json_and_limits(
|
||||||
settings.gpu.clone(),
|
settings.gpu.clone(),
|
||||||
|
@ -217,20 +221,20 @@ pub fn auto_detect0(
|
||||||
relevant_limits.gpu.limits,
|
relevant_limits.gpu.limits,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
GpuLimitType::GenericAMD => Box::new(
|
GpuLimitType::GenericAMD => {
|
||||||
crate::settings::generic_amd::Gpu::from_json_and_limits(
|
Box::new(crate::settings::generic_amd::Gpu::from_json_and_limits(
|
||||||
settings.gpu.clone(),
|
settings.gpu.clone(),
|
||||||
settings.version,
|
settings.version,
|
||||||
relevant_limits.gpu.limits,
|
relevant_limits.gpu.limits,
|
||||||
),
|
))
|
||||||
),
|
}
|
||||||
GpuLimitType::Unknown => {
|
GpuLimitType::Unknown => {
|
||||||
Box::new(crate::settings::unknown::Gpu::from_json_and_limits(
|
Box::new(crate::settings::unknown::Gpu::from_json_and_limits(
|
||||||
settings.gpu.clone(),
|
settings.gpu.clone(),
|
||||||
settings.version,
|
settings.version,
|
||||||
relevant_limits.gpu.limits,
|
relevant_limits.gpu.limits,
|
||||||
))
|
))
|
||||||
},
|
}
|
||||||
GpuLimitType::DevMode => {
|
GpuLimitType::DevMode => {
|
||||||
Box::new(crate::settings::dev_mode::Gpu::from_json_and_limits(
|
Box::new(crate::settings::dev_mode::Gpu::from_json_and_limits(
|
||||||
settings.gpu.clone(),
|
settings.gpu.clone(),
|
||||||
|
@ -240,34 +244,36 @@ pub fn auto_detect0(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let battery_driver: Box<dyn TBattery> = match relevant_limits.battery.provider {
|
let battery_driver: Box<dyn TBattery> = match relevant_limits.battery.provider {
|
||||||
BatteryLimitType::SteamDeck => {
|
BatteryLimitType::SteamDeck => Box::new(
|
||||||
Box::new(crate::settings::steam_deck::Battery::from_json_and_limits(
|
crate::settings::steam_deck::Battery::from_json_and_limits(
|
||||||
settings.battery.clone(),
|
settings.battery.clone(),
|
||||||
settings.version,
|
settings.version,
|
||||||
relevant_limits.battery.limits,
|
relevant_limits.battery.limits,
|
||||||
).variant(super::super::steam_deck::Model::LCD))
|
)
|
||||||
}
|
.variant(super::super::steam_deck::Model::LCD),
|
||||||
BatteryLimitType::SteamDeckOLED => {
|
|
||||||
Box::new(crate::settings::steam_deck::Battery::from_json_and_limits(
|
|
||||||
settings.battery.clone(),
|
|
||||||
settings.version,
|
|
||||||
relevant_limits.battery.limits,
|
|
||||||
).variant(super::super::steam_deck::Model::OLED))
|
|
||||||
}
|
|
||||||
BatteryLimitType::Generic => Box::new(
|
|
||||||
crate::settings::generic::Battery::from_json_and_limits(
|
|
||||||
settings.battery.clone(),
|
|
||||||
settings.version,
|
|
||||||
relevant_limits.battery.limits,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
BatteryLimitType::SteamDeckOLED => Box::new(
|
||||||
|
crate::settings::steam_deck::Battery::from_json_and_limits(
|
||||||
|
settings.battery.clone(),
|
||||||
|
settings.version,
|
||||||
|
relevant_limits.battery.limits,
|
||||||
|
)
|
||||||
|
.variant(super::super::steam_deck::Model::OLED),
|
||||||
|
),
|
||||||
|
BatteryLimitType::Generic => {
|
||||||
|
Box::new(crate::settings::generic::Battery::from_json_and_limits(
|
||||||
|
settings.battery.clone(),
|
||||||
|
settings.version,
|
||||||
|
relevant_limits.battery.limits,
|
||||||
|
))
|
||||||
|
}
|
||||||
BatteryLimitType::Unknown => {
|
BatteryLimitType::Unknown => {
|
||||||
Box::new(crate::settings::unknown::Battery::from_json_and_limits(
|
Box::new(crate::settings::unknown::Battery::from_json_and_limits(
|
||||||
settings.battery.clone(),
|
settings.battery.clone(),
|
||||||
settings.version,
|
settings.version,
|
||||||
relevant_limits.battery.limits,
|
relevant_limits.battery.limits,
|
||||||
))
|
))
|
||||||
},
|
}
|
||||||
BatteryLimitType::DevMode => {
|
BatteryLimitType::DevMode => {
|
||||||
Box::new(crate::settings::dev_mode::Battery::from_json_and_limits(
|
Box::new(crate::settings::dev_mode::Battery::from_json_and_limits(
|
||||||
settings.battery.clone(),
|
settings.battery.clone(),
|
||||||
|
@ -285,62 +291,78 @@ pub fn auto_detect0(
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
let cpu_driver: Box<dyn TCpus> = match relevant_limits.cpu.provider {
|
let cpu_driver: Box<dyn TCpus> = match relevant_limits.cpu.provider {
|
||||||
CpuLimitType::SteamDeck => {
|
CpuLimitType::SteamDeck => Box::new(
|
||||||
Box::new(crate::settings::steam_deck::Cpus::from_limits(relevant_limits.cpu.limits).variant(super::super::steam_deck::Model::LCD))
|
crate::settings::steam_deck::Cpus::from_limits(relevant_limits.cpu.limits)
|
||||||
}
|
.variant(super::super::steam_deck::Model::LCD),
|
||||||
CpuLimitType::SteamDeckOLED => {
|
),
|
||||||
Box::new(crate::settings::steam_deck::Cpus::from_limits(relevant_limits.cpu.limits).variant(super::super::steam_deck::Model::OLED))
|
CpuLimitType::SteamDeckOLED => Box::new(
|
||||||
}
|
crate::settings::steam_deck::Cpus::from_limits(relevant_limits.cpu.limits)
|
||||||
CpuLimitType::Generic => {
|
.variant(super::super::steam_deck::Model::OLED),
|
||||||
Box::new(crate::settings::generic::Cpus::<
|
),
|
||||||
crate::settings::generic::Cpu,
|
CpuLimitType::Generic => Box::new(crate::settings::generic::Cpus::<
|
||||||
>::from_limits(relevant_limits.cpu.limits))
|
crate::settings::generic::Cpu,
|
||||||
}
|
>::from_limits(
|
||||||
CpuLimitType::GenericAMD => {
|
relevant_limits.cpu.limits
|
||||||
Box::new(crate::settings::generic_amd::Cpus::from_limits(relevant_limits.cpu.limits))
|
)),
|
||||||
}
|
CpuLimitType::GenericAMD => Box::new(
|
||||||
CpuLimitType::Unknown => {
|
crate::settings::generic_amd::Cpus::from_limits(relevant_limits.cpu.limits),
|
||||||
Box::new(crate::settings::unknown::Cpus::from_limits(relevant_limits.cpu.limits))
|
),
|
||||||
}
|
CpuLimitType::Unknown => Box::new(crate::settings::unknown::Cpus::from_limits(
|
||||||
CpuLimitType::DevMode => {
|
relevant_limits.cpu.limits,
|
||||||
Box::new(crate::settings::dev_mode::Cpus::from_limits(relevant_limits.cpu.limits))
|
)),
|
||||||
}
|
CpuLimitType::DevMode => Box::new(
|
||||||
|
crate::settings::dev_mode::Cpus::from_limits(relevant_limits.cpu.limits),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
let gpu_driver: Box<dyn TGpu> = match relevant_limits.gpu.provider {
|
let gpu_driver: Box<dyn TGpu> = match relevant_limits.gpu.provider {
|
||||||
GpuLimitType::SteamDeck => {
|
GpuLimitType::SteamDeck => Box::new(
|
||||||
Box::new(crate::settings::steam_deck::Gpu::from_limits(relevant_limits.gpu.limits).variant(super::super::steam_deck::Model::LCD))
|
crate::settings::steam_deck::Gpu::from_limits(relevant_limits.gpu.limits)
|
||||||
}
|
.variant(super::super::steam_deck::Model::LCD),
|
||||||
GpuLimitType::SteamDeckOLED => {
|
),
|
||||||
Box::new(crate::settings::steam_deck::Gpu::from_limits(relevant_limits.gpu.limits).variant(super::super::steam_deck::Model::OLED))
|
GpuLimitType::SteamDeckOLED => Box::new(
|
||||||
}
|
crate::settings::steam_deck::Gpu::from_limits(relevant_limits.gpu.limits)
|
||||||
GpuLimitType::Generic => {
|
.variant(super::super::steam_deck::Model::OLED),
|
||||||
Box::new(crate::settings::generic::Gpu::from_limits(relevant_limits.gpu.limits))
|
),
|
||||||
}
|
GpuLimitType::Generic => Box::new(crate::settings::generic::Gpu::from_limits(
|
||||||
GpuLimitType::GenericAMD => {
|
relevant_limits.gpu.limits,
|
||||||
Box::new(crate::settings::generic_amd::Gpu::from_limits(relevant_limits.gpu.limits))
|
)),
|
||||||
}
|
GpuLimitType::GenericAMD => Box::new(
|
||||||
GpuLimitType::Unknown => {
|
crate::settings::generic_amd::Gpu::from_limits(relevant_limits.gpu.limits),
|
||||||
Box::new(crate::settings::unknown::Gpu::from_limits(relevant_limits.gpu.limits))
|
),
|
||||||
}
|
GpuLimitType::Unknown => Box::new(crate::settings::unknown::Gpu::from_limits(
|
||||||
GpuLimitType::DevMode => {
|
relevant_limits.gpu.limits,
|
||||||
Box::new(crate::settings::dev_mode::Gpu::from_limits(relevant_limits.gpu.limits))
|
)),
|
||||||
}
|
GpuLimitType::DevMode => Box::new(crate::settings::dev_mode::Gpu::from_limits(
|
||||||
|
relevant_limits.gpu.limits,
|
||||||
|
)),
|
||||||
};
|
};
|
||||||
let battery_driver: Box<dyn TBattery> = match relevant_limits.battery.provider {
|
let battery_driver: Box<dyn TBattery> = match relevant_limits.battery.provider {
|
||||||
BatteryLimitType::SteamDeck => {
|
BatteryLimitType::SteamDeck => Box::new(
|
||||||
Box::new(crate::settings::steam_deck::Battery::from_limits(relevant_limits.battery.limits).variant(super::super::steam_deck::Model::LCD))
|
crate::settings::steam_deck::Battery::from_limits(
|
||||||
}
|
relevant_limits.battery.limits,
|
||||||
BatteryLimitType::SteamDeckOLED => {
|
)
|
||||||
Box::new(crate::settings::steam_deck::Battery::from_limits(relevant_limits.battery.limits).variant(super::super::steam_deck::Model::OLED))
|
.variant(super::super::steam_deck::Model::LCD),
|
||||||
}
|
),
|
||||||
|
BatteryLimitType::SteamDeckOLED => Box::new(
|
||||||
|
crate::settings::steam_deck::Battery::from_limits(
|
||||||
|
relevant_limits.battery.limits,
|
||||||
|
)
|
||||||
|
.variant(super::super::steam_deck::Model::OLED),
|
||||||
|
),
|
||||||
BatteryLimitType::Generic => {
|
BatteryLimitType::Generic => {
|
||||||
Box::new(crate::settings::generic::Battery::from_limits(relevant_limits.battery.limits))
|
Box::new(crate::settings::generic::Battery::from_limits(
|
||||||
|
relevant_limits.battery.limits,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
BatteryLimitType::Unknown => {
|
BatteryLimitType::Unknown => {
|
||||||
Box::new(crate::settings::unknown::Battery::from_limits(relevant_limits.battery.limits))
|
Box::new(crate::settings::unknown::Battery::from_limits(
|
||||||
|
relevant_limits.battery.limits,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
BatteryLimitType::DevMode => {
|
BatteryLimitType::DevMode => {
|
||||||
Box::new(crate::settings::dev_mode::Battery::from_limits(relevant_limits.battery.limits))
|
Box::new(crate::settings::dev_mode::Battery::from_limits(
|
||||||
|
relevant_limits.battery.limits,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return Driver {
|
return Driver {
|
||||||
|
|
|
@ -93,14 +93,16 @@ pub fn get_limits_cached() -> Base {
|
||||||
fn save_base(new_base: &Base, path: impl AsRef<std::path::Path>) {
|
fn save_base(new_base: &Base, path: impl AsRef<std::path::Path>) {
|
||||||
let limits_path = path.as_ref();
|
let limits_path = path.as_ref();
|
||||||
match std::fs::File::create(&limits_path) {
|
match std::fs::File::create(&limits_path) {
|
||||||
Ok(f) => match ron::ser::to_writer_pretty(f, &new_base, crate::utility::ron_pretty_config()) {
|
Ok(f) => {
|
||||||
Ok(_) => log::info!("Successfully saved new limits to {}", limits_path.display()),
|
match ron::ser::to_writer_pretty(f, &new_base, crate::utility::ron_pretty_config()) {
|
||||||
Err(e) => log::error!(
|
Ok(_) => log::info!("Successfully saved new limits to {}", limits_path.display()),
|
||||||
"Failed to save limits json to file `{}`: {}",
|
Err(e) => log::error!(
|
||||||
limits_path.display(),
|
"Failed to save limits json to file `{}`: {}",
|
||||||
e
|
limits_path.display(),
|
||||||
),
|
e
|
||||||
},
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
Err(e) => log::error!("Cannot create {}: {}", limits_path.display(), e),
|
Err(e) => log::error!("Cannot create {}: {}", limits_path.display(), e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use limits_core::json::{DeveloperMessage, Base};
|
use limits_core::json::{Base, DeveloperMessage};
|
||||||
|
|
||||||
pub fn limits_path() -> std::path::PathBuf {
|
pub fn limits_path() -> std::path::PathBuf {
|
||||||
crate::utility::settings_dir().join(crate::consts::LIMITS_FILE)
|
crate::utility::settings_dir().join(crate::consts::LIMITS_FILE)
|
||||||
|
|
|
@ -3,8 +3,8 @@ use std::convert::Into;
|
||||||
use limits_core::json_v2::GenericBatteryLimit;
|
use limits_core::json_v2::GenericBatteryLimit;
|
||||||
|
|
||||||
use crate::persist::BatteryJson;
|
use crate::persist::BatteryJson;
|
||||||
use crate::settings::{TBattery, ProviderBuilder};
|
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
|
use crate::settings::{ProviderBuilder, TBattery};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Battery {
|
pub struct Battery {
|
||||||
|
@ -32,7 +32,11 @@ impl Into<BatteryJson> for Battery {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
||||||
fn from_json_and_limits(persist: BatteryJson, version: u64, limits: GenericBatteryLimit) -> Self {
|
fn from_json_and_limits(
|
||||||
|
persist: BatteryJson,
|
||||||
|
version: u64,
|
||||||
|
limits: GenericBatteryLimit,
|
||||||
|
) -> Self {
|
||||||
Battery {
|
Battery {
|
||||||
persist,
|
persist,
|
||||||
version,
|
version,
|
||||||
|
@ -43,7 +47,12 @@ impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
||||||
|
|
||||||
fn from_limits(limits: GenericBatteryLimit) -> Self {
|
fn from_limits(limits: GenericBatteryLimit) -> Self {
|
||||||
Battery {
|
Battery {
|
||||||
persist: BatteryJson { charge_rate: None, charge_mode: None, events: vec![], root: None },
|
persist: BatteryJson {
|
||||||
|
charge_rate: None,
|
||||||
|
charge_mode: None,
|
||||||
|
events: vec![],
|
||||||
|
root: None,
|
||||||
|
},
|
||||||
version: 0,
|
version: 0,
|
||||||
limits,
|
limits,
|
||||||
charge_limit: None,
|
charge_limit: None,
|
||||||
|
@ -71,10 +80,16 @@ impl TBattery for Battery {
|
||||||
fn limits(&self) -> crate::api::BatteryLimits {
|
fn limits(&self) -> crate::api::BatteryLimits {
|
||||||
log::debug!("dev_mode_Battery::limits(self) -> {{...}}");
|
log::debug!("dev_mode_Battery::limits(self) -> {{...}}");
|
||||||
crate::api::BatteryLimits {
|
crate::api::BatteryLimits {
|
||||||
charge_current: self.limits.charge_rate.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(11), max: lim.max.unwrap_or(1111) }),
|
charge_current: self.limits.charge_rate.map(|lim| crate::api::RangeLimit {
|
||||||
|
min: lim.min.unwrap_or(11),
|
||||||
|
max: lim.max.unwrap_or(1111),
|
||||||
|
}),
|
||||||
charge_current_step: 10,
|
charge_current_step: 10,
|
||||||
charge_modes: self.limits.charge_modes.clone(),
|
charge_modes: self.limits.charge_modes.clone(),
|
||||||
charge_limit: self.limits.charge_limit.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(2.0), max: lim.max.unwrap_or(98.0) }),
|
charge_limit: self.limits.charge_limit.map(|lim| crate::api::RangeLimit {
|
||||||
|
min: lim.min.unwrap_or(2.0),
|
||||||
|
max: lim.max.unwrap_or(98.0),
|
||||||
|
}),
|
||||||
charge_limit_step: 1.0,
|
charge_limit_step: 1.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -90,7 +105,10 @@ impl TBattery for Battery {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_charge_rate(&self) -> Option<u64> {
|
fn get_charge_rate(&self) -> Option<u64> {
|
||||||
log::debug!("dev_mode_Battery::get_charge_rate(self) -> {:?}", self.persist.charge_rate);
|
log::debug!(
|
||||||
|
"dev_mode_Battery::get_charge_rate(self) -> {:?}",
|
||||||
|
self.persist.charge_rate
|
||||||
|
);
|
||||||
self.persist.charge_rate
|
self.persist.charge_rate
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,7 +118,10 @@ impl TBattery for Battery {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_charge_mode(&self) -> Option<String> {
|
fn get_charge_mode(&self) -> Option<String> {
|
||||||
log::debug!("dev_mode_Battery::get_charge_mode(self) -> {:?}", self.persist.charge_mode);
|
log::debug!(
|
||||||
|
"dev_mode_Battery::get_charge_mode(self) -> {:?}",
|
||||||
|
self.persist.charge_mode
|
||||||
|
);
|
||||||
self.persist.charge_mode.clone()
|
self.persist.charge_mode.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +156,10 @@ impl TBattery for Battery {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_charge_limit(&self) -> Option<f64> {
|
fn get_charge_limit(&self) -> Option<f64> {
|
||||||
log::debug!("dev_mode_Battery::get_charge_limit(self) -> {:?}", self.charge_limit);
|
log::debug!(
|
||||||
|
"dev_mode_Battery::get_charge_limit(self) -> {:?}",
|
||||||
|
self.charge_limit
|
||||||
|
);
|
||||||
self.charge_limit
|
self.charge_limit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
|
|
||||||
use limits_core::json_v2::{GenericCpusLimit, GenericCpuLimit};
|
use limits_core::json_v2::{GenericCpuLimit, GenericCpusLimit};
|
||||||
|
|
||||||
use crate::persist::CpuJson;
|
use crate::persist::CpuJson;
|
||||||
use crate::settings::MinMax;
|
use crate::settings::MinMax;
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
use crate::settings::{TCpu, TCpus, ProviderBuilder};
|
use crate::settings::{ProviderBuilder, TCpu, TCpus};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Cpus {
|
pub struct Cpus {
|
||||||
|
@ -40,13 +40,22 @@ impl OnResume for Cpus {
|
||||||
impl crate::settings::OnPowerEvent for Cpus {}
|
impl crate::settings::OnPowerEvent for Cpus {}
|
||||||
|
|
||||||
impl ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
impl ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
||||||
fn from_json_and_limits(persistent: Vec<CpuJson>, version: u64, limits: GenericCpusLimit) -> Self {
|
fn from_json_and_limits(
|
||||||
|
persistent: Vec<CpuJson>,
|
||||||
|
version: u64,
|
||||||
|
limits: GenericCpusLimit,
|
||||||
|
) -> Self {
|
||||||
let mut cpus = Vec::with_capacity(persistent.len());
|
let mut cpus = Vec::with_capacity(persistent.len());
|
||||||
for (i, cpu) in persistent.iter().enumerate() {
|
for (i, cpu) in persistent.iter().enumerate() {
|
||||||
cpus.push(Cpu::from_json_and_limits(cpu.to_owned(), version, i, limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_else(|| {
|
cpus.push(Cpu::from_json_and_limits(
|
||||||
log::warn!("No cpu limit for index {}, using default", i);
|
cpu.to_owned(),
|
||||||
Default::default()
|
version,
|
||||||
})));
|
i,
|
||||||
|
limits.cpus.get(i).map(|x| x.to_owned()).unwrap_or_else(|| {
|
||||||
|
log::warn!("No cpu limit for index {}, using default", i);
|
||||||
|
Default::default()
|
||||||
|
}),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
let smt_guess = crate::settings::util::guess_smt(&persistent);
|
let smt_guess = crate::settings::util::guess_smt(&persistent);
|
||||||
Self {
|
Self {
|
||||||
|
@ -78,7 +87,12 @@ impl TCpus for Cpus {
|
||||||
cpus: self.cpus.iter().map(|x| x.limits()).collect(),
|
cpus: self.cpus.iter().map(|x| x.limits()).collect(),
|
||||||
count: self.cpus.len(),
|
count: self.cpus.len(),
|
||||||
smt_capable: true,
|
smt_capable: true,
|
||||||
governors: vec!["this".to_owned(), "is".to_owned(), "dev".to_owned(), "mode".to_owned()],
|
governors: vec![
|
||||||
|
"this".to_owned(),
|
||||||
|
"is".to_owned(),
|
||||||
|
"dev".to_owned(),
|
||||||
|
"mode".to_owned(),
|
||||||
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,8 +144,16 @@ impl std::fmt::Debug for Cpu {
|
||||||
|
|
||||||
impl Cpu {
|
impl Cpu {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_json_and_limits(other: CpuJson, version: u64, i: usize, limits: GenericCpuLimit) -> Self {
|
pub fn from_json_and_limits(
|
||||||
let clock_limits = other.clock_limits.clone().map(|lim| MinMax { min: lim.min, max: lim.max });
|
other: CpuJson,
|
||||||
|
version: u64,
|
||||||
|
i: usize,
|
||||||
|
limits: GenericCpuLimit,
|
||||||
|
) -> Self {
|
||||||
|
let clock_limits = other.clock_limits.clone().map(|lim| MinMax {
|
||||||
|
min: lim.min,
|
||||||
|
max: lim.max,
|
||||||
|
});
|
||||||
match version {
|
match version {
|
||||||
0 => Self {
|
0 => Self {
|
||||||
persist: other,
|
persist: other,
|
||||||
|
@ -153,7 +175,12 @@ impl Cpu {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_limits(i: usize, limits: GenericCpuLimit) -> Self {
|
pub fn from_limits(i: usize, limits: GenericCpuLimit) -> Self {
|
||||||
Self {
|
Self {
|
||||||
persist: CpuJson { online: true, clock_limits: None, governor: "".to_owned(), root: None },
|
persist: CpuJson {
|
||||||
|
online: true,
|
||||||
|
clock_limits: None,
|
||||||
|
governor: "".to_owned(),
|
||||||
|
root: None,
|
||||||
|
},
|
||||||
version: 0,
|
version: 0,
|
||||||
index: i,
|
index: i,
|
||||||
limits,
|
limits,
|
||||||
|
@ -163,10 +190,21 @@ impl Cpu {
|
||||||
|
|
||||||
fn limits(&self) -> crate::api::CpuLimits {
|
fn limits(&self) -> crate::api::CpuLimits {
|
||||||
crate::api::CpuLimits {
|
crate::api::CpuLimits {
|
||||||
clock_min_limits: self.limits.clock_min.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(1100), max: lim.max.unwrap_or(6900) }),
|
clock_min_limits: self.limits.clock_min.map(|lim| crate::api::RangeLimit {
|
||||||
clock_max_limits: self.limits.clock_max.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(4200), max: lim.max.unwrap_or(4300) }),
|
min: lim.min.unwrap_or(1100),
|
||||||
|
max: lim.max.unwrap_or(6900),
|
||||||
|
}),
|
||||||
|
clock_max_limits: self.limits.clock_max.map(|lim| crate::api::RangeLimit {
|
||||||
|
min: lim.min.unwrap_or(4200),
|
||||||
|
max: lim.max.unwrap_or(4300),
|
||||||
|
}),
|
||||||
clock_step: self.limits.clock_step.unwrap_or(11),
|
clock_step: self.limits.clock_step.unwrap_or(11),
|
||||||
governors: vec!["this".to_owned(), "is".to_owned(), "dev".to_owned(), "mode".to_owned()],
|
governors: vec![
|
||||||
|
"this".to_owned(),
|
||||||
|
"is".to_owned(),
|
||||||
|
"dev".to_owned(),
|
||||||
|
"mode".to_owned(),
|
||||||
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -211,11 +249,20 @@ impl TCpu for Cpu {
|
||||||
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) {
|
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) {
|
||||||
log::debug!("dev_mode_Cpu::clock_limits(self, {:?})", limits);
|
log::debug!("dev_mode_Cpu::clock_limits(self, {:?})", limits);
|
||||||
self.clock_limits = limits;
|
self.clock_limits = limits;
|
||||||
self.persist.clock_limits = self.clock_limits.clone().map(|lim| crate::persist::MinMaxJson { max: lim.max, min: lim.min });
|
self.persist.clock_limits =
|
||||||
|
self.clock_limits
|
||||||
|
.clone()
|
||||||
|
.map(|lim| crate::persist::MinMaxJson {
|
||||||
|
max: lim.max,
|
||||||
|
min: lim.min,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_clock_limits(&self) -> Option<&MinMax<u64>> {
|
fn get_clock_limits(&self) -> Option<&MinMax<u64>> {
|
||||||
log::debug!("dev_mode_Cpu::get_clock_limits(self) -> {:?}", self.clock_limits.as_ref());
|
log::debug!(
|
||||||
|
"dev_mode_Cpu::get_clock_limits(self) -> {:?}",
|
||||||
|
self.clock_limits.as_ref()
|
||||||
|
);
|
||||||
self.clock_limits.as_ref()
|
self.clock_limits.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@ use limits_core::json_v2::GenericGpuLimit;
|
||||||
|
|
||||||
use crate::persist::GpuJson;
|
use crate::persist::GpuJson;
|
||||||
use crate::settings::MinMax;
|
use crate::settings::MinMax;
|
||||||
use crate::settings::{TGpu, ProviderBuilder};
|
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
|
use crate::settings::{ProviderBuilder, TGpu};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Gpu {
|
pub struct Gpu {
|
||||||
|
@ -27,7 +27,10 @@ impl std::fmt::Debug for Gpu {
|
||||||
|
|
||||||
impl ProviderBuilder<GpuJson, GenericGpuLimit> for Gpu {
|
impl ProviderBuilder<GpuJson, GenericGpuLimit> for Gpu {
|
||||||
fn from_json_and_limits(persist: GpuJson, version: u64, limits: GenericGpuLimit) -> Self {
|
fn from_json_and_limits(persist: GpuJson, version: u64, limits: GenericGpuLimit) -> Self {
|
||||||
let clock_limits = persist.clock_limits.clone().map(|lim| MinMax { min: lim.min, max: lim.max });
|
let clock_limits = persist.clock_limits.clone().map(|lim| MinMax {
|
||||||
|
min: lim.min,
|
||||||
|
max: lim.max,
|
||||||
|
});
|
||||||
Self {
|
Self {
|
||||||
persist,
|
persist,
|
||||||
version,
|
version,
|
||||||
|
@ -83,16 +86,37 @@ impl TGpu for Gpu {
|
||||||
let ppt_divisor = self.limits.ppt_divisor.unwrap_or(1_000_000);
|
let ppt_divisor = self.limits.ppt_divisor.unwrap_or(1_000_000);
|
||||||
let tdp_divisor = self.limits.tdp_divisor.unwrap_or(1_000_000);
|
let tdp_divisor = self.limits.tdp_divisor.unwrap_or(1_000_000);
|
||||||
crate::api::GpuLimits {
|
crate::api::GpuLimits {
|
||||||
fast_ppt_limits: self.limits.fast_ppt.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(11_000_000) / ppt_divisor, max: lim.max.unwrap_or(42_000_000) / ppt_divisor }),
|
fast_ppt_limits: self.limits.fast_ppt.map(|lim| crate::api::RangeLimit {
|
||||||
slow_ppt_limits: self.limits.slow_ppt.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(7_000_000) / ppt_divisor, max: lim.max.unwrap_or(69_000_000) / ppt_divisor }),
|
min: lim.min.unwrap_or(11_000_000) / ppt_divisor,
|
||||||
|
max: lim.max.unwrap_or(42_000_000) / ppt_divisor,
|
||||||
|
}),
|
||||||
|
slow_ppt_limits: self.limits.slow_ppt.map(|lim| crate::api::RangeLimit {
|
||||||
|
min: lim.min.unwrap_or(7_000_000) / ppt_divisor,
|
||||||
|
max: lim.max.unwrap_or(69_000_000) / ppt_divisor,
|
||||||
|
}),
|
||||||
ppt_step: self.limits.ppt_step.unwrap_or(1),
|
ppt_step: self.limits.ppt_step.unwrap_or(1),
|
||||||
tdp_limits: self.limits.tdp.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(11_000_000) / tdp_divisor, max: lim.max.unwrap_or(69_000_000) / tdp_divisor }),
|
tdp_limits: self.limits.tdp.map(|lim| crate::api::RangeLimit {
|
||||||
tdp_boost_limits: self.limits.tdp_boost.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(7_000_000) / tdp_divisor, max: lim.max.unwrap_or(69_000_000) / tdp_divisor }),
|
min: lim.min.unwrap_or(11_000_000) / tdp_divisor,
|
||||||
|
max: lim.max.unwrap_or(69_000_000) / tdp_divisor,
|
||||||
|
}),
|
||||||
|
tdp_boost_limits: self.limits.tdp_boost.map(|lim| crate::api::RangeLimit {
|
||||||
|
min: lim.min.unwrap_or(7_000_000) / tdp_divisor,
|
||||||
|
max: lim.max.unwrap_or(69_000_000) / tdp_divisor,
|
||||||
|
}),
|
||||||
tdp_step: self.limits.tdp_step.unwrap_or(1),
|
tdp_step: self.limits.tdp_step.unwrap_or(1),
|
||||||
clock_min_limits: self.limits.clock_min.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(1100), max: lim.max.unwrap_or(6900) }),
|
clock_min_limits: self.limits.clock_min.map(|lim| crate::api::RangeLimit {
|
||||||
clock_max_limits: self.limits.clock_max.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(1100), max: lim.max.unwrap_or(4200) }),
|
min: lim.min.unwrap_or(1100),
|
||||||
|
max: lim.max.unwrap_or(6900),
|
||||||
|
}),
|
||||||
|
clock_max_limits: self.limits.clock_max.map(|lim| crate::api::RangeLimit {
|
||||||
|
min: lim.min.unwrap_or(1100),
|
||||||
|
max: lim.max.unwrap_or(4200),
|
||||||
|
}),
|
||||||
clock_step: self.limits.clock_step.unwrap_or(100),
|
clock_step: self.limits.clock_step.unwrap_or(100),
|
||||||
memory_control: self.limits.memory_clock.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(100), max: lim.max.unwrap_or(1100) }),
|
memory_control: self.limits.memory_clock.map(|lim| crate::api::RangeLimit {
|
||||||
|
min: lim.min.unwrap_or(100),
|
||||||
|
max: lim.max.unwrap_or(1100),
|
||||||
|
}),
|
||||||
memory_step: self.limits.memory_clock_step.unwrap_or(400),
|
memory_step: self.limits.memory_clock_step.unwrap_or(400),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,24 +127,41 @@ impl TGpu for Gpu {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ppt(&mut self, fast: Option<u64>, slow: Option<u64>) {
|
fn ppt(&mut self, fast: Option<u64>, slow: Option<u64>) {
|
||||||
log::debug!("dev_mode_Gpu::ppt(self, fast: {:?}, slow: {:?})", fast, slow);
|
log::debug!(
|
||||||
|
"dev_mode_Gpu::ppt(self, fast: {:?}, slow: {:?})",
|
||||||
|
fast,
|
||||||
|
slow
|
||||||
|
);
|
||||||
self.persist.fast_ppt = fast;
|
self.persist.fast_ppt = fast;
|
||||||
self.persist.slow_ppt = slow;
|
self.persist.slow_ppt = slow;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_ppt(&self) -> (Option<u64>, Option<u64>) {
|
fn get_ppt(&self) -> (Option<u64>, Option<u64>) {
|
||||||
log::debug!("dev_mode_Gpu::get_ppt(self) -> (fast: {:?}, slow: {:?})", self.persist.fast_ppt, self.persist.slow_ppt);
|
log::debug!(
|
||||||
|
"dev_mode_Gpu::get_ppt(self) -> (fast: {:?}, slow: {:?})",
|
||||||
|
self.persist.fast_ppt,
|
||||||
|
self.persist.slow_ppt
|
||||||
|
);
|
||||||
(self.persist.fast_ppt, self.persist.slow_ppt)
|
(self.persist.fast_ppt, self.persist.slow_ppt)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) {
|
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) {
|
||||||
log::debug!("dev_mode_Gpu::clock_limits(self, {:?})", limits);
|
log::debug!("dev_mode_Gpu::clock_limits(self, {:?})", limits);
|
||||||
self.clock_limits = limits;
|
self.clock_limits = limits;
|
||||||
self.persist.clock_limits = self.clock_limits.clone().map(|lim| crate::persist::MinMaxJson { max: lim.max, min: lim.min });
|
self.persist.clock_limits =
|
||||||
|
self.clock_limits
|
||||||
|
.clone()
|
||||||
|
.map(|lim| crate::persist::MinMaxJson {
|
||||||
|
max: lim.max,
|
||||||
|
min: lim.min,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_clock_limits(&self) -> Option<&MinMax<u64>> {
|
fn get_clock_limits(&self) -> Option<&MinMax<u64>> {
|
||||||
log::debug!("dev_mode_Gpu::get_clock_limits(self) -> {:?}", self.clock_limits.as_ref());
|
log::debug!(
|
||||||
|
"dev_mode_Gpu::get_clock_limits(self) -> {:?}",
|
||||||
|
self.clock_limits.as_ref()
|
||||||
|
);
|
||||||
self.clock_limits.as_ref()
|
self.clock_limits.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +171,10 @@ impl TGpu for Gpu {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_memory_clock(&self) -> Option<u64> {
|
fn get_memory_clock(&self) -> Option<u64> {
|
||||||
log::debug!("dev_mode_Gpu::memory_clock(self) -> {:?}", self.persist.memory_clock);
|
log::debug!(
|
||||||
|
"dev_mode_Gpu::memory_clock(self) -> {:?}",
|
||||||
|
self.persist.memory_clock
|
||||||
|
);
|
||||||
self.persist.memory_clock
|
self.persist.memory_clock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,15 @@ pub use gpu::Gpu;
|
||||||
fn _impl_checker() {
|
fn _impl_checker() {
|
||||||
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
||||||
|
|
||||||
impl_provider_builder::<Battery, crate::persist::BatteryJson, limits_core::json_v2::GenericBatteryLimit>();
|
impl_provider_builder::<
|
||||||
impl_provider_builder::<Cpus, Vec<crate::persist::CpuJson>, limits_core::json_v2::GenericCpusLimit>();
|
Battery,
|
||||||
|
crate::persist::BatteryJson,
|
||||||
|
limits_core::json_v2::GenericBatteryLimit,
|
||||||
|
>();
|
||||||
|
impl_provider_builder::<
|
||||||
|
Cpus,
|
||||||
|
Vec<crate::persist::CpuJson>,
|
||||||
|
limits_core::json_v2::GenericCpusLimit,
|
||||||
|
>();
|
||||||
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,13 @@ impl Driver {
|
||||||
auto_detect0(Some(settings), json_path, app_id, name, id_bup, name_bup)
|
auto_detect0(Some(settings), json_path, app_id, name, id_bup, name_bup)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn system_default(json_path: std::path::PathBuf, app_id: u64, name: String, variant_id: u64, variant_name: String) -> Self {
|
pub fn system_default(
|
||||||
|
json_path: std::path::PathBuf,
|
||||||
|
app_id: u64,
|
||||||
|
name: String,
|
||||||
|
variant_id: u64,
|
||||||
|
variant_name: String,
|
||||||
|
) -> Self {
|
||||||
auto_detect0(None, json_path, app_id, name, variant_id, variant_name)
|
auto_detect0(None, json_path, app_id, name, variant_id, variant_name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::path::PathBuf;
|
||||||
//use super::{Battery, Cpus, Gpu};
|
//use super::{Battery, Cpus, Gpu};
|
||||||
use super::{OnResume, OnSet, SettingError};
|
use super::{OnResume, OnSet, SettingError};
|
||||||
use super::{TBattery, TCpus, TGeneral, TGpu};
|
use super::{TBattery, TCpus, TGeneral, TGpu};
|
||||||
use crate::persist::{SettingsJson, FileJson};
|
use crate::persist::{FileJson, SettingsJson};
|
||||||
//use crate::utility::unwrap_lock;
|
//use crate::utility::unwrap_lock;
|
||||||
|
|
||||||
const LATEST_VERSION: u64 = 0;
|
const LATEST_VERSION: u64 = 0;
|
||||||
|
@ -103,11 +103,14 @@ impl TGeneral for General {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_variants(&self) -> Vec<crate::api::VariantInfo> {
|
fn get_variants(&self) -> Vec<crate::api::VariantInfo> {
|
||||||
if let Ok(file) = crate::persist::FileJson::open(self.get_path()) {
|
let json_path = crate::utility::settings_dir().join(self.get_path());
|
||||||
file.variants.into_iter()
|
if let Ok(file) = crate::persist::FileJson::open(json_path) {
|
||||||
|
file.variants
|
||||||
|
.into_iter()
|
||||||
.map(|(id, conf)| crate::api::VariantInfo {
|
.map(|(id, conf)| crate::api::VariantInfo {
|
||||||
id: id.to_string(),
|
id: id.to_string(),
|
||||||
name: conf.name,
|
name: conf.name,
|
||||||
|
id_num: id,
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
|
@ -115,25 +118,40 @@ impl TGeneral for General {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_variant(&self, variant: crate::persist::SettingsJson) -> Result<Vec<crate::api::VariantInfo>, SettingError> {
|
fn add_variant(
|
||||||
|
&self,
|
||||||
|
variant: crate::persist::SettingsJson,
|
||||||
|
) -> Result<Vec<crate::api::VariantInfo>, SettingError> {
|
||||||
let variant_name = variant.name.clone();
|
let variant_name = variant.name.clone();
|
||||||
crate::persist::FileJson::update_variant_or_create(self.get_path(), self.get_app_id(), variant, variant_name)
|
let json_path = crate::utility::settings_dir().join(self.get_path());
|
||||||
.map_err(|e| SettingError {
|
crate::persist::FileJson::update_variant_or_create(
|
||||||
msg: format!("failed to add variant: {}", e),
|
json_path,
|
||||||
setting: SettingVariant::General,
|
self.get_app_id(),
|
||||||
})
|
variant,
|
||||||
.map(|file| file.variants.into_iter()
|
variant_name,
|
||||||
|
)
|
||||||
|
.map_err(|e| SettingError {
|
||||||
|
msg: format!("failed to add variant: {}", e),
|
||||||
|
setting: SettingVariant::General,
|
||||||
|
})
|
||||||
|
.map(|file| {
|
||||||
|
file.0.variants
|
||||||
|
.into_iter()
|
||||||
.map(|(id, conf)| crate::api::VariantInfo {
|
.map(|(id, conf)| crate::api::VariantInfo {
|
||||||
id: id.to_string(),
|
id: id.to_string(),
|
||||||
name: conf.name,
|
name: conf.name,
|
||||||
|
id_num: id,
|
||||||
})
|
})
|
||||||
.collect())
|
.collect()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_variant_info(&self) -> crate::api::VariantInfo {
|
fn get_variant_info(&self) -> crate::api::VariantInfo {
|
||||||
|
log::debug!("Current variant `{}` ({})", self.variant_name, self.variant_id);
|
||||||
crate::api::VariantInfo {
|
crate::api::VariantInfo {
|
||||||
id: self.variant_id.to_string(),
|
id: self.variant_id.to_string(),
|
||||||
name: self.variant_name.clone(),
|
name: self.variant_name.clone(),
|
||||||
|
id_num: self.variant_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,8 +217,15 @@ impl Settings {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn system_default(json_path: PathBuf, app_id: u64, name: String, variant_id: u64, variant_name: String) -> Self {
|
pub fn system_default(
|
||||||
let driver = super::Driver::system_default(json_path, app_id, name, variant_id, variant_name);
|
json_path: PathBuf,
|
||||||
|
app_id: u64,
|
||||||
|
name: String,
|
||||||
|
variant_id: u64,
|
||||||
|
variant_name: String,
|
||||||
|
) -> Self {
|
||||||
|
let driver =
|
||||||
|
super::Driver::system_default(json_path, app_id, name, variant_id, variant_name);
|
||||||
Self {
|
Self {
|
||||||
general: driver.general,
|
general: driver.general,
|
||||||
cpus: driver.cpus,
|
cpus: driver.cpus,
|
||||||
|
@ -210,19 +235,47 @@ impl Settings {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_system_default(&mut self, name: String, variant_id: u64, variant_name: String) {
|
pub fn load_system_default(&mut self, name: String, variant_id: u64, variant_name: String) {
|
||||||
let driver = super::Driver::system_default(self.general.get_path().to_owned(), self.general.get_app_id(), name, variant_id, variant_name);
|
let driver = super::Driver::system_default(
|
||||||
|
self.general.get_path().to_owned(),
|
||||||
|
self.general.get_app_id(),
|
||||||
|
name,
|
||||||
|
variant_id,
|
||||||
|
variant_name,
|
||||||
|
);
|
||||||
self.cpus = driver.cpus;
|
self.cpus = driver.cpus;
|
||||||
self.gpu = driver.gpu;
|
self.gpu = driver.gpu;
|
||||||
self.battery = driver.battery;
|
self.battery = driver.battery;
|
||||||
self.general = driver.general;
|
self.general = driver.general;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_variant<'a>(settings_file: &'a FileJson, variant_id: u64, variant_name: String) -> Result<&'a SettingsJson, SettingError> {
|
pub fn get_variant<'a>(
|
||||||
|
settings_file: &'a FileJson,
|
||||||
|
variant_id: u64,
|
||||||
|
variant_name: String,
|
||||||
|
) -> Result<&'a SettingsJson, SettingError> {
|
||||||
if let Some(variant) = settings_file.variants.get(&variant_id) {
|
if let Some(variant) = settings_file.variants.get(&variant_id) {
|
||||||
Ok(variant)
|
Ok(variant)
|
||||||
|
} else if variant_id == 0 {
|
||||||
|
// special case: requesting primary variant for settings with non-persistent primary
|
||||||
|
let mut valid_ids: Vec<&u64> = settings_file.variants.keys().collect();
|
||||||
|
valid_ids.sort();
|
||||||
|
if let Some(id) = valid_ids.get(0) {
|
||||||
|
Ok(settings_file.variants.get(id).expect("variant id key magically disappeared"))
|
||||||
|
} else {
|
||||||
|
Err(SettingError {
|
||||||
|
msg: format!(
|
||||||
|
"Cannot get variant `{}` (id:{}) from empty settings file",
|
||||||
|
variant_name, variant_id
|
||||||
|
),
|
||||||
|
setting: SettingVariant::General,
|
||||||
|
})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(SettingError {
|
Err(SettingError {
|
||||||
msg: format!("Cannot get non-existent variant `{}` (id:{})", variant_name, variant_id),
|
msg: format!(
|
||||||
|
"Cannot get non-existent variant `{}` (id:{})",
|
||||||
|
variant_name, variant_id
|
||||||
|
),
|
||||||
setting: SettingVariant::General,
|
setting: SettingVariant::General,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -240,13 +293,8 @@ impl Settings {
|
||||||
let json_path = crate::utility::settings_dir().join(&filename);
|
let json_path = crate::utility::settings_dir().join(&filename);
|
||||||
if json_path.exists() {
|
if json_path.exists() {
|
||||||
if variant == u64::MAX {
|
if variant == u64::MAX {
|
||||||
*self.general.persistent() = true;
|
log::debug!("Creating new variant `{}` in existing settings file {}", variant_name, json_path.display());
|
||||||
let file_json = FileJson::update_variant_or_create(&json_path, app_id, self.json(), variant_name.clone()).map_err(|e| SettingError {
|
self.create_and_load_variant(&json_path, app_id, variant_name)?;
|
||||||
msg: format!("Failed to open settings {}: {}", json_path.display(), e),
|
|
||||||
setting: SettingVariant::General,
|
|
||||||
})?;
|
|
||||||
self.general.variant_id(file_json.variants.iter().find(|(_key, val)| val.name == variant_name).map(|(key, _val)| *key).expect("Setting variant was not added properly"));
|
|
||||||
self.general.variant_name(variant_name);
|
|
||||||
} else {
|
} else {
|
||||||
let file_json = FileJson::open(&json_path).map_err(|e| SettingError {
|
let file_json = FileJson::open(&json_path).map_err(|e| SettingError {
|
||||||
msg: format!("Failed to open settings {}: {}", json_path.display(), e),
|
msg: format!("Failed to open settings {}: {}", json_path.display(), e),
|
||||||
|
@ -261,31 +309,61 @@ impl Settings {
|
||||||
);
|
);
|
||||||
*self.general.persistent() = false;
|
*self.general.persistent() = false;
|
||||||
self.general.name(name);
|
self.general.name(name);
|
||||||
|
self.general.variant_name(settings_json.name.clone());
|
||||||
|
self.general.variant_id(settings_json.variant);
|
||||||
} else {
|
} else {
|
||||||
let x = super::Driver::init(name, settings_json, json_path.clone(), app_id);
|
let x = super::Driver::init(name, settings_json, json_path.clone(), app_id);
|
||||||
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;
|
self.general = x.general;
|
||||||
self.cpus = x.cpus;
|
self.cpus = x.cpus;
|
||||||
self.gpu = x.gpu;
|
self.gpu = x.gpu;
|
||||||
self.battery = x.battery;
|
self.battery = x.battery;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if system_defaults {
|
if system_defaults {
|
||||||
self.load_system_default(name, variant, variant_name);
|
self.load_system_default(name, variant, variant_name.clone());
|
||||||
} else {
|
} else {
|
||||||
self.general.name(name);
|
self.general.name(name);
|
||||||
self.general.variant_name(variant_name);
|
self.general.variant_name(variant_name.clone());
|
||||||
|
self.general.variant_id(variant);
|
||||||
}
|
}
|
||||||
*self.general.persistent() = false;
|
*self.general.persistent() = false;
|
||||||
|
if variant == u64::MAX {
|
||||||
|
log::debug!("Creating new variant `{}` in new settings file {}", variant_name, json_path.display());
|
||||||
|
self.create_and_load_variant(&json_path, app_id, variant_name)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*self.general.app_id() = app_id;
|
*self.general.app_id() = app_id;
|
||||||
self.general.path(filename);
|
self.general.path(filename);
|
||||||
self.general.variant_id(variant);
|
|
||||||
Ok(*self.general.persistent())
|
Ok(*self.general.persistent())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_and_load_variant(&mut self, json_path: &PathBuf, app_id: u64, variant_name: String) -> Result<(), SettingError> {
|
||||||
|
*self.general.persistent() = true;
|
||||||
|
self.general.variant_id(u64::MAX);
|
||||||
|
self.general.variant_name(variant_name.clone());
|
||||||
|
let (_file_json, new_variant) = FileJson::update_variant_or_create(
|
||||||
|
json_path,
|
||||||
|
app_id,
|
||||||
|
self.json(),
|
||||||
|
self.general.get_name().to_owned(),
|
||||||
|
)
|
||||||
|
.map_err(|e| SettingError {
|
||||||
|
msg: format!("Failed to open settings {}: {}", json_path.display(), e),
|
||||||
|
setting: SettingVariant::General,
|
||||||
|
})?;
|
||||||
|
self.general.variant_id(new_variant.variant);
|
||||||
|
self.general.variant_name(new_variant.name);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub fn load_file(&mut self, filename: PathBuf, name: String, system_defaults: bool) -> Result<bool, SettingError> {
|
pub fn load_file(&mut self, filename: PathBuf, name: String, system_defaults: bool) -> Result<bool, SettingError> {
|
||||||
let json_path = crate::utility::settings_dir().join(filename);
|
let json_path = crate::utility::settings_dir().join(filename);
|
||||||
|
|
|
@ -4,8 +4,8 @@ use limits_core::json_v2::GenericBatteryLimit;
|
||||||
use sysfuss::{SysEntity, SysEntityAttributesExt};
|
use sysfuss::{SysEntity, SysEntityAttributesExt};
|
||||||
|
|
||||||
use crate::persist::BatteryJson;
|
use crate::persist::BatteryJson;
|
||||||
use crate::settings::{TBattery, ProviderBuilder};
|
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
|
use crate::settings::{ProviderBuilder, TBattery};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Battery {
|
pub struct Battery {
|
||||||
|
@ -21,7 +21,10 @@ impl Into<BatteryJson> for Battery {
|
||||||
charge_rate: None,
|
charge_rate: None,
|
||||||
charge_mode: None,
|
charge_mode: None,
|
||||||
events: Vec::default(),
|
events: Vec::default(),
|
||||||
root: self.sysfs.root().and_then(|p| p.as_ref().to_str().map(|s| s.to_owned())),
|
root: self
|
||||||
|
.sysfs
|
||||||
|
.root()
|
||||||
|
.and_then(|p| p.as_ref().to_str().map(|s| s.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,16 +62,26 @@ impl Battery {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_design_voltage(&self) -> Option<f64> {
|
fn get_design_voltage(&self) -> Option<f64> {
|
||||||
match self.sysfs.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::VoltageMax) {
|
match self
|
||||||
Ok(x) => Some(x/1000000.0),
|
.sysfs
|
||||||
|
.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::VoltageMax)
|
||||||
|
{
|
||||||
|
Ok(x) => Some(x / 1000000.0),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::debug!("get_design_voltage voltage_max err: {}", e);
|
log::debug!("get_design_voltage voltage_max err: {}", e);
|
||||||
match sysfuss::SysEntityRawExt::attribute::<_, f64, _>(&self.sysfs, "voltage_min_design".to_owned()) { // Framework 13 AMD
|
match sysfuss::SysEntityRawExt::attribute::<_, f64, _>(
|
||||||
Ok(x) => Some(x/1000000.0),
|
&self.sysfs,
|
||||||
|
"voltage_min_design".to_owned(),
|
||||||
|
) {
|
||||||
|
// Framework 13 AMD
|
||||||
|
Ok(x) => Some(x / 1000000.0),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::debug!("get_design_voltage voltage_min_design err: {}", e);
|
log::debug!("get_design_voltage voltage_min_design err: {}", e);
|
||||||
match self.sysfs.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::VoltageMin) {
|
match self
|
||||||
Ok(x) => Some(x/1000000.0),
|
.sysfs
|
||||||
|
.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::VoltageMin)
|
||||||
|
{
|
||||||
|
Ok(x) => Some(x / 1000000.0),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::debug!("get_design_voltage voltage_min err: {}", e);
|
log::debug!("get_design_voltage voltage_min err: {}", e);
|
||||||
None
|
None
|
||||||
|
@ -90,7 +103,7 @@ impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
||||||
// TODO
|
// TODO
|
||||||
Self {
|
Self {
|
||||||
limits,
|
limits,
|
||||||
sysfs: Self::find_psu_sysfs(persistent.root)
|
sysfs: Self::find_psu_sysfs(persistent.root),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,8 +161,11 @@ impl TBattery for Battery {
|
||||||
|
|
||||||
fn read_charge_full(&self) -> Option<f64> {
|
fn read_charge_full(&self) -> Option<f64> {
|
||||||
if let Some(battery_voltage) = self.get_design_voltage() {
|
if let Some(battery_voltage) = self.get_design_voltage() {
|
||||||
match self.sysfs.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::ChargeFull) {
|
match self
|
||||||
Ok(x) => Some(x/1000000.0 * battery_voltage),
|
.sysfs
|
||||||
|
.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::ChargeFull)
|
||||||
|
{
|
||||||
|
Ok(x) => Some(x / 1000000.0 * battery_voltage),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("read_charge_full err: {}", e);
|
log::warn!("read_charge_full err: {}", e);
|
||||||
None
|
None
|
||||||
|
@ -162,8 +178,11 @@ impl TBattery for Battery {
|
||||||
|
|
||||||
fn read_charge_now(&self) -> Option<f64> {
|
fn read_charge_now(&self) -> Option<f64> {
|
||||||
if let Some(battery_voltage) = self.get_design_voltage() {
|
if let Some(battery_voltage) = self.get_design_voltage() {
|
||||||
match self.sysfs.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::ChargeNow) {
|
match self
|
||||||
Ok(x) => Some(x/1000000.0 * battery_voltage),
|
.sysfs
|
||||||
|
.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::ChargeNow)
|
||||||
|
{
|
||||||
|
Ok(x) => Some(x / 1000000.0 * battery_voltage),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("read_charge_now err: {}", e);
|
log::warn!("read_charge_now err: {}", e);
|
||||||
None
|
None
|
||||||
|
@ -176,8 +195,11 @@ impl TBattery for Battery {
|
||||||
|
|
||||||
fn read_charge_design(&self) -> Option<f64> {
|
fn read_charge_design(&self) -> Option<f64> {
|
||||||
if let Some(battery_voltage) = self.get_design_voltage() {
|
if let Some(battery_voltage) = self.get_design_voltage() {
|
||||||
match self.sysfs.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::ChargeFullDesign) {
|
match self
|
||||||
Ok(x) => Some(x/1000000.0 * battery_voltage),
|
.sysfs
|
||||||
|
.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::ChargeFullDesign)
|
||||||
|
{
|
||||||
|
Ok(x) => Some(x / 1000000.0 * battery_voltage),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("read_charge_design err: {}", e);
|
log::warn!("read_charge_design err: {}", e);
|
||||||
None
|
None
|
||||||
|
@ -189,8 +211,11 @@ impl TBattery for Battery {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_current_now(&self) -> Option<f64> {
|
fn read_current_now(&self) -> Option<f64> {
|
||||||
match self.sysfs.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::CurrentNow) {
|
match self
|
||||||
Ok(x) => Some(x/1000.0), // expects mA, reads uA
|
.sysfs
|
||||||
|
.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::CurrentNow)
|
||||||
|
{
|
||||||
|
Ok(x) => Some(x / 1000.0), // expects mA, reads uA
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("read_current_now err: {}", e);
|
log::warn!("read_current_now err: {}", e);
|
||||||
None
|
None
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
use std::convert::{AsMut, AsRef, Into};
|
use std::convert::{AsMut, AsRef, Into};
|
||||||
|
|
||||||
use limits_core::json_v2::{GenericCpusLimit, GenericCpuLimit};
|
use limits_core::json_v2::{GenericCpuLimit, GenericCpusLimit};
|
||||||
|
|
||||||
use super::FromGenericCpuInfo;
|
use super::FromGenericCpuInfo;
|
||||||
use crate::api::RangeLimit;
|
use crate::api::RangeLimit;
|
||||||
use crate::persist::CpuJson;
|
use crate::persist::CpuJson;
|
||||||
use crate::settings::{min_max_from_json, MinMax};
|
use crate::settings::{min_max_from_json, MinMax};
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
use crate::settings::{TCpu, TCpus, ProviderBuilder};
|
use crate::settings::{ProviderBuilder, TCpu, TCpus};
|
||||||
|
|
||||||
const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present";
|
const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present";
|
||||||
const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control";
|
const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control";
|
||||||
|
@ -89,8 +89,14 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> Cpus<C> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus<C> {
|
impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo>
|
||||||
fn from_json_and_limits(mut other: Vec<CpuJson>, version: u64, limits: GenericCpusLimit) -> Self {
|
ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus<C>
|
||||||
|
{
|
||||||
|
fn from_json_and_limits(
|
||||||
|
mut other: Vec<CpuJson>,
|
||||||
|
version: u64,
|
||||||
|
limits: GenericCpusLimit,
|
||||||
|
) -> Self {
|
||||||
let (_, can_smt) = Self::system_smt_capabilities();
|
let (_, can_smt) = Self::system_smt_capabilities();
|
||||||
let mut result = Vec::with_capacity(other.len());
|
let mut result = Vec::with_capacity(other.len());
|
||||||
let max_cpus = Self::cpu_count();
|
let max_cpus = Self::cpu_count();
|
||||||
|
@ -103,9 +109,12 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> ProviderBuilder<Vec
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let cpu_limit = limits.cpus.get(i)
|
let cpu_limit = limits
|
||||||
|
.cpus
|
||||||
|
.get(i)
|
||||||
.or_else(|| limits.cpus.get(0))
|
.or_else(|| limits.cpus.get(0))
|
||||||
.unwrap_or_else(|| &fallback_cpu_limit).clone();
|
.unwrap_or_else(|| &fallback_cpu_limit)
|
||||||
|
.clone();
|
||||||
let new_cpu = C::from_json_and_limits(cpu, version, i, cpu_limit);
|
let new_cpu = C::from_json_and_limits(cpu, version, i, cpu_limit);
|
||||||
result.push(new_cpu);
|
result.push(new_cpu);
|
||||||
}
|
}
|
||||||
|
@ -130,9 +139,12 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> ProviderBuilder<Vec
|
||||||
let mut new_cpus = Vec::with_capacity(cpu_count);
|
let mut new_cpus = Vec::with_capacity(cpu_count);
|
||||||
let fallback_cpu_limit = GenericCpuLimit::default();
|
let fallback_cpu_limit = GenericCpuLimit::default();
|
||||||
for i in 0..cpu_count {
|
for i in 0..cpu_count {
|
||||||
let cpu_limit = limits.cpus.get(i)
|
let cpu_limit = limits
|
||||||
|
.cpus
|
||||||
|
.get(i)
|
||||||
.or_else(|| limits.cpus.get(0))
|
.or_else(|| limits.cpus.get(0))
|
||||||
.unwrap_or_else(|| &fallback_cpu_limit).clone();
|
.unwrap_or_else(|| &fallback_cpu_limit)
|
||||||
|
.clone();
|
||||||
let new_cpu = C::from_limits(i, cpu_limit);
|
let new_cpu = C::from_limits(i, cpu_limit);
|
||||||
new_cpus.push(new_cpu);
|
new_cpus.push(new_cpu);
|
||||||
}
|
}
|
||||||
|
@ -221,7 +233,8 @@ pub struct Cpu {
|
||||||
impl Cpu {
|
impl Cpu {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn current_governor(index: usize) -> String {
|
fn current_governor(index: usize) -> String {
|
||||||
usdpl_back::api::files::read_single(cpu_governor_path(index)).unwrap_or_else(|_| "schedutil".to_owned())
|
usdpl_back::api::files::read_single(cpu_governor_path(index))
|
||||||
|
.unwrap_or_else(|_| "schedutil".to_owned())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,9 +5,9 @@ use sysfuss::{BasicEntityPath, SysEntity};
|
||||||
|
|
||||||
use crate::api::RangeLimit;
|
use crate::api::RangeLimit;
|
||||||
use crate::persist::GpuJson;
|
use crate::persist::GpuJson;
|
||||||
use crate::settings::{TGpu, ProviderBuilder};
|
|
||||||
use crate::settings::{min_max_from_json, MinMax};
|
use crate::settings::{min_max_from_json, MinMax};
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
|
use crate::settings::{ProviderBuilder, TGpu};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Gpu {
|
pub struct Gpu {
|
||||||
|
@ -38,15 +38,17 @@ impl Gpu {
|
||||||
fn find_card_sysfs(root: Option<impl AsRef<std::path::Path>>) -> BasicEntityPath {
|
fn find_card_sysfs(root: Option<impl AsRef<std::path::Path>>) -> BasicEntityPath {
|
||||||
let root = crate::settings::util::root_or_default_sysfs(root);
|
let root = crate::settings::util::root_or_default_sysfs(root);
|
||||||
match root.class("drm", crate::settings::util::always_satisfied) {
|
match root.class("drm", crate::settings::util::always_satisfied) {
|
||||||
Ok(mut iter) => {
|
Ok(mut iter) => iter.next().unwrap_or_else(|| {
|
||||||
iter.next()
|
log::error!(
|
||||||
.unwrap_or_else(|| {
|
"Failed to find generic gpu drm in sysfs (no results), using naive fallback"
|
||||||
log::error!("Failed to find generic gpu drm in sysfs (no results), using naive fallback");
|
);
|
||||||
BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0"))
|
BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0"))
|
||||||
})
|
}),
|
||||||
},
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to find generic gpu drm in sysfs ({}), using naive fallback", e);
|
log::error!(
|
||||||
|
"Failed to find generic gpu drm in sysfs ({}), using naive fallback",
|
||||||
|
e
|
||||||
|
);
|
||||||
BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0"))
|
BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +58,9 @@ impl Gpu {
|
||||||
impl ProviderBuilder<GpuJson, GenericGpuLimit> for Gpu {
|
impl ProviderBuilder<GpuJson, GenericGpuLimit> for Gpu {
|
||||||
fn from_json_and_limits(persistent: GpuJson, version: u64, limits: GenericGpuLimit) -> Self {
|
fn from_json_and_limits(persistent: GpuJson, version: u64, limits: GenericGpuLimit) -> Self {
|
||||||
let clock_lims = if limits.clock_min.is_some() && limits.clock_max.is_some() {
|
let clock_lims = if limits.clock_min.is_some() && limits.clock_max.is_some() {
|
||||||
persistent.clock_limits.map(|x| min_max_from_json(x, version))
|
persistent
|
||||||
|
.clock_limits
|
||||||
|
.map(|x| min_max_from_json(x, version))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -84,7 +88,7 @@ impl ProviderBuilder<GpuJson, GenericGpuLimit> for Gpu {
|
||||||
},
|
},
|
||||||
clock_limits: clock_lims,
|
clock_limits: clock_lims,
|
||||||
limits,
|
limits,
|
||||||
sysfs: Self::find_card_sysfs(persistent.root)
|
sysfs: Self::find_card_sysfs(persistent.root),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,7 +116,10 @@ impl Into<GpuJson> for Gpu {
|
||||||
tdp_boost: self.tdp_boost,
|
tdp_boost: self.tdp_boost,
|
||||||
clock_limits: self.clock_limits.map(|x| x.into()),
|
clock_limits: self.clock_limits.map(|x| x.into()),
|
||||||
memory_clock: None,
|
memory_clock: None,
|
||||||
root: self.sysfs.root().and_then(|p| p.as_ref().to_str().map(|s| s.to_owned()))
|
root: self
|
||||||
|
.sysfs
|
||||||
|
.root()
|
||||||
|
.and_then(|p| p.as_ref().to_str().map(|s| s.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -139,21 +146,29 @@ impl TGpu for Gpu {
|
||||||
.fast_ppt
|
.fast_ppt
|
||||||
.clone()
|
.clone()
|
||||||
.map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15)))
|
.map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15)))
|
||||||
.map(|mut x| if let Some(ppt_divisor) = self.limits.ppt_divisor {
|
.map(|mut x| {
|
||||||
x.min /= ppt_divisor;
|
if let Some(ppt_divisor) = self.limits.ppt_divisor {
|
||||||
x.max /= ppt_divisor;
|
x.min /= ppt_divisor;
|
||||||
x
|
x.max /= ppt_divisor;
|
||||||
} else {x}),
|
x
|
||||||
|
} else {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
}),
|
||||||
slow_ppt_limits: self
|
slow_ppt_limits: self
|
||||||
.limits
|
.limits
|
||||||
.slow_ppt
|
.slow_ppt
|
||||||
.clone()
|
.clone()
|
||||||
.map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15)))
|
.map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15)))
|
||||||
.map(|mut x| if let Some(ppt_divisor) = self.limits.ppt_divisor {
|
.map(|mut x| {
|
||||||
x.min /= ppt_divisor;
|
if let Some(ppt_divisor) = self.limits.ppt_divisor {
|
||||||
x.max /= ppt_divisor;
|
x.min /= ppt_divisor;
|
||||||
x
|
x.max /= ppt_divisor;
|
||||||
} else {x}),
|
x
|
||||||
|
} else {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
}),
|
||||||
ppt_step: self.limits.ppt_step.unwrap_or(1),
|
ppt_step: self.limits.ppt_step.unwrap_or(1),
|
||||||
tdp_limits: self
|
tdp_limits: self
|
||||||
.limits
|
.limits
|
||||||
|
@ -188,28 +203,56 @@ impl TGpu for Gpu {
|
||||||
|
|
||||||
fn ppt(&mut self, fast: Option<u64>, slow: Option<u64>) {
|
fn ppt(&mut self, fast: Option<u64>, slow: Option<u64>) {
|
||||||
if let Some(fast_lims) = &self.limits.fast_ppt {
|
if let Some(fast_lims) = &self.limits.fast_ppt {
|
||||||
self.fast_ppt = fast.map(|x| if let Some(ppt_divisor) = self.limits.ppt_divisor { x * ppt_divisor } else { x })
|
self.fast_ppt = fast
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
x.clamp(
|
if let Some(ppt_divisor) = self.limits.ppt_divisor {
|
||||||
fast_lims.min.unwrap_or(0),
|
x * ppt_divisor
|
||||||
fast_lims.max.unwrap_or(u64::MAX),
|
} else {
|
||||||
)
|
x
|
||||||
});
|
}
|
||||||
|
})
|
||||||
|
.map(|x| {
|
||||||
|
x.clamp(
|
||||||
|
fast_lims.min.unwrap_or(0),
|
||||||
|
fast_lims.max.unwrap_or(u64::MAX),
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if let Some(slow_lims) = &self.limits.slow_ppt {
|
if let Some(slow_lims) = &self.limits.slow_ppt {
|
||||||
self.slow_ppt = slow.map(|x| if let Some(ppt_divisor) = self.limits.ppt_divisor { x * ppt_divisor } else { x })
|
self.slow_ppt = slow
|
||||||
.map(|x| {
|
.map(|x| {
|
||||||
x.clamp(
|
if let Some(ppt_divisor) = self.limits.ppt_divisor {
|
||||||
slow_lims.min.unwrap_or(0),
|
x * ppt_divisor
|
||||||
slow_lims.max.unwrap_or(u64::MAX),
|
} else {
|
||||||
)
|
x
|
||||||
});
|
}
|
||||||
|
})
|
||||||
|
.map(|x| {
|
||||||
|
x.clamp(
|
||||||
|
slow_lims.min.unwrap_or(0),
|
||||||
|
slow_lims.max.unwrap_or(u64::MAX),
|
||||||
|
)
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_ppt(&self) -> (Option<u64>, Option<u64>) {
|
fn get_ppt(&self) -> (Option<u64>, Option<u64>) {
|
||||||
(self.fast_ppt.map(|x| if let Some(ppt_divisor) = self.limits.ppt_divisor { x / ppt_divisor } else { x }),
|
(
|
||||||
self.slow_ppt.map(|x| if let Some(ppt_divisor) = self.limits.ppt_divisor { x / ppt_divisor } else { x }))
|
self.fast_ppt.map(|x| {
|
||||||
|
if let Some(ppt_divisor) = self.limits.ppt_divisor {
|
||||||
|
x / ppt_divisor
|
||||||
|
} else {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
self.slow_ppt.map(|x| {
|
||||||
|
if let Some(ppt_divisor) = self.limits.ppt_divisor {
|
||||||
|
x / ppt_divisor
|
||||||
|
} else {
|
||||||
|
x
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) {
|
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) {
|
||||||
|
|
|
@ -11,7 +11,15 @@ pub use traits::FromGenericCpuInfo;
|
||||||
fn _impl_checker() {
|
fn _impl_checker() {
|
||||||
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
||||||
|
|
||||||
impl_provider_builder::<Battery, crate::persist::BatteryJson, limits_core::json_v2::GenericBatteryLimit>();
|
impl_provider_builder::<
|
||||||
impl_provider_builder::<Cpus<Cpu>, Vec<crate::persist::CpuJson>, limits_core::json_v2::GenericCpusLimit>();
|
Battery,
|
||||||
|
crate::persist::BatteryJson,
|
||||||
|
limits_core::json_v2::GenericBatteryLimit,
|
||||||
|
>();
|
||||||
|
impl_provider_builder::<
|
||||||
|
Cpus<Cpu>,
|
||||||
|
Vec<crate::persist::CpuJson>,
|
||||||
|
limits_core::json_v2::GenericCpusLimit,
|
||||||
|
>();
|
||||||
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::persist::CpuJson;
|
||||||
use crate::settings::generic::{Cpu as GenericCpu, Cpus as GenericCpus, FromGenericCpuInfo};
|
use crate::settings::generic::{Cpu as GenericCpu, Cpus as GenericCpus, FromGenericCpuInfo};
|
||||||
use crate::settings::MinMax;
|
use crate::settings::MinMax;
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
use crate::settings::{TCpu, TCpus, ProviderBuilder};
|
use crate::settings::{ProviderBuilder, TCpu, TCpus};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Cpus {
|
pub struct Cpus {
|
||||||
|
|
|
@ -4,10 +4,14 @@ use std::sync::Mutex;
|
||||||
use crate::persist::GpuJson;
|
use crate::persist::GpuJson;
|
||||||
use crate::settings::generic::Gpu as GenericGpu;
|
use crate::settings::generic::Gpu as GenericGpu;
|
||||||
use crate::settings::MinMax;
|
use crate::settings::MinMax;
|
||||||
use crate::settings::{TGpu, ProviderBuilder};
|
|
||||||
use crate::settings::{OnResume, OnSet, SettingError, SettingVariant};
|
use crate::settings::{OnResume, OnSet, SettingError, SettingVariant};
|
||||||
|
use crate::settings::{ProviderBuilder, TGpu};
|
||||||
|
|
||||||
fn msg_or_err<D: std::fmt::Display, E: std::fmt::Display>(output: &mut String, msg: &str, result: Result<D, E>) {
|
fn msg_or_err<D: std::fmt::Display, E: std::fmt::Display>(
|
||||||
|
output: &mut String,
|
||||||
|
msg: &str,
|
||||||
|
result: Result<D, E>,
|
||||||
|
) {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
match result {
|
match result {
|
||||||
Ok(val) => writeln!(output, "{}: {}", msg, val).unwrap(),
|
Ok(val) => writeln!(output, "{}: {}", msg, val).unwrap(),
|
||||||
|
@ -16,20 +20,41 @@ fn msg_or_err<D: std::fmt::Display, E: std::fmt::Display>(output: &mut String, m
|
||||||
}
|
}
|
||||||
|
|
||||||
fn log_capabilities(ryzenadj: &RyzenAdj) {
|
fn log_capabilities(ryzenadj: &RyzenAdj) {
|
||||||
log::info!("RyzenAdj v{}.{}.{}", libryzenadj::libryzenadj_sys::RYZENADJ_REVISION_VER, libryzenadj::libryzenadj_sys::RYZENADJ_MAJOR_VER, libryzenadj::libryzenadj_sys::RYZENADJ_MINIOR_VER);
|
log::info!(
|
||||||
|
"RyzenAdj v{}.{}.{}",
|
||||||
|
libryzenadj::libryzenadj_sys::RYZENADJ_REVISION_VER,
|
||||||
|
libryzenadj::libryzenadj_sys::RYZENADJ_MAJOR_VER,
|
||||||
|
libryzenadj::libryzenadj_sys::RYZENADJ_MINIOR_VER
|
||||||
|
);
|
||||||
#[cfg(feature = "experimental")]
|
#[cfg(feature = "experimental")]
|
||||||
if let Some(x) = ryzenadj.get_init_table_err() {
|
if let Some(x) = ryzenadj.get_init_table_err() {
|
||||||
log::warn!("RyzenAdj table init error: {}", x);
|
log::warn!("RyzenAdj table init error: {}", x);
|
||||||
}
|
}
|
||||||
let mut log_msg = String::new();
|
let mut log_msg = String::new();
|
||||||
msg_or_err(&mut log_msg, "bios version", ryzenadj.get_bios_if_ver());
|
msg_or_err(&mut log_msg, "bios version", ryzenadj.get_bios_if_ver());
|
||||||
msg_or_err(&mut log_msg, "refresh", ryzenadj.refresh().map(|_| "success"));
|
msg_or_err(
|
||||||
msg_or_err(&mut log_msg, "CPU family", ryzenadj.get_cpu_family().map(|fam| {
|
&mut log_msg,
|
||||||
let fam_dbg = format!("{:?}", fam);
|
"refresh",
|
||||||
format!("{} (#{})", fam_dbg, fam as i32)
|
ryzenadj.refresh().map(|_| "success"),
|
||||||
}));
|
);
|
||||||
msg_or_err(&mut log_msg, "get_fast_value (PPT)", ryzenadj.get_fast_value());
|
msg_or_err(
|
||||||
msg_or_err(&mut log_msg, "get_slow_value (PPT)", ryzenadj.get_slow_value());
|
&mut log_msg,
|
||||||
|
"CPU family",
|
||||||
|
ryzenadj.get_cpu_family().map(|fam| {
|
||||||
|
let fam_dbg = format!("{:?}", fam);
|
||||||
|
format!("{} (#{})", fam_dbg, fam as i32)
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
msg_or_err(
|
||||||
|
&mut log_msg,
|
||||||
|
"get_fast_value (PPT)",
|
||||||
|
ryzenadj.get_fast_value(),
|
||||||
|
);
|
||||||
|
msg_or_err(
|
||||||
|
&mut log_msg,
|
||||||
|
"get_slow_value (PPT)",
|
||||||
|
ryzenadj.get_slow_value(),
|
||||||
|
);
|
||||||
msg_or_err(&mut log_msg, "get_gfx_clk", ryzenadj.get_gfx_clk());
|
msg_or_err(&mut log_msg, "get_gfx_clk", ryzenadj.get_gfx_clk());
|
||||||
msg_or_err(&mut log_msg, "get_gfx_volt", ryzenadj.get_gfx_volt());
|
msg_or_err(&mut log_msg, "get_gfx_volt", ryzenadj.get_gfx_volt());
|
||||||
|
|
||||||
|
@ -41,7 +66,7 @@ fn ryzen_adj_or_log() -> Option<Mutex<RyzenAdj>> {
|
||||||
Ok(x) => {
|
Ok(x) => {
|
||||||
log_capabilities(&x);
|
log_capabilities(&x);
|
||||||
Some(Mutex::new(x))
|
Some(Mutex::new(x))
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("RyzenAdj init error: {}", e);
|
log::error!("RyzenAdj init error: {}", e);
|
||||||
None
|
None
|
||||||
|
@ -90,7 +115,6 @@ impl ProviderBuilder<GpuJson, limits_core::json_v2::GenericGpuLimit> for Gpu {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gpu {
|
impl Gpu {
|
||||||
|
|
||||||
fn set_all(&mut self) -> Result<(), Vec<SettingError>> {
|
fn set_all(&mut self) -> Result<(), Vec<SettingError>> {
|
||||||
let mutex = match &self.implementor {
|
let mutex = match &self.implementor {
|
||||||
Some(x) => x,
|
Some(x) => x,
|
||||||
|
|
|
@ -7,6 +7,10 @@ pub use gpu::Gpu;
|
||||||
fn _impl_checker() {
|
fn _impl_checker() {
|
||||||
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
||||||
|
|
||||||
impl_provider_builder::<Cpus, Vec<crate::persist::CpuJson>, limits_core::json_v2::GenericCpusLimit>();
|
impl_provider_builder::<
|
||||||
|
Cpus,
|
||||||
|
Vec<crate::persist::CpuJson>,
|
||||||
|
limits_core::json_v2::GenericCpusLimit,
|
||||||
|
>();
|
||||||
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,25 +6,37 @@ mod min_max;
|
||||||
mod traits;
|
mod traits;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
pub mod dev_mode;
|
||||||
pub mod generic;
|
pub mod generic;
|
||||||
pub mod generic_amd;
|
pub mod generic_amd;
|
||||||
pub mod steam_deck;
|
pub mod steam_deck;
|
||||||
pub mod unknown;
|
pub mod unknown;
|
||||||
pub mod dev_mode;
|
|
||||||
|
|
||||||
pub use detect::{auto_detect0, auto_detect_provider, limits_worker::spawn as limits_worker_spawn, get_dev_messages};
|
pub use detect::{
|
||||||
|
auto_detect0, auto_detect_provider, get_dev_messages,
|
||||||
|
limits_worker::spawn as limits_worker_spawn,
|
||||||
|
};
|
||||||
pub use driver::Driver;
|
pub use driver::Driver;
|
||||||
pub use general::{General, SettingVariant, Settings};
|
pub use general::{General, SettingVariant, Settings};
|
||||||
pub use min_max::{min_max_from_json, MinMax};
|
pub use min_max::{min_max_from_json, MinMax};
|
||||||
|
|
||||||
pub use error::SettingError;
|
pub use error::SettingError;
|
||||||
pub use traits::{OnPowerEvent, OnResume, OnSet, PowerMode, TBattery, TCpu, TCpus, TGeneral, TGpu, ProviderBuilder};
|
pub use traits::{
|
||||||
|
OnPowerEvent, OnResume, OnSet, PowerMode, ProviderBuilder, TBattery, TCpu, TCpus, TGeneral,
|
||||||
|
TGpu,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn system_defaults_test() {
|
fn system_defaults_test() {
|
||||||
let settings = super::Settings::system_default("idc".into(), 0, "Cool name".into(), 0, "Variant 0".into());
|
let settings = super::Settings::system_default(
|
||||||
|
"idc".into(),
|
||||||
|
0,
|
||||||
|
"Cool name".into(),
|
||||||
|
0,
|
||||||
|
"Variant 0".into(),
|
||||||
|
);
|
||||||
println!("Loaded system settings: {:?}", settings);
|
println!("Loaded system settings: {:?}", settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use sysfuss::{PowerSupplyAttribute, PowerSupplyPath, HwMonAttribute, HwMonAttributeItem, HwMonAttributeType, HwMonPath, SysEntity, SysEntityAttributesExt, SysAttribute};
|
|
||||||
use sysfuss::capability::attributes;
|
use sysfuss::capability::attributes;
|
||||||
|
use sysfuss::{
|
||||||
|
HwMonAttribute, HwMonAttributeItem, HwMonAttributeType, HwMonPath, PowerSupplyAttribute,
|
||||||
|
PowerSupplyPath, SysAttribute, SysEntity, SysEntityAttributesExt,
|
||||||
|
};
|
||||||
|
|
||||||
use limits_core::json_v2::GenericBatteryLimit;
|
use limits_core::json_v2::GenericBatteryLimit;
|
||||||
|
|
||||||
use smokepatio::ec::{ControllerSet, unnamed_power::{UnnamedPowerEC, ChargeMode}};
|
|
||||||
use crate::api::RangeLimit;
|
use crate::api::RangeLimit;
|
||||||
use crate::persist::{BatteryEventJson, BatteryJson};
|
use crate::persist::{BatteryEventJson, BatteryJson};
|
||||||
use crate::settings::{TBattery, ProviderBuilder};
|
|
||||||
use crate::settings::{OnPowerEvent, OnResume, OnSet, PowerMode, SettingError};
|
use crate::settings::{OnPowerEvent, OnResume, OnSet, PowerMode, SettingError};
|
||||||
|
use crate::settings::{ProviderBuilder, TBattery};
|
||||||
|
use smokepatio::ec::{
|
||||||
|
unnamed_power::{ChargeMode, UnnamedPowerEC},
|
||||||
|
ControllerSet,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Battery {
|
pub struct Battery {
|
||||||
|
@ -121,7 +127,12 @@ impl EventInstruction {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_json(other: BatteryEventJson, _version: u64, hwmon: Arc<HwMonPath>, ec: Arc<Mutex<UnnamedPowerEC>>) -> Self {
|
fn from_json(
|
||||||
|
other: BatteryEventJson,
|
||||||
|
_version: u64,
|
||||||
|
hwmon: Arc<HwMonPath>,
|
||||||
|
ec: Arc<Mutex<UnnamedPowerEC>>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
trigger: Self::str_to_trigger(&other.trigger).unwrap_or(EventTrigger::Ignored),
|
trigger: Self::str_to_trigger(&other.trigger).unwrap_or(EventTrigger::Ignored),
|
||||||
charge_rate: other.charge_rate,
|
charge_rate: other.charge_rate,
|
||||||
|
@ -137,7 +148,10 @@ impl EventInstruction {
|
||||||
|
|
||||||
fn set_charge_mode(&self) -> Result<(), SettingError> {
|
fn set_charge_mode(&self) -> Result<(), SettingError> {
|
||||||
if let Some(charge_mode) = self.charge_mode {
|
if let Some(charge_mode) = self.charge_mode {
|
||||||
let mut lock = self.bat_ec.lock().expect("failed to lock battery controller");
|
let mut lock = self
|
||||||
|
.bat_ec
|
||||||
|
.lock()
|
||||||
|
.expect("failed to lock battery controller");
|
||||||
lock.set(charge_mode).map_err(|_| SettingError {
|
lock.set(charge_mode).map_err(|_| SettingError {
|
||||||
msg: format!("Failed to set charge mode"),
|
msg: format!("Failed to set charge mode"),
|
||||||
setting: crate::settings::SettingVariant::Battery,
|
setting: crate::settings::SettingVariant::Battery,
|
||||||
|
@ -149,12 +163,15 @@ impl EventInstruction {
|
||||||
|
|
||||||
fn set_charge_rate(&self) -> Result<(), SettingError> {
|
fn set_charge_rate(&self) -> Result<(), SettingError> {
|
||||||
if let Some(charge_rate) = self.charge_rate {
|
if let Some(charge_rate) = self.charge_rate {
|
||||||
self.sysfs_hwmon.set(MAX_BATTERY_CHARGE_RATE_ATTR, charge_rate).map_err(
|
self.sysfs_hwmon
|
||||||
|e| SettingError {
|
.set(MAX_BATTERY_CHARGE_RATE_ATTR, charge_rate)
|
||||||
msg: format!("Failed to write to `{:?}`: {}", MAX_BATTERY_CHARGE_RATE_ATTR, e),
|
.map_err(|e| SettingError {
|
||||||
|
msg: format!(
|
||||||
|
"Failed to write to `{:?}`: {}",
|
||||||
|
MAX_BATTERY_CHARGE_RATE_ATTR, e
|
||||||
|
),
|
||||||
setting: crate::settings::SettingVariant::Battery,
|
setting: crate::settings::SettingVariant::Battery,
|
||||||
},
|
})
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -194,7 +211,6 @@ const BATTERY_CHARGE_DESIGN_PATH: &str = "/sys/class/power_supply/BAT1/charge_fu
|
||||||
const USB_PD_IN_MVOLTAGE_PATH: &str = "/sys/class/hwmon/hwmon5/in0_input"; // read-only
|
const USB_PD_IN_MVOLTAGE_PATH: &str = "/sys/class/hwmon/hwmon5/in0_input"; // read-only
|
||||||
const USB_PD_IN_CURRENT_PATH: &str = "/sys/class/hwmon/hwmon5/curr1_input"; // read-only*/
|
const USB_PD_IN_CURRENT_PATH: &str = "/sys/class/hwmon/hwmon5/curr1_input"; // read-only*/
|
||||||
|
|
||||||
|
|
||||||
const BATTERY_NEEDS: &[PowerSupplyAttribute] = &[
|
const BATTERY_NEEDS: &[PowerSupplyAttribute] = &[
|
||||||
PowerSupplyAttribute::Type,
|
PowerSupplyAttribute::Type,
|
||||||
PowerSupplyAttribute::CurrentNow,
|
PowerSupplyAttribute::CurrentNow,
|
||||||
|
@ -213,8 +229,10 @@ const HWMON_NEEDS: &[HwMonAttribute] = &[
|
||||||
//HwMonAttribute::custom("maximum_battery_charge_rate"), // NOTE: Cannot filter by custom capabilities
|
//HwMonAttribute::custom("maximum_battery_charge_rate"), // NOTE: Cannot filter by custom capabilities
|
||||||
];
|
];
|
||||||
|
|
||||||
const MAX_BATTERY_CHARGE_RATE_ATTR: HwMonAttribute = HwMonAttribute::custom("maximum_battery_charge_rate");
|
const MAX_BATTERY_CHARGE_RATE_ATTR: HwMonAttribute =
|
||||||
const MAX_BATTERY_CHARGE_LEVEL_ATTR: HwMonAttribute = HwMonAttribute::custom("max_battery_charge_level");
|
HwMonAttribute::custom("maximum_battery_charge_rate");
|
||||||
|
const MAX_BATTERY_CHARGE_LEVEL_ATTR: HwMonAttribute =
|
||||||
|
HwMonAttribute::custom("max_battery_charge_level");
|
||||||
|
|
||||||
const MAX_CHARGE_RATE: u64 = 2500;
|
const MAX_CHARGE_RATE: u64 = 2500;
|
||||||
const MIN_CHARGE_RATE: u64 = 250;
|
const MIN_CHARGE_RATE: u64 = 250;
|
||||||
|
@ -229,9 +247,12 @@ impl Battery {
|
||||||
log::error!("Failed to find SteamDeck battery power_supply in sysfs (no results), using naive fallback");
|
log::error!("Failed to find SteamDeck battery power_supply in sysfs (no results), using naive fallback");
|
||||||
root.power_supply_by_name("BAT1")
|
root.power_supply_by_name("BAT1")
|
||||||
});
|
});
|
||||||
log::info!("Found SteamDeck battery power_supply in sysfs: {}", psu.as_ref().display());
|
log::info!(
|
||||||
|
"Found SteamDeck battery power_supply in sysfs: {}",
|
||||||
|
psu.as_ref().display()
|
||||||
|
);
|
||||||
psu
|
psu
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to find SteamDeck battery power_supply in sysfs ({}), using naive fallback", e);
|
log::error!("Failed to find SteamDeck battery power_supply in sysfs ({}), using naive fallback", e);
|
||||||
root.power_supply_by_name("BAT1")
|
root.power_supply_by_name("BAT1")
|
||||||
|
@ -245,11 +266,15 @@ impl Battery {
|
||||||
Ok(hwmon) => {
|
Ok(hwmon) => {
|
||||||
if !hwmon.capable(attributes(HWMON_NEEDS.into_iter().copied())) {
|
if !hwmon.capable(attributes(HWMON_NEEDS.into_iter().copied())) {
|
||||||
log::warn!("Found incapable SteamDeck battery hwmon in sysfs (hwmon by name {} exists but missing attributes), persevering because ignorance is bliss", super::util::JUPITER_HWMON_NAME);
|
log::warn!("Found incapable SteamDeck battery hwmon in sysfs (hwmon by name {} exists but missing attributes), persevering because ignorance is bliss", super::util::JUPITER_HWMON_NAME);
|
||||||
} else {
|
} else {
|
||||||
log::info!("Found SteamDeck battery hwmon {} in sysfs: {}", super::util::JUPITER_HWMON_NAME, hwmon.as_ref().display());
|
log::info!(
|
||||||
|
"Found SteamDeck battery hwmon {} in sysfs: {}",
|
||||||
|
super::util::JUPITER_HWMON_NAME,
|
||||||
|
hwmon.as_ref().display()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
hwmon
|
hwmon
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("Failed to find SteamDeck battery hwmon {} in sysfs ({}), trying alternate name",
|
log::warn!("Failed to find SteamDeck battery hwmon {} in sysfs ({}), trying alternate name",
|
||||||
super::util::JUPITER_HWMON_NAME, e);
|
super::util::JUPITER_HWMON_NAME, e);
|
||||||
|
@ -258,10 +283,14 @@ impl Battery {
|
||||||
if !hwmon.capable(attributes(HWMON_NEEDS.into_iter().copied())) {
|
if !hwmon.capable(attributes(HWMON_NEEDS.into_iter().copied())) {
|
||||||
log::warn!("Found incapable SteamDeck battery hwmon in sysfs (hwmon by name {} exists but missing attributes), persevering because ignorance is bliss", super::util::STEAMDECK_HWMON_NAME);
|
log::warn!("Found incapable SteamDeck battery hwmon in sysfs (hwmon by name {} exists but missing attributes), persevering because ignorance is bliss", super::util::STEAMDECK_HWMON_NAME);
|
||||||
} else {
|
} else {
|
||||||
log::info!("Found SteamDeck battery hwmon {} in sysfs: {}", super::util::STEAMDECK_HWMON_NAME, hwmon.as_ref().display());
|
log::info!(
|
||||||
|
"Found SteamDeck battery hwmon {} in sysfs: {}",
|
||||||
|
super::util::STEAMDECK_HWMON_NAME,
|
||||||
|
hwmon.as_ref().display()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
hwmon
|
hwmon
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to find SteamDeck battery hwmon {} in sysfs ({}), using naive fallback", super::util::STEAMDECK_HWMON_NAME, e);
|
log::error!("Failed to find SteamDeck battery hwmon {} in sysfs ({}), using naive fallback", super::util::STEAMDECK_HWMON_NAME, e);
|
||||||
root.hwmon_by_index(5)
|
root.hwmon_by_index(5)
|
||||||
|
@ -295,21 +324,27 @@ impl Battery {
|
||||||
if let Some(charge_rate) = self.charge_rate {
|
if let Some(charge_rate) = self.charge_rate {
|
||||||
self.state.charge_rate_set = true;
|
self.state.charge_rate_set = true;
|
||||||
let path = MAX_BATTERY_CHARGE_RATE_ATTR.path(&*self.sysfs_hwmon);
|
let path = MAX_BATTERY_CHARGE_RATE_ATTR.path(&*self.sysfs_hwmon);
|
||||||
self.sysfs_hwmon.set(MAX_BATTERY_CHARGE_RATE_ATTR, charge_rate).map_err(
|
self.sysfs_hwmon
|
||||||
|e| SettingError {
|
.set(MAX_BATTERY_CHARGE_RATE_ATTR, charge_rate)
|
||||||
|
.map_err(|e| SettingError {
|
||||||
msg: format!("Failed to write to `{}`: {}", path.display(), e),
|
msg: format!("Failed to write to `{}`: {}", path.display(), e),
|
||||||
setting: crate::settings::SettingVariant::Battery,
|
setting: crate::settings::SettingVariant::Battery,
|
||||||
},
|
})
|
||||||
)
|
|
||||||
} else if self.state.charge_rate_set {
|
} else if self.state.charge_rate_set {
|
||||||
self.state.charge_rate_set = false;
|
self.state.charge_rate_set = false;
|
||||||
let path = MAX_BATTERY_CHARGE_RATE_ATTR.path(&*self.sysfs_hwmon);
|
let path = MAX_BATTERY_CHARGE_RATE_ATTR.path(&*self.sysfs_hwmon);
|
||||||
self.sysfs_hwmon.set(MAX_BATTERY_CHARGE_RATE_ATTR, self.limits.charge_rate.and_then(|lim| lim.max).unwrap_or(2500)).map_err(
|
self.sysfs_hwmon
|
||||||
|e| SettingError {
|
.set(
|
||||||
|
MAX_BATTERY_CHARGE_RATE_ATTR,
|
||||||
|
self.limits
|
||||||
|
.charge_rate
|
||||||
|
.and_then(|lim| lim.max)
|
||||||
|
.unwrap_or(2500),
|
||||||
|
)
|
||||||
|
.map_err(|e| SettingError {
|
||||||
msg: format!("Failed to write to `{}`: {}", path.display(), e),
|
msg: format!("Failed to write to `{}`: {}", path.display(), e),
|
||||||
setting: crate::settings::SettingVariant::Battery,
|
setting: crate::settings::SettingVariant::Battery,
|
||||||
},
|
})
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -318,14 +353,20 @@ impl Battery {
|
||||||
fn set_charge_mode(&mut self) -> Result<(), SettingError> {
|
fn set_charge_mode(&mut self) -> Result<(), SettingError> {
|
||||||
if let Some(charge_mode) = self.charge_mode {
|
if let Some(charge_mode) = self.charge_mode {
|
||||||
self.state.charge_mode_set = true;
|
self.state.charge_mode_set = true;
|
||||||
let mut lock = self.bat_ec.lock().expect("Failed to lock battery controller");
|
let mut lock = self
|
||||||
|
.bat_ec
|
||||||
|
.lock()
|
||||||
|
.expect("Failed to lock battery controller");
|
||||||
lock.set(charge_mode).map_err(|_| SettingError {
|
lock.set(charge_mode).map_err(|_| SettingError {
|
||||||
msg: format!("Failed to set charge mode"),
|
msg: format!("Failed to set charge mode"),
|
||||||
setting: crate::settings::SettingVariant::Battery,
|
setting: crate::settings::SettingVariant::Battery,
|
||||||
})
|
})
|
||||||
} else if self.state.charge_mode_set {
|
} else if self.state.charge_mode_set {
|
||||||
self.state.charge_mode_set = false;
|
self.state.charge_mode_set = false;
|
||||||
let mut lock = self.bat_ec.lock().expect("Failed to lock battery controller");
|
let mut lock = self
|
||||||
|
.bat_ec
|
||||||
|
.lock()
|
||||||
|
.expect("Failed to lock battery controller");
|
||||||
lock.set(ChargeMode::Normal).map_err(|_| SettingError {
|
lock.set(ChargeMode::Normal).map_err(|_| SettingError {
|
||||||
msg: format!("Failed to set charge mode"),
|
msg: format!("Failed to set charge mode"),
|
||||||
setting: crate::settings::SettingVariant::Battery,
|
setting: crate::settings::SettingVariant::Battery,
|
||||||
|
@ -337,23 +378,35 @@ impl Battery {
|
||||||
|
|
||||||
fn set_charge_limit(&mut self) -> Result<(), SettingError> {
|
fn set_charge_limit(&mut self) -> Result<(), SettingError> {
|
||||||
let attr_exists = MAX_BATTERY_CHARGE_LEVEL_ATTR.exists(&*self.sysfs_hwmon);
|
let attr_exists = MAX_BATTERY_CHARGE_LEVEL_ATTR.exists(&*self.sysfs_hwmon);
|
||||||
log::debug!("Does battery limit attribute (max_battery_charge_level) exist? {}", attr_exists);
|
log::debug!(
|
||||||
|
"Does battery limit attribute (max_battery_charge_level) exist? {}",
|
||||||
|
attr_exists
|
||||||
|
);
|
||||||
if let Some(charge_limit) = self.charge_limit {
|
if let Some(charge_limit) = self.charge_limit {
|
||||||
self.state.charge_limit_set = true;
|
self.state.charge_limit_set = true;
|
||||||
self.sysfs_hwmon.set(MAX_BATTERY_CHARGE_LEVEL_ATTR, (charge_limit * 100.0).round() as u64)
|
self.sysfs_hwmon
|
||||||
.map_err(|e| SettingError {
|
.set(
|
||||||
msg: format!("Failed to write to {:?}: {}", MAX_BATTERY_CHARGE_LEVEL_ATTR, e),
|
MAX_BATTERY_CHARGE_LEVEL_ATTR,
|
||||||
setting: crate::settings::SettingVariant::Battery,
|
(charge_limit * 100.0).round() as u64,
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
.map_err(|e| SettingError {
|
||||||
|
msg: format!(
|
||||||
|
"Failed to write to {:?}: {}",
|
||||||
|
MAX_BATTERY_CHARGE_LEVEL_ATTR, e
|
||||||
|
),
|
||||||
|
setting: crate::settings::SettingVariant::Battery,
|
||||||
|
})
|
||||||
} else if self.state.charge_limit_set {
|
} else if self.state.charge_limit_set {
|
||||||
self.state.charge_limit_set = false;
|
self.state.charge_limit_set = false;
|
||||||
self.sysfs_hwmon.set(MAX_BATTERY_CHARGE_LEVEL_ATTR, 0)
|
self.sysfs_hwmon
|
||||||
|
.set(MAX_BATTERY_CHARGE_LEVEL_ATTR, 0)
|
||||||
.map_err(|e| SettingError {
|
.map_err(|e| SettingError {
|
||||||
msg: format!("Failed to reset (write to) {:?}: {}", MAX_BATTERY_CHARGE_LEVEL_ATTR, e),
|
msg: format!(
|
||||||
setting: crate::settings::SettingVariant::Battery,
|
"Failed to reset (write to) {:?}: {}",
|
||||||
}
|
MAX_BATTERY_CHARGE_LEVEL_ATTR, e
|
||||||
)
|
),
|
||||||
|
setting: crate::settings::SettingVariant::Battery,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -373,8 +426,16 @@ impl Battery {
|
||||||
|
|
||||||
fn clamp_all(&mut self) {
|
fn clamp_all(&mut self) {
|
||||||
if let Some(charge_rate) = &mut self.charge_rate {
|
if let Some(charge_rate) = &mut self.charge_rate {
|
||||||
*charge_rate =
|
*charge_rate = (*charge_rate).clamp(
|
||||||
(*charge_rate).clamp(self.limits.charge_rate.and_then(|lim| lim.min).unwrap_or(MIN_CHARGE_RATE), self.limits.charge_rate.and_then(|lim| lim.max).unwrap_or(MAX_CHARGE_RATE));
|
self.limits
|
||||||
|
.charge_rate
|
||||||
|
.and_then(|lim| lim.min)
|
||||||
|
.unwrap_or(MIN_CHARGE_RATE),
|
||||||
|
self.limits
|
||||||
|
.charge_rate
|
||||||
|
.and_then(|lim| lim.max)
|
||||||
|
.unwrap_or(MAX_CHARGE_RATE),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,13 +619,21 @@ impl Into<BatteryJson> for Battery {
|
||||||
charge_rate: self.charge_rate,
|
charge_rate: self.charge_rate,
|
||||||
charge_mode: self.charge_mode.map(Self::charge_mode_to_str),
|
charge_mode: self.charge_mode.map(Self::charge_mode_to_str),
|
||||||
events: events.into_iter().map(|x| x.into()).collect(),
|
events: events.into_iter().map(|x| x.into()).collect(),
|
||||||
root: self.sysfs_bat.root().or(self.sysfs_hwmon.root()).and_then(|p| p.as_ref().to_str().map(|x| x.to_owned()))
|
root: self
|
||||||
|
.sysfs_bat
|
||||||
|
.root()
|
||||||
|
.or(self.sysfs_hwmon.root())
|
||||||
|
.and_then(|p| p.as_ref().to_str().map(|x| x.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
||||||
fn from_json_and_limits(persistent: BatteryJson, version: u64, limits: GenericBatteryLimit) -> Self {
|
fn from_json_and_limits(
|
||||||
|
persistent: BatteryJson,
|
||||||
|
version: u64,
|
||||||
|
limits: GenericBatteryLimit,
|
||||||
|
) -> Self {
|
||||||
let hwmon_sys = Arc::new(Self::find_hwmon_sysfs(None::<&'static str>));
|
let hwmon_sys = Arc::new(Self::find_hwmon_sysfs(None::<&'static str>));
|
||||||
let ec = Arc::new(Mutex::new(UnnamedPowerEC::new()));
|
let ec = Arc::new(Mutex::new(UnnamedPowerEC::new()));
|
||||||
match version {
|
match version {
|
||||||
|
@ -586,14 +655,15 @@ impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
||||||
sysfs_hwmon: hwmon_sys,
|
sysfs_hwmon: hwmon_sys,
|
||||||
bat_ec: ec,
|
bat_ec: ec,
|
||||||
variant: super::Model::LCD,
|
variant: super::Model::LCD,
|
||||||
}.remove_charge_limit_instructions(),
|
}
|
||||||
|
.remove_charge_limit_instructions(),
|
||||||
_ => Self {
|
_ => Self {
|
||||||
charge_rate: persistent.charge_rate,
|
charge_rate: persistent.charge_rate,
|
||||||
charge_mode: persistent
|
charge_mode: persistent
|
||||||
.charge_mode
|
.charge_mode
|
||||||
.map(|x| Self::str_to_charge_mode(&x))
|
.map(|x| Self::str_to_charge_mode(&x))
|
||||||
.flatten(),
|
.flatten(),
|
||||||
charge_limit: None,
|
charge_limit: None,
|
||||||
events: persistent
|
events: persistent
|
||||||
.events
|
.events
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -605,7 +675,8 @@ impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
||||||
sysfs_hwmon: hwmon_sys,
|
sysfs_hwmon: hwmon_sys,
|
||||||
bat_ec: ec,
|
bat_ec: ec,
|
||||||
variant: super::Model::LCD,
|
variant: super::Model::LCD,
|
||||||
}.remove_charge_limit_instructions(),
|
}
|
||||||
|
.remove_charge_limit_instructions(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -621,7 +692,8 @@ impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
||||||
sysfs_hwmon: Arc::new(Self::find_hwmon_sysfs(None::<&'static str>)),
|
sysfs_hwmon: Arc::new(Self::find_hwmon_sysfs(None::<&'static str>)),
|
||||||
bat_ec: Arc::new(Mutex::new(UnnamedPowerEC::new())),
|
bat_ec: Arc::new(Mutex::new(UnnamedPowerEC::new())),
|
||||||
variant: super::Model::LCD,
|
variant: super::Model::LCD,
|
||||||
}.remove_charge_limit_instructions()
|
}
|
||||||
|
.remove_charge_limit_instructions()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -675,8 +747,16 @@ impl TBattery for Battery {
|
||||||
fn limits(&self) -> crate::api::BatteryLimits {
|
fn limits(&self) -> crate::api::BatteryLimits {
|
||||||
crate::api::BatteryLimits {
|
crate::api::BatteryLimits {
|
||||||
charge_current: Some(RangeLimit {
|
charge_current: Some(RangeLimit {
|
||||||
min: self.limits.charge_rate.and_then(|lim| lim.min).unwrap_or(MIN_CHARGE_RATE),
|
min: self
|
||||||
max: self.limits.charge_rate.and_then(|lim| lim.max).unwrap_or(MAX_CHARGE_RATE),
|
.limits
|
||||||
|
.charge_rate
|
||||||
|
.and_then(|lim| lim.min)
|
||||||
|
.unwrap_or(MIN_CHARGE_RATE),
|
||||||
|
max: self
|
||||||
|
.limits
|
||||||
|
.charge_rate
|
||||||
|
.and_then(|lim| lim.max)
|
||||||
|
.unwrap_or(MAX_CHARGE_RATE),
|
||||||
}),
|
}),
|
||||||
charge_current_step: 50,
|
charge_current_step: 50,
|
||||||
charge_modes: vec![
|
charge_modes: vec![
|
||||||
|
|
|
@ -2,22 +2,20 @@ use std::convert::Into;
|
||||||
|
|
||||||
use sysfuss::{BasicEntityPath, SysEntity, SysEntityAttributesExt};
|
use sysfuss::{BasicEntityPath, SysEntity, SysEntityAttributesExt};
|
||||||
|
|
||||||
use limits_core::json_v2::{GenericCpusLimit, GenericCpuLimit};
|
use limits_core::json_v2::{GenericCpuLimit, GenericCpusLimit};
|
||||||
|
|
||||||
use super::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT;
|
|
||||||
use super::util::{range_max_or_fallback, range_min_or_fallback};
|
use super::util::{range_max_or_fallback, range_min_or_fallback};
|
||||||
|
use super::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT;
|
||||||
use crate::api::RangeLimit;
|
use crate::api::RangeLimit;
|
||||||
use crate::persist::CpuJson;
|
use crate::persist::CpuJson;
|
||||||
use crate::settings::{min_max_from_json, MinMax};
|
use crate::settings::{min_max_from_json, MinMax};
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
use crate::settings::{TCpu, TCpus, ProviderBuilder};
|
use crate::settings::{ProviderBuilder, TCpu, TCpus};
|
||||||
|
|
||||||
const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present";
|
const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present";
|
||||||
const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control";
|
const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control";
|
||||||
|
|
||||||
const CARD_EXTENSIONS: &[&'static str] = &[
|
const CARD_EXTENSIONS: &[&'static str] = &[super::DPM_FORCE_LIMITS_ATTRIBUTE];
|
||||||
super::DPM_FORCE_LIMITS_ATTRIBUTE
|
|
||||||
];
|
|
||||||
|
|
||||||
const MAX_CLOCK: u64 = 3500;
|
const MAX_CLOCK: u64 = 3500;
|
||||||
const MIN_MAX_CLOCK: u64 = 200; // minimum value allowed for maximum CPU clock, MHz
|
const MIN_MAX_CLOCK: u64 = 200; // minimum value allowed for maximum CPU clock, MHz
|
||||||
|
@ -109,7 +107,11 @@ impl Cpus {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
impl ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
||||||
fn from_json_and_limits(mut persistent: Vec<CpuJson>, version: u64, limits: GenericCpusLimit) -> Self {
|
fn from_json_and_limits(
|
||||||
|
mut persistent: Vec<CpuJson>,
|
||||||
|
version: u64,
|
||||||
|
limits: GenericCpusLimit,
|
||||||
|
) -> Self {
|
||||||
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.reset();
|
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.reset();
|
||||||
let (_, can_smt) = Self::system_smt_capabilities();
|
let (_, can_smt) = Self::system_smt_capabilities();
|
||||||
let mut result = Vec::with_capacity(persistent.len());
|
let mut result = Vec::with_capacity(persistent.len());
|
||||||
|
@ -123,18 +125,9 @@ impl ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let new_cpu = if let Some(cpu_limit) = limits.cpus.get(i) {
|
let new_cpu = if let Some(cpu_limit) = limits.cpus.get(i) {
|
||||||
Cpu::from_json_and_limits(
|
Cpu::from_json_and_limits(cpu, version, i, cpu_limit.to_owned())
|
||||||
cpu,
|
|
||||||
version,
|
|
||||||
i,
|
|
||||||
cpu_limit.to_owned()
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Cpu::from_json(
|
Cpu::from_json(cpu, version, i)
|
||||||
cpu,
|
|
||||||
version,
|
|
||||||
i,
|
|
||||||
)
|
|
||||||
};
|
};
|
||||||
result.push(new_cpu);
|
result.push(new_cpu);
|
||||||
}
|
}
|
||||||
|
@ -160,10 +153,7 @@ impl ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
||||||
let mut sys_cpus = Vec::with_capacity(max_cpu);
|
let mut sys_cpus = Vec::with_capacity(max_cpu);
|
||||||
for i in 0..max_cpu {
|
for i in 0..max_cpu {
|
||||||
let new_cpu = if let Some(cpu_limit) = limits.cpus.get(i) {
|
let new_cpu = if let Some(cpu_limit) = limits.cpus.get(i) {
|
||||||
Cpu::from_limits(
|
Cpu::from_limits(i, cpu_limit.to_owned())
|
||||||
i,
|
|
||||||
cpu_limit.to_owned()
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
Cpu::system_default(i)
|
Cpu::system_default(i)
|
||||||
};
|
};
|
||||||
|
@ -255,7 +245,12 @@ enum ClockType {
|
||||||
|
|
||||||
impl Cpu {
|
impl Cpu {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_json_and_limits(other: CpuJson, version: u64, i: usize, oc_limits: GenericCpuLimit) -> Self {
|
fn from_json_and_limits(
|
||||||
|
other: CpuJson,
|
||||||
|
version: u64,
|
||||||
|
i: usize,
|
||||||
|
oc_limits: GenericCpuLimit,
|
||||||
|
) -> Self {
|
||||||
match version {
|
match version {
|
||||||
0 => Self {
|
0 => Self {
|
||||||
online: other.online,
|
online: other.online,
|
||||||
|
@ -280,13 +275,21 @@ impl Cpu {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_json(other: CpuJson, version: u64, i: usize) -> Self {
|
fn from_json(other: CpuJson, version: u64, i: usize) -> Self {
|
||||||
let oc_limits = GenericCpuLimit::default_for(&limits_core::json_v2::CpuLimitType::SteamDeck, i);
|
let oc_limits =
|
||||||
|
GenericCpuLimit::default_for(&limits_core::json_v2::CpuLimitType::SteamDeck, i);
|
||||||
Self::from_json_and_limits(other, version, i, oc_limits)
|
Self::from_json_and_limits(other, version, i, oc_limits)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_card_sysfs(root: Option<impl AsRef<std::path::Path>>) -> BasicEntityPath {
|
fn find_card_sysfs(root: Option<impl AsRef<std::path::Path>>) -> BasicEntityPath {
|
||||||
let root = crate::settings::util::root_or_default_sysfs(root);
|
let root = crate::settings::util::root_or_default_sysfs(root);
|
||||||
match root.class("drm", sysfuss::capability::attributes(crate::settings::util::CARD_NEEDS.into_iter().map(|s| s.to_string()))) {
|
match root.class(
|
||||||
|
"drm",
|
||||||
|
sysfuss::capability::attributes(
|
||||||
|
crate::settings::util::CARD_NEEDS
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| s.to_string()),
|
||||||
|
),
|
||||||
|
) {
|
||||||
Ok(iter) => {
|
Ok(iter) => {
|
||||||
let card = iter
|
let card = iter
|
||||||
.filter(|ent| if let Ok(name) = ent.name() { name.starts_with("card")} else { false })
|
.filter(|ent| if let Ok(name) = ent.name() { name.starts_with("card")} else { false })
|
||||||
|
@ -298,37 +301,45 @@ impl Cpu {
|
||||||
});
|
});
|
||||||
log::info!("Found SteamDeck drm in sysfs: {}", card.as_ref().display());
|
log::info!("Found SteamDeck drm in sysfs: {}", card.as_ref().display());
|
||||||
card
|
card
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to find SteamDeck drm in sysfs ({}), using naive fallback", e);
|
log::error!(
|
||||||
|
"Failed to find SteamDeck drm in sysfs ({}), using naive fallback",
|
||||||
|
e
|
||||||
|
);
|
||||||
BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0"))
|
BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_clock_limit(&self, index: usize, speed: u64, mode: ClockType) -> Result<(), SettingError> {
|
fn set_clock_limit(
|
||||||
|
&self,
|
||||||
|
index: usize,
|
||||||
|
speed: u64,
|
||||||
|
mode: ClockType,
|
||||||
|
) -> Result<(), SettingError> {
|
||||||
let payload = format!("p {} {} {}\n", index / 2, mode as u8, speed);
|
let payload = format!("p {} {} {}\n", index / 2, mode as u8, speed);
|
||||||
self.sysfs.set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), &payload).map_err(|e| {
|
self.sysfs
|
||||||
SettingError {
|
.set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), &payload)
|
||||||
|
.map_err(|e| SettingError {
|
||||||
msg: format!(
|
msg: format!(
|
||||||
"Failed to write `{}` to `{}`: {}",
|
"Failed to write `{}` to `{}`: {}",
|
||||||
&payload, CPU_CLOCK_LIMITS_ATTRIBUTE, e
|
&payload, CPU_CLOCK_LIMITS_ATTRIBUTE, e
|
||||||
),
|
),
|
||||||
setting: crate::settings::SettingVariant::Cpu,
|
setting: crate::settings::SettingVariant::Cpu,
|
||||||
}
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_clock_limits(&self) -> Result<(), SettingError> {
|
fn reset_clock_limits(&self) -> Result<(), SettingError> {
|
||||||
self.sysfs.set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), "r\n").map_err(|e| {
|
self.sysfs
|
||||||
SettingError {
|
.set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), "r\n")
|
||||||
|
.map_err(|e| SettingError {
|
||||||
msg: format!(
|
msg: format!(
|
||||||
"Failed to write `r` to `{}`: {}",
|
"Failed to write `r` to `{}`: {}",
|
||||||
CPU_CLOCK_LIMITS_ATTRIBUTE, e
|
CPU_CLOCK_LIMITS_ATTRIBUTE, e
|
||||||
),
|
),
|
||||||
setting: crate::settings::SettingVariant::Cpu,
|
setting: crate::settings::SettingVariant::Cpu,
|
||||||
}
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_clock_limits(&mut self) -> Result<(), Vec<SettingError>> {
|
fn set_clock_limits(&mut self) -> Result<(), Vec<SettingError>> {
|
||||||
|
@ -350,11 +361,12 @@ impl Cpu {
|
||||||
}
|
}
|
||||||
// min clock
|
// min clock
|
||||||
if let Some(min) = clock_limits.min {
|
if let Some(min) = clock_limits.min {
|
||||||
let valid_min = if min < range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK) {
|
let valid_min =
|
||||||
range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK)
|
if min < range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK) {
|
||||||
} else {
|
range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK)
|
||||||
min
|
} else {
|
||||||
};
|
min
|
||||||
|
};
|
||||||
self.set_clock_limit(self.index, valid_min, ClockType::Min)
|
self.set_clock_limit(self.index, valid_min, ClockType::Min)
|
||||||
.unwrap_or_else(|e| errors.push(e));
|
.unwrap_or_else(|e| errors.push(e));
|
||||||
}
|
}
|
||||||
|
@ -371,22 +383,30 @@ impl Cpu {
|
||||||
let mut errors = Vec::new();
|
let mut errors = Vec::new();
|
||||||
self.state.clock_limits_set = false;
|
self.state.clock_limits_set = false;
|
||||||
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(false, self.index);
|
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(false, self.index);
|
||||||
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT
|
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs)?;
|
||||||
.enforce_level(&self.sysfs)?;
|
|
||||||
if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() {
|
if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() {
|
||||||
// always set clock speeds, since it doesn't reset correctly (kernel/hardware bug)
|
// always set clock speeds, since it doesn't reset correctly (kernel/hardware bug)
|
||||||
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs)?;
|
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs)?;
|
||||||
// disable manual clock limits
|
// disable manual clock limits
|
||||||
log::debug!("Setting CPU {} to default clockspeed", self.index);
|
log::debug!("Setting CPU {} to default clockspeed", self.index);
|
||||||
// max clock
|
// max clock
|
||||||
self.set_clock_limit(self.index, range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK), ClockType::Max)
|
self.set_clock_limit(
|
||||||
.unwrap_or_else(|e| errors.push(e));
|
self.index,
|
||||||
|
range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK),
|
||||||
|
ClockType::Max,
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|e| errors.push(e));
|
||||||
// min clock
|
// min clock
|
||||||
self.set_clock_limit(self.index, range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK), ClockType::Min)
|
self.set_clock_limit(
|
||||||
.unwrap_or_else(|e| errors.push(e));
|
self.index,
|
||||||
|
range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK),
|
||||||
|
ClockType::Min,
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|e| errors.push(e));
|
||||||
}
|
}
|
||||||
// TODO remove this when it's no longer needed
|
// TODO remove this when it's no longer needed
|
||||||
self.clock_unset_workaround().unwrap_or_else(|mut e| errors.append(&mut e));
|
self.clock_unset_workaround()
|
||||||
|
.unwrap_or_else(|mut e| errors.append(&mut e));
|
||||||
if errors.is_empty() {
|
if errors.is_empty() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
@ -407,11 +427,19 @@ impl Cpu {
|
||||||
// disable manual clock limits
|
// disable manual clock limits
|
||||||
log::debug!("Setting CPU {} to default clockspeed", self.index);
|
log::debug!("Setting CPU {} to default clockspeed", self.index);
|
||||||
// max clock
|
// max clock
|
||||||
self.set_clock_limit(self.index, range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK), ClockType::Max)
|
self.set_clock_limit(
|
||||||
.unwrap_or_else(|e| errors.push(e));
|
self.index,
|
||||||
|
range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK),
|
||||||
|
ClockType::Max,
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|e| errors.push(e));
|
||||||
// min clock
|
// min clock
|
||||||
self.set_clock_limit(self.index, range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK), ClockType::Min)
|
self.set_clock_limit(
|
||||||
.unwrap_or_else(|e| errors.push(e));
|
self.index,
|
||||||
|
range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK),
|
||||||
|
ClockType::Min,
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|e| errors.push(e));
|
||||||
|
|
||||||
self.set_confirm().unwrap_or_else(|e| errors.push(e));
|
self.set_confirm().unwrap_or_else(|e| errors.push(e));
|
||||||
|
|
||||||
|
@ -430,12 +458,15 @@ impl Cpu {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_confirm(&self) -> Result<(), SettingError> {
|
fn set_confirm(&self) -> Result<(), SettingError> {
|
||||||
self.sysfs.set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), "c\n").map_err(|e| {
|
self.sysfs
|
||||||
SettingError {
|
.set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), "c\n")
|
||||||
msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_ATTRIBUTE, e),
|
.map_err(|e| SettingError {
|
||||||
|
msg: format!(
|
||||||
|
"Failed to write `c` to `{}`: {}",
|
||||||
|
CPU_CLOCK_LIMITS_ATTRIBUTE, e
|
||||||
|
),
|
||||||
setting: crate::settings::SettingVariant::Cpu,
|
setting: crate::settings::SettingVariant::Cpu,
|
||||||
}
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_force_performance_related(&mut self) -> Result<(), Vec<SettingError>> {
|
fn set_force_performance_related(&mut self) -> Result<(), Vec<SettingError>> {
|
||||||
|
@ -504,12 +535,16 @@ impl Cpu {
|
||||||
fn clamp_all(&mut self) {
|
fn clamp_all(&mut self) {
|
||||||
if let Some(clock_limits) = &mut self.clock_limits {
|
if let Some(clock_limits) = &mut self.clock_limits {
|
||||||
if let Some(min) = clock_limits.min {
|
if let Some(min) = clock_limits.min {
|
||||||
clock_limits.min =
|
clock_limits.min = Some(min.clamp(
|
||||||
Some(min.clamp(range_min_or_fallback(&self.limits.clock_max, MIN_MAX_CLOCK), range_max_or_fallback(&self.limits.clock_min, MAX_CLOCK)));
|
range_min_or_fallback(&self.limits.clock_max, MIN_MAX_CLOCK),
|
||||||
|
range_max_or_fallback(&self.limits.clock_min, MAX_CLOCK),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
if let Some(max) = clock_limits.max {
|
if let Some(max) = clock_limits.max {
|
||||||
clock_limits.max =
|
clock_limits.max = Some(max.clamp(
|
||||||
Some(max.clamp(range_min_or_fallback(&self.limits.clock_max, MIN_MAX_CLOCK), range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK)));
|
range_min_or_fallback(&self.limits.clock_max, MIN_MAX_CLOCK),
|
||||||
|
range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -534,12 +569,15 @@ impl Cpu {
|
||||||
limits: oc_limits,
|
limits: oc_limits,
|
||||||
index: cpu_index,
|
index: cpu_index,
|
||||||
state: crate::state::steam_deck::Cpu::default(),
|
state: crate::state::steam_deck::Cpu::default(),
|
||||||
sysfs: Self::find_card_sysfs(None::<&'static str>)
|
sysfs: Self::find_card_sysfs(None::<&'static str>),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn system_default(cpu_index: usize) -> Self {
|
fn system_default(cpu_index: usize) -> Self {
|
||||||
Self::from_limits(cpu_index, GenericCpuLimit::default_for(&limits_core::json_v2::CpuLimitType::SteamDeck, cpu_index))
|
Self::from_limits(
|
||||||
|
cpu_index,
|
||||||
|
GenericCpuLimit::default_for(&limits_core::json_v2::CpuLimitType::SteamDeck, cpu_index),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn limits(&self) -> crate::api::CpuLimits {
|
fn limits(&self) -> crate::api::CpuLimits {
|
||||||
|
@ -578,7 +616,10 @@ impl Into<CpuJson> for Cpu {
|
||||||
online: self.online,
|
online: self.online,
|
||||||
clock_limits: self.clock_limits.map(|x| x.into()),
|
clock_limits: self.clock_limits.map(|x| x.into()),
|
||||||
governor: self.governor,
|
governor: self.governor,
|
||||||
root: self.sysfs.root().and_then(|p| p.as_ref().to_str().map(|r| r.to_owned()))
|
root: self
|
||||||
|
.sysfs
|
||||||
|
.root()
|
||||||
|
.and_then(|p| p.as_ref().to_str().map(|r| r.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
|
|
||||||
use sysfuss::{BasicEntityPath, HwMonPath, SysEntity, capability::attributes, SysEntityAttributes, SysEntityAttributesExt, SysAttribute};
|
use sysfuss::{
|
||||||
|
capability::attributes, BasicEntityPath, HwMonPath, SysAttribute, SysEntity,
|
||||||
|
SysEntityAttributes, SysEntityAttributesExt,
|
||||||
|
};
|
||||||
|
|
||||||
use limits_core::json_v2::GenericGpuLimit;
|
use limits_core::json_v2::GenericGpuLimit;
|
||||||
|
|
||||||
use super::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT;
|
use super::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT;
|
||||||
use crate::api::RangeLimit;
|
use crate::api::RangeLimit;
|
||||||
use crate::persist::GpuJson;
|
use crate::persist::GpuJson;
|
||||||
use crate::settings::{TGpu, ProviderBuilder};
|
|
||||||
use crate::settings::{min_max_from_json, MinMax};
|
use crate::settings::{min_max_from_json, MinMax};
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
|
use crate::settings::{ProviderBuilder, TGpu};
|
||||||
|
|
||||||
// usually in /sys/class/hwmon/hwmon4/<attribute>
|
// usually in /sys/class/hwmon/hwmon4/<attribute>
|
||||||
const SLOW_PPT_ATTRIBUTE: sysfuss::HwMonAttribute = sysfuss::HwMonAttribute::custom("power1_cap");
|
const SLOW_PPT_ATTRIBUTE: sysfuss::HwMonAttribute = sysfuss::HwMonAttribute::custom("power1_cap");
|
||||||
|
@ -60,7 +63,14 @@ const PPT_DIVISOR: u64 = 1_000;
|
||||||
impl Gpu {
|
impl Gpu {
|
||||||
fn find_card_sysfs(root: Option<impl AsRef<std::path::Path>>) -> BasicEntityPath {
|
fn find_card_sysfs(root: Option<impl AsRef<std::path::Path>>) -> BasicEntityPath {
|
||||||
let root = crate::settings::util::root_or_default_sysfs(root);
|
let root = crate::settings::util::root_or_default_sysfs(root);
|
||||||
match root.class("drm", attributes(crate::settings::util::CARD_NEEDS.into_iter().map(|s| s.to_string()))) {
|
match root.class(
|
||||||
|
"drm",
|
||||||
|
attributes(
|
||||||
|
crate::settings::util::CARD_NEEDS
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| s.to_string()),
|
||||||
|
),
|
||||||
|
) {
|
||||||
Ok(iter) => {
|
Ok(iter) => {
|
||||||
let card = iter
|
let card = iter
|
||||||
.filter(|ent| if let Ok(name) = ent.name() { name.starts_with("card")} else { false })
|
.filter(|ent| if let Ok(name) = ent.name() { name.starts_with("card")} else { false })
|
||||||
|
@ -70,11 +80,17 @@ impl Gpu {
|
||||||
log::error!("Failed to find SteamDeck gpu drm in sysfs (no results), using naive fallback");
|
log::error!("Failed to find SteamDeck gpu drm in sysfs (no results), using naive fallback");
|
||||||
BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0"))
|
BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0"))
|
||||||
});
|
});
|
||||||
log::info!("Found SteamDeck gpu drm in sysfs: {}", card.as_ref().display());
|
log::info!(
|
||||||
|
"Found SteamDeck gpu drm in sysfs: {}",
|
||||||
|
card.as_ref().display()
|
||||||
|
);
|
||||||
card
|
card
|
||||||
},
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to find SteamDeck gpu drm in sysfs ({}), using naive fallback", e);
|
log::error!(
|
||||||
|
"Failed to find SteamDeck gpu drm in sysfs ({}), using naive fallback",
|
||||||
|
e
|
||||||
|
);
|
||||||
BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0"))
|
BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,33 +98,47 @@ impl Gpu {
|
||||||
|
|
||||||
fn find_hwmon_sysfs(root: Option<impl AsRef<std::path::Path>>) -> HwMonPath {
|
fn find_hwmon_sysfs(root: Option<impl AsRef<std::path::Path>>) -> HwMonPath {
|
||||||
let root = crate::settings::util::root_or_default_sysfs(root);
|
let root = crate::settings::util::root_or_default_sysfs(root);
|
||||||
let hwmon = root.hwmon_by_name(super::util::GPU_HWMON_NAME).unwrap_or_else(|e| {
|
let hwmon = root
|
||||||
log::error!("Failed to find SteamDeck gpu hwmon in sysfs ({}), using naive fallback", e);
|
.hwmon_by_name(super::util::GPU_HWMON_NAME)
|
||||||
root.hwmon_by_index(4)
|
.unwrap_or_else(|e| {
|
||||||
});
|
log::error!(
|
||||||
log::info!("Found SteamDeck gpu hwmon {} in sysfs: {}", super::util::GPU_HWMON_NAME, hwmon.as_ref().display());
|
"Failed to find SteamDeck gpu hwmon in sysfs ({}), using naive fallback",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
root.hwmon_by_index(4)
|
||||||
|
});
|
||||||
|
log::info!(
|
||||||
|
"Found SteamDeck gpu hwmon {} in sysfs: {}",
|
||||||
|
super::util::GPU_HWMON_NAME,
|
||||||
|
hwmon.as_ref().display()
|
||||||
|
);
|
||||||
hwmon
|
hwmon
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_clock_limit(&self, speed: u64, mode: ClockType) -> Result<(), SettingError> {
|
fn set_clock_limit(&self, speed: u64, mode: ClockType) -> Result<(), SettingError> {
|
||||||
let payload = format!("s {} {}\n", mode as u8, speed);
|
let payload = format!("s {} {}\n", mode as u8, speed);
|
||||||
let path = GPU_CLOCK_LIMITS_ATTRIBUTE.path(&self.sysfs_card);
|
let path = GPU_CLOCK_LIMITS_ATTRIBUTE.path(&self.sysfs_card);
|
||||||
self.sysfs_card.set(GPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), &payload).map_err(|e| {
|
self.sysfs_card
|
||||||
SettingError {
|
.set(GPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), &payload)
|
||||||
msg: format!("Failed to write `{}` to `{}`: {}", &payload, path.display(), e),
|
.map_err(|e| SettingError {
|
||||||
|
msg: format!(
|
||||||
|
"Failed to write `{}` to `{}`: {}",
|
||||||
|
&payload,
|
||||||
|
path.display(),
|
||||||
|
e
|
||||||
|
),
|
||||||
setting: crate::settings::SettingVariant::Gpu,
|
setting: crate::settings::SettingVariant::Gpu,
|
||||||
}
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_confirm(&self) -> Result<(), SettingError> {
|
fn set_confirm(&self) -> Result<(), SettingError> {
|
||||||
let path = GPU_CLOCK_LIMITS_ATTRIBUTE.path(&self.sysfs_card);
|
let path = GPU_CLOCK_LIMITS_ATTRIBUTE.path(&self.sysfs_card);
|
||||||
self.sysfs_card.set(GPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), "c\n").map_err(|e| {
|
self.sysfs_card
|
||||||
SettingError {
|
.set(GPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), "c\n")
|
||||||
|
.map_err(|e| SettingError {
|
||||||
msg: format!("Failed to write `c` to `{}`: {}", path.display(), e),
|
msg: format!("Failed to write `c` to `{}`: {}", path.display(), e),
|
||||||
setting: crate::settings::SettingVariant::Gpu,
|
setting: crate::settings::SettingVariant::Gpu,
|
||||||
}
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_memory_clock_maxed(&self) -> bool {
|
fn is_memory_clock_maxed(&self) -> bool {
|
||||||
|
@ -116,7 +146,12 @@ impl Gpu {
|
||||||
if let Some(limit) = &self.limits.memory_clock {
|
if let Some(limit) = &self.limits.memory_clock {
|
||||||
if let Some(limit) = &limit.max {
|
if let Some(limit) = &limit.max {
|
||||||
if let Some(step) = &self.limits.memory_clock_step {
|
if let Some(step) = &self.limits.memory_clock_step {
|
||||||
log::debug!("chosen_clock: {}, limit_clock: {}, step: {}", clock, limit, step);
|
log::debug!(
|
||||||
|
"chosen_clock: {}, limit_clock: {}, step: {}",
|
||||||
|
clock,
|
||||||
|
limit,
|
||||||
|
step
|
||||||
|
);
|
||||||
return clock > &(limit - step);
|
return clock > &(limit - step);
|
||||||
} else {
|
} else {
|
||||||
log::debug!("chosen_clock: {}, limit_clock: {}", clock, limit);
|
log::debug!("chosen_clock: {}, limit_clock: {}", clock, limit);
|
||||||
|
@ -129,7 +164,10 @@ impl Gpu {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn quantize_memory_clock(&self, clock: u64) -> u64 {
|
fn quantize_memory_clock(&self, clock: u64) -> u64 {
|
||||||
if let Ok(f) = self.sysfs_card.read_value(GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.to_owned()) {
|
if let Ok(f) = self
|
||||||
|
.sysfs_card
|
||||||
|
.read_value(GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.to_owned())
|
||||||
|
{
|
||||||
let options = parse_pp_dpm_fclk(&String::from_utf8_lossy(&f));
|
let options = parse_pp_dpm_fclk(&String::from_utf8_lossy(&f));
|
||||||
// round (and find) nearest valid clock step
|
// round (and find) nearest valid clock step
|
||||||
// roughly price is right strategy (clock step will always be lower or equal to chosen)
|
// roughly price is right strategy (clock step will always be lower or equal to chosen)
|
||||||
|
@ -142,7 +180,7 @@ impl Gpu {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
return *current_val_opt as _;
|
return *current_val_opt as _;
|
||||||
} else {
|
} else {
|
||||||
return options[i-1].0 as _;
|
return options[i - 1].0 as _;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,9 +198,11 @@ impl Gpu {
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
let mut payload = String::from("0");
|
let mut payload = String::from("0");
|
||||||
for i in 1..max_val {
|
for i in 1..max_val {
|
||||||
write!(payload, " {}", i).expect("Failed to write to memory payload (should be infallible!?)");
|
write!(payload, " {}", i)
|
||||||
|
.expect("Failed to write to memory payload (should be infallible!?)");
|
||||||
}
|
}
|
||||||
write!(payload, " {}\n", max_val).expect("Failed to write to memory payload (should be infallible!?)");
|
write!(payload, " {}\n", max_val)
|
||||||
|
.expect("Failed to write to memory payload (should be infallible!?)");
|
||||||
payload
|
payload
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,11 +217,13 @@ impl Gpu {
|
||||||
self.state.clock_limits_set = true;
|
self.state.clock_limits_set = true;
|
||||||
// max clock
|
// max clock
|
||||||
if let Some(max) = clock_limits.max {
|
if let Some(max) = clock_limits.max {
|
||||||
self.set_clock_limit(max, ClockType::Max).unwrap_or_else(|e| errors.push(e));
|
self.set_clock_limit(max, ClockType::Max)
|
||||||
|
.unwrap_or_else(|e| errors.push(e));
|
||||||
}
|
}
|
||||||
// min clock
|
// min clock
|
||||||
if let Some(min) = clock_limits.min {
|
if let Some(min) = clock_limits.min {
|
||||||
self.set_clock_limit(min, ClockType::Min).unwrap_or_else(|e| errors.push(e));
|
self.set_clock_limit(min, ClockType::Min)
|
||||||
|
.unwrap_or_else(|e| errors.push(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.set_confirm().unwrap_or_else(|e| errors.push(e));
|
self.set_confirm().unwrap_or_else(|e| errors.push(e));
|
||||||
|
@ -195,11 +237,23 @@ impl Gpu {
|
||||||
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs_card)?;
|
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs_card)?;
|
||||||
// disable manual clock limits
|
// disable manual clock limits
|
||||||
// max clock
|
// max clock
|
||||||
self.set_clock_limit(self.limits.clock_max.and_then(|lim| lim.max).unwrap_or(MAX_CLOCK), ClockType::Max)
|
self.set_clock_limit(
|
||||||
.unwrap_or_else(|e| errors.push(e));
|
self.limits
|
||||||
|
.clock_max
|
||||||
|
.and_then(|lim| lim.max)
|
||||||
|
.unwrap_or(MAX_CLOCK),
|
||||||
|
ClockType::Max,
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|e| errors.push(e));
|
||||||
// min clock
|
// min clock
|
||||||
self.set_clock_limit(self.limits.clock_min.and_then(|lim| lim.min).unwrap_or(MIN_CLOCK), ClockType::Min)
|
self.set_clock_limit(
|
||||||
.unwrap_or_else(|e| errors.push(e));
|
self.limits
|
||||||
|
.clock_min
|
||||||
|
.and_then(|lim| lim.min)
|
||||||
|
.unwrap_or(MIN_CLOCK),
|
||||||
|
ClockType::Min,
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|e| errors.push(e));
|
||||||
|
|
||||||
self.set_confirm().unwrap_or_else(|e| errors.push(e));
|
self.set_confirm().unwrap_or_else(|e| errors.push(e));
|
||||||
} else {
|
} else {
|
||||||
|
@ -218,28 +272,37 @@ impl Gpu {
|
||||||
fn set_memory_speed(&self, clock: u64) -> Result<(), SettingError> {
|
fn set_memory_speed(&self, clock: u64) -> Result<(), SettingError> {
|
||||||
let path = GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.path(&self.sysfs_card);
|
let path = GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.path(&self.sysfs_card);
|
||||||
let payload = self.build_memory_clock_payload(clock);
|
let payload = self.build_memory_clock_payload(clock);
|
||||||
log::debug!("Generated payload for gpu fclk (memory): `{}` (is maxed? {})", payload, self.is_memory_clock_maxed());
|
log::debug!(
|
||||||
self.sysfs_card.set(GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.to_owned(), payload).map_err(|e| {
|
"Generated payload for gpu fclk (memory): `{}` (is maxed? {})",
|
||||||
SettingError {
|
payload,
|
||||||
|
self.is_memory_clock_maxed()
|
||||||
|
);
|
||||||
|
self.sysfs_card
|
||||||
|
.set(GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.to_owned(), payload)
|
||||||
|
.map_err(|e| SettingError {
|
||||||
msg: format!("Failed to write to `{}`: {}", path.display(), e),
|
msg: format!("Failed to write to `{}`: {}", path.display(), e),
|
||||||
setting: crate::settings::SettingVariant::Gpu,
|
setting: crate::settings::SettingVariant::Gpu,
|
||||||
}
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_force_performance_related(&mut self) -> Result<(), Vec<SettingError>> {
|
fn set_force_performance_related(&mut self) -> Result<(), Vec<SettingError>> {
|
||||||
let mut errors = Vec::new();
|
let mut errors = Vec::new();
|
||||||
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(!self.is_memory_clock_maxed() || self.clock_limits.is_some());
|
|
||||||
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT
|
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT
|
||||||
.enforce_level(&self.sysfs_card)
|
.set_gpu(!self.is_memory_clock_maxed() || self.clock_limits.is_some());
|
||||||
.unwrap_or_else(|mut e| errors.append(&mut e));
|
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT
|
||||||
|
.enforce_level(&self.sysfs_card)
|
||||||
|
.unwrap_or_else(|mut e| errors.append(&mut e));
|
||||||
// enable/disable downclock of GPU memory (to 400Mhz?)
|
// enable/disable downclock of GPU memory (to 400Mhz?)
|
||||||
self.set_memory_speed(
|
self.set_memory_speed(
|
||||||
self.memory_clock
|
self.memory_clock
|
||||||
.or_else(|| self.limits.memory_clock
|
.or_else(|| {
|
||||||
.map(|lim| lim.max.unwrap_or(MAX_MEMORY_CLOCK))
|
self.limits
|
||||||
).unwrap_or(MAX_MEMORY_CLOCK)
|
.memory_clock
|
||||||
).unwrap_or_else(|e| errors.push(e));
|
.map(|lim| lim.max.unwrap_or(MAX_MEMORY_CLOCK))
|
||||||
|
})
|
||||||
|
.unwrap_or(MAX_MEMORY_CLOCK),
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|e| errors.push(e));
|
||||||
self.set_clocks()
|
self.set_clocks()
|
||||||
.unwrap_or_else(|mut e| errors.append(&mut e));
|
.unwrap_or_else(|mut e| errors.append(&mut e));
|
||||||
// commit changes (if no errors have already occured)
|
// commit changes (if no errors have already occured)
|
||||||
|
@ -262,7 +325,8 @@ impl Gpu {
|
||||||
// set fast PPT
|
// set fast PPT
|
||||||
if let Some(fast_ppt) = &self.fast_ppt {
|
if let Some(fast_ppt) = &self.fast_ppt {
|
||||||
self.state.fast_ppt_set = true;
|
self.state.fast_ppt_set = true;
|
||||||
self.sysfs_hwmon.set(FAST_PPT_ATTRIBUTE, fast_ppt)
|
self.sysfs_hwmon
|
||||||
|
.set(FAST_PPT_ATTRIBUTE, fast_ppt)
|
||||||
.map_err(|e| SettingError {
|
.map_err(|e| SettingError {
|
||||||
msg: format!(
|
msg: format!(
|
||||||
"Failed to write `{}` to `{:?}`: {}",
|
"Failed to write `{}` to `{:?}`: {}",
|
||||||
|
@ -276,7 +340,8 @@ impl Gpu {
|
||||||
} else if self.state.fast_ppt_set {
|
} else if self.state.fast_ppt_set {
|
||||||
self.state.fast_ppt_set = false;
|
self.state.fast_ppt_set = false;
|
||||||
let fast_ppt = self.limits.fast_ppt_default.unwrap_or(MIDDLE_PPT);
|
let fast_ppt = self.limits.fast_ppt_default.unwrap_or(MIDDLE_PPT);
|
||||||
self.sysfs_hwmon.set(FAST_PPT_ATTRIBUTE, fast_ppt)
|
self.sysfs_hwmon
|
||||||
|
.set(FAST_PPT_ATTRIBUTE, fast_ppt)
|
||||||
.map_err(|e| SettingError {
|
.map_err(|e| SettingError {
|
||||||
msg: format!(
|
msg: format!(
|
||||||
"Failed to write `{}` to `{:?}`: {}",
|
"Failed to write `{}` to `{:?}`: {}",
|
||||||
|
@ -291,7 +356,8 @@ impl Gpu {
|
||||||
// set slow PPT
|
// set slow PPT
|
||||||
if let Some(slow_ppt) = &self.slow_ppt {
|
if let Some(slow_ppt) = &self.slow_ppt {
|
||||||
self.state.slow_ppt_set = true;
|
self.state.slow_ppt_set = true;
|
||||||
self.sysfs_hwmon.set(SLOW_PPT_ATTRIBUTE, slow_ppt)
|
self.sysfs_hwmon
|
||||||
|
.set(SLOW_PPT_ATTRIBUTE, slow_ppt)
|
||||||
.map_err(|e| SettingError {
|
.map_err(|e| SettingError {
|
||||||
msg: format!(
|
msg: format!(
|
||||||
"Failed to write `{}` to `{:?}`: {}",
|
"Failed to write `{}` to `{:?}`: {}",
|
||||||
|
@ -305,7 +371,8 @@ impl Gpu {
|
||||||
} else if self.state.slow_ppt_set {
|
} else if self.state.slow_ppt_set {
|
||||||
self.state.slow_ppt_set = false;
|
self.state.slow_ppt_set = false;
|
||||||
let slow_ppt = self.limits.slow_ppt_default.unwrap_or(MIDDLE_PPT);
|
let slow_ppt = self.limits.slow_ppt_default.unwrap_or(MIDDLE_PPT);
|
||||||
self.sysfs_hwmon.set(SLOW_PPT_ATTRIBUTE, slow_ppt)
|
self.sysfs_hwmon
|
||||||
|
.set(SLOW_PPT_ATTRIBUTE, slow_ppt)
|
||||||
.map_err(|e| SettingError {
|
.map_err(|e| SettingError {
|
||||||
msg: format!(
|
msg: format!(
|
||||||
"Failed to write `{}` to `{:?}`: {}",
|
"Failed to write `{}` to `{:?}`: {}",
|
||||||
|
@ -328,23 +395,72 @@ impl Gpu {
|
||||||
|
|
||||||
fn clamp_all(&mut self) {
|
fn clamp_all(&mut self) {
|
||||||
if let Some(fast_ppt) = &mut self.fast_ppt {
|
if let Some(fast_ppt) = &mut self.fast_ppt {
|
||||||
*fast_ppt = (*fast_ppt).clamp(self.limits.fast_ppt.and_then(|lim| lim.min).unwrap_or(MIN_FAST_PPT), self.limits.fast_ppt.and_then(|lim| lim.max).unwrap_or(MAX_FAST_PPT));
|
*fast_ppt = (*fast_ppt).clamp(
|
||||||
|
self.limits
|
||||||
|
.fast_ppt
|
||||||
|
.and_then(|lim| lim.min)
|
||||||
|
.unwrap_or(MIN_FAST_PPT),
|
||||||
|
self.limits
|
||||||
|
.fast_ppt
|
||||||
|
.and_then(|lim| lim.max)
|
||||||
|
.unwrap_or(MAX_FAST_PPT),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if let Some(slow_ppt) = &mut self.slow_ppt {
|
if let Some(slow_ppt) = &mut self.slow_ppt {
|
||||||
*slow_ppt = (*slow_ppt).clamp(self.limits.slow_ppt.and_then(|lim| lim.min).unwrap_or(MIN_SLOW_PPT), self.limits.slow_ppt.and_then(|lim| lim.max).unwrap_or(MAX_SLOW_PPT));
|
*slow_ppt = (*slow_ppt).clamp(
|
||||||
|
self.limits
|
||||||
|
.slow_ppt
|
||||||
|
.and_then(|lim| lim.min)
|
||||||
|
.unwrap_or(MIN_SLOW_PPT),
|
||||||
|
self.limits
|
||||||
|
.slow_ppt
|
||||||
|
.and_then(|lim| lim.max)
|
||||||
|
.unwrap_or(MAX_SLOW_PPT),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if let Some(clock_limits) = &mut self.clock_limits {
|
if let Some(clock_limits) = &mut self.clock_limits {
|
||||||
if let Some(min) = clock_limits.min {
|
if let Some(min) = clock_limits.min {
|
||||||
clock_limits.min =
|
clock_limits.min = Some(
|
||||||
Some(min.clamp(self.limits.clock_min.and_then(|lim| lim.min).unwrap_or(MIN_CLOCK), self.limits.clock_min.and_then(|lim| lim.max).unwrap_or(MAX_CLOCK)));
|
min.clamp(
|
||||||
|
self.limits
|
||||||
|
.clock_min
|
||||||
|
.and_then(|lim| lim.min)
|
||||||
|
.unwrap_or(MIN_CLOCK),
|
||||||
|
self.limits
|
||||||
|
.clock_min
|
||||||
|
.and_then(|lim| lim.max)
|
||||||
|
.unwrap_or(MAX_CLOCK),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if let Some(max) = clock_limits.max {
|
if let Some(max) = clock_limits.max {
|
||||||
clock_limits.max =
|
clock_limits.max = Some(
|
||||||
Some(max.clamp(self.limits.clock_max.and_then(|lim| lim.min).unwrap_or(MIN_CLOCK), self.limits.clock_max.and_then(|lim| lim.max).unwrap_or(MAX_CLOCK)));
|
max.clamp(
|
||||||
|
self.limits
|
||||||
|
.clock_max
|
||||||
|
.and_then(|lim| lim.min)
|
||||||
|
.unwrap_or(MIN_CLOCK),
|
||||||
|
self.limits
|
||||||
|
.clock_max
|
||||||
|
.and_then(|lim| lim.max)
|
||||||
|
.unwrap_or(MAX_CLOCK),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(mem_clock) = self.memory_clock {
|
if let Some(mem_clock) = self.memory_clock {
|
||||||
self.memory_clock = Some(mem_clock.clamp(self.limits.memory_clock.and_then(|lim| lim.min).unwrap_or(MIN_MEMORY_CLOCK), self.limits.memory_clock.and_then(|lim| lim.max).unwrap_or(MAX_MEMORY_CLOCK)));
|
self.memory_clock = Some(
|
||||||
|
mem_clock.clamp(
|
||||||
|
self.limits
|
||||||
|
.memory_clock
|
||||||
|
.and_then(|lim| lim.min)
|
||||||
|
.unwrap_or(MIN_MEMORY_CLOCK),
|
||||||
|
self.limits
|
||||||
|
.memory_clock
|
||||||
|
.and_then(|lim| lim.max)
|
||||||
|
.unwrap_or(MAX_MEMORY_CLOCK),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,7 +480,11 @@ impl Into<GpuJson> for Gpu {
|
||||||
tdp_boost: None,
|
tdp_boost: None,
|
||||||
clock_limits: self.clock_limits.map(|x| x.into()),
|
clock_limits: self.clock_limits.map(|x| x.into()),
|
||||||
memory_clock: self.memory_clock,
|
memory_clock: self.memory_clock,
|
||||||
root: self.sysfs_card.root().or(self.sysfs_hwmon.root()).and_then(|p| p.as_ref().to_str().map(|r| r.to_owned()))
|
root: self
|
||||||
|
.sysfs_card
|
||||||
|
.root()
|
||||||
|
.or(self.sysfs_hwmon.root())
|
||||||
|
.and_then(|p| p.as_ref().to_str().map(|r| r.to_owned())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -375,7 +495,9 @@ impl ProviderBuilder<GpuJson, GenericGpuLimit> for Gpu {
|
||||||
0 => Self {
|
0 => Self {
|
||||||
fast_ppt: persistent.fast_ppt,
|
fast_ppt: persistent.fast_ppt,
|
||||||
slow_ppt: persistent.slow_ppt,
|
slow_ppt: persistent.slow_ppt,
|
||||||
clock_limits: persistent.clock_limits.map(|x| min_max_from_json(x, version)),
|
clock_limits: persistent
|
||||||
|
.clock_limits
|
||||||
|
.map(|x| min_max_from_json(x, version)),
|
||||||
memory_clock: persistent.memory_clock,
|
memory_clock: persistent.memory_clock,
|
||||||
limits: limits,
|
limits: limits,
|
||||||
state: crate::state::steam_deck::Gpu::default(),
|
state: crate::state::steam_deck::Gpu::default(),
|
||||||
|
@ -386,7 +508,9 @@ impl ProviderBuilder<GpuJson, GenericGpuLimit> for Gpu {
|
||||||
_ => Self {
|
_ => Self {
|
||||||
fast_ppt: persistent.fast_ppt,
|
fast_ppt: persistent.fast_ppt,
|
||||||
slow_ppt: persistent.slow_ppt,
|
slow_ppt: persistent.slow_ppt,
|
||||||
clock_limits: persistent.clock_limits.map(|x| min_max_from_json(x, version)),
|
clock_limits: persistent
|
||||||
|
.clock_limits
|
||||||
|
.map(|x| min_max_from_json(x, version)),
|
||||||
memory_clock: persistent.memory_clock,
|
memory_clock: persistent.memory_clock,
|
||||||
limits: limits,
|
limits: limits,
|
||||||
state: crate::state::steam_deck::Gpu::default(),
|
state: crate::state::steam_deck::Gpu::default(),
|
||||||
|
@ -433,12 +557,16 @@ impl TGpu for Gpu {
|
||||||
fn limits(&self) -> crate::api::GpuLimits {
|
fn limits(&self) -> crate::api::GpuLimits {
|
||||||
crate::api::GpuLimits {
|
crate::api::GpuLimits {
|
||||||
fast_ppt_limits: Some(RangeLimit {
|
fast_ppt_limits: Some(RangeLimit {
|
||||||
min: super::util::range_min_or_fallback(&self.limits.fast_ppt, MIN_FAST_PPT) / self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR),
|
min: super::util::range_min_or_fallback(&self.limits.fast_ppt, MIN_FAST_PPT)
|
||||||
max: super::util::range_max_or_fallback(&self.limits.fast_ppt, MAX_FAST_PPT) / self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR),
|
/ self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR),
|
||||||
|
max: super::util::range_max_or_fallback(&self.limits.fast_ppt, MAX_FAST_PPT)
|
||||||
|
/ self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR),
|
||||||
}),
|
}),
|
||||||
slow_ppt_limits: Some(RangeLimit {
|
slow_ppt_limits: Some(RangeLimit {
|
||||||
min: super::util::range_min_or_fallback(&self.limits.slow_ppt, MIN_SLOW_PPT) / self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR),
|
min: super::util::range_min_or_fallback(&self.limits.slow_ppt, MIN_SLOW_PPT)
|
||||||
max: super::util::range_max_or_fallback(&self.limits.slow_ppt, MIN_SLOW_PPT) / self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR),
|
/ self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR),
|
||||||
|
max: super::util::range_max_or_fallback(&self.limits.slow_ppt, MIN_SLOW_PPT)
|
||||||
|
/ self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR),
|
||||||
}),
|
}),
|
||||||
ppt_step: self.limits.ppt_step.unwrap_or(1),
|
ppt_step: self.limits.ppt_step.unwrap_or(1),
|
||||||
tdp_limits: None,
|
tdp_limits: None,
|
||||||
|
@ -454,8 +582,14 @@ impl TGpu for Gpu {
|
||||||
}),
|
}),
|
||||||
clock_step: self.limits.clock_step.unwrap_or(100),
|
clock_step: self.limits.clock_step.unwrap_or(100),
|
||||||
memory_control: Some(RangeLimit {
|
memory_control: Some(RangeLimit {
|
||||||
min: super::util::range_min_or_fallback(&self.limits.memory_clock, MIN_MEMORY_CLOCK),
|
min: super::util::range_min_or_fallback(
|
||||||
max: super::util::range_max_or_fallback(&self.limits.memory_clock, MAX_MEMORY_CLOCK),
|
&self.limits.memory_clock,
|
||||||
|
MIN_MEMORY_CLOCK,
|
||||||
|
),
|
||||||
|
max: super::util::range_max_or_fallback(
|
||||||
|
&self.limits.memory_clock,
|
||||||
|
MAX_MEMORY_CLOCK,
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
memory_step: self.limits.memory_clock_step.unwrap_or(400),
|
memory_step: self.limits.memory_clock_step.unwrap_or(400),
|
||||||
}
|
}
|
||||||
|
@ -472,8 +606,10 @@ impl TGpu for Gpu {
|
||||||
|
|
||||||
fn get_ppt(&self) -> (Option<u64>, Option<u64>) {
|
fn get_ppt(&self) -> (Option<u64>, Option<u64>) {
|
||||||
(
|
(
|
||||||
self.fast_ppt.map(|x| x / self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR)),
|
self.fast_ppt
|
||||||
self.slow_ppt.map(|x| x / self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR)),
|
.map(|x| x / self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR)),
|
||||||
|
self.slow_ppt
|
||||||
|
.map(|x| x / self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,13 +637,16 @@ impl TGpu for Gpu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_pp_dpm_fclk(s: &str) -> Vec<(usize, usize)> { // (value, MHz)
|
fn parse_pp_dpm_fclk(s: &str) -> Vec<(usize, usize)> {
|
||||||
|
// (value, MHz)
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
for line in s.split('\n') {
|
for line in s.split('\n') {
|
||||||
if !line.is_empty() {
|
if !line.is_empty() {
|
||||||
if let Some((val, freq_mess)) = line.split_once(':') {
|
if let Some((val, freq_mess)) = line.split_once(':') {
|
||||||
if let Ok(val) = val.parse::<usize>() {
|
if let Ok(val) = val.parse::<usize>() {
|
||||||
if let Some((freq, _unit)) = freq_mess.trim().split_once(|c: char| !c.is_digit(10)) {
|
if let Some((freq, _unit)) =
|
||||||
|
freq_mess.trim().split_once(|c: char| !c.is_digit(10))
|
||||||
|
{
|
||||||
if let Ok(freq) = freq.parse::<usize>() {
|
if let Ok(freq) = freq.parse::<usize>() {
|
||||||
result.push((val, freq));
|
result.push((val, freq));
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,9 @@ mod util;
|
||||||
pub use battery::Battery;
|
pub use battery::Battery;
|
||||||
pub use cpu::Cpus;
|
pub use cpu::Cpus;
|
||||||
pub use gpu::Gpu;
|
pub use gpu::Gpu;
|
||||||
pub(self) use power_dpm_force::{POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT, DPM_FORCE_LIMITS_ATTRIBUTE};
|
pub(self) use power_dpm_force::{
|
||||||
|
DPM_FORCE_LIMITS_ATTRIBUTE, POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum Model {
|
pub enum Model {
|
||||||
|
@ -20,7 +22,15 @@ pub use util::flash_led;
|
||||||
fn _impl_checker() {
|
fn _impl_checker() {
|
||||||
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
||||||
|
|
||||||
impl_provider_builder::<Battery, crate::persist::BatteryJson, limits_core::json_v2::GenericBatteryLimit>();
|
impl_provider_builder::<
|
||||||
impl_provider_builder::<Cpus, Vec<crate::persist::CpuJson>, limits_core::json_v2::GenericCpusLimit>();
|
Battery,
|
||||||
|
crate::persist::BatteryJson,
|
||||||
|
limits_core::json_v2::GenericBatteryLimit,
|
||||||
|
>();
|
||||||
|
impl_provider_builder::<
|
||||||
|
Cpus,
|
||||||
|
Vec<crate::persist::CpuJson>,
|
||||||
|
limits_core::json_v2::GenericCpusLimit,
|
||||||
|
>();
|
||||||
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
use std::sync::atomic::{AtomicU64, Ordering};
|
use std::sync::atomic::{AtomicU64, Ordering};
|
||||||
|
|
||||||
use sysfuss::{BasicEntityPath, SysEntityAttributesExt, SysAttribute};
|
use sysfuss::{BasicEntityPath, SysAttribute, SysEntityAttributesExt};
|
||||||
|
|
||||||
use crate::settings::SettingError;
|
use crate::settings::SettingError;
|
||||||
|
|
||||||
|
@ -63,7 +63,8 @@ impl PDFPLManager {
|
||||||
let needs = self.needs_manual();
|
let needs = self.needs_manual();
|
||||||
let mut errors = Vec::new();
|
let mut errors = Vec::new();
|
||||||
let path = DPM_FORCE_LIMITS_ATTRIBUTE.path(entity);
|
let path = DPM_FORCE_LIMITS_ATTRIBUTE.path(entity);
|
||||||
let mode: String = entity.attribute(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned())
|
let mode: String = entity
|
||||||
|
.attribute(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned())
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
vec![SettingError {
|
vec![SettingError {
|
||||||
msg: format!("Failed to read `{}`: {}", path.display(), e),
|
msg: format!("Failed to read `{}`: {}", path.display(), e),
|
||||||
|
@ -73,7 +74,8 @@ impl PDFPLManager {
|
||||||
if mode != "manual" && needs {
|
if mode != "manual" && needs {
|
||||||
log::info!("Setting `{}` to manual", path.display());
|
log::info!("Setting `{}` to manual", path.display());
|
||||||
// set manual control
|
// set manual control
|
||||||
entity.set(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned(), "manual")
|
entity
|
||||||
|
.set(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned(), "manual")
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
errors.push(SettingError {
|
errors.push(SettingError {
|
||||||
msg: format!("Failed to write `manual` to `{}`: {}", path.display(), e),
|
msg: format!("Failed to write `manual` to `{}`: {}", path.display(), e),
|
||||||
|
@ -84,7 +86,8 @@ impl PDFPLManager {
|
||||||
} else if mode != "auto" && !needs {
|
} else if mode != "auto" && !needs {
|
||||||
log::info!("Setting `{}` to auto", path.display());
|
log::info!("Setting `{}` to auto", path.display());
|
||||||
// unset manual control
|
// unset manual control
|
||||||
entity.set(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned(), "auto")
|
entity
|
||||||
|
.set(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned(), "auto")
|
||||||
.map_err(|e| {
|
.map_err(|e| {
|
||||||
errors.push(SettingError {
|
errors.push(SettingError {
|
||||||
msg: format!("Failed to write `auto` to `{}`: {}", path.display(), e),
|
msg: format!("Failed to write `auto` to `{}`: {}", path.display(), e),
|
||||||
|
@ -93,10 +96,13 @@ impl PDFPLManager {
|
||||||
})
|
})
|
||||||
.unwrap_or(());
|
.unwrap_or(());
|
||||||
}
|
}
|
||||||
if let Ok(mode_now) =
|
if let Ok(mode_now) = entity.attribute::<String, _>(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned()) {
|
||||||
entity.attribute::<String, _>(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned())
|
log::debug!(
|
||||||
{
|
"Mode for `{}` is now `{}` ({:#b})",
|
||||||
log::debug!("Mode for `{}` is now `{}` ({:#b})", path.display(), mode_now, self.get());
|
path.display(),
|
||||||
|
mode_now,
|
||||||
|
self.get()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
log::debug!("Error getting new mode for debugging purposes");
|
log::debug!("Error getting new mode for debugging purposes");
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,16 +4,23 @@ pub const JUPITER_HWMON_NAME: &'static str = "jupiter";
|
||||||
pub const STEAMDECK_HWMON_NAME: &'static str = "steamdeck_hwmon";
|
pub const STEAMDECK_HWMON_NAME: &'static str = "steamdeck_hwmon";
|
||||||
pub const GPU_HWMON_NAME: &'static str = "amdgpu";
|
pub const GPU_HWMON_NAME: &'static str = "amdgpu";
|
||||||
|
|
||||||
pub fn range_min_or_fallback<I: Copy>(range: &Option<limits_core::json_v2::RangeLimit<I>>, fallback: I) -> I {
|
pub fn range_min_or_fallback<I: Copy>(
|
||||||
|
range: &Option<limits_core::json_v2::RangeLimit<I>>,
|
||||||
|
fallback: I,
|
||||||
|
) -> I {
|
||||||
range.and_then(|lim| lim.min).unwrap_or(fallback)
|
range.and_then(|lim| lim.min).unwrap_or(fallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn range_max_or_fallback<I: Copy>(range: &Option<limits_core::json_v2::RangeLimit<I>>, fallback: I) -> I {
|
pub fn range_max_or_fallback<I: Copy>(
|
||||||
|
range: &Option<limits_core::json_v2::RangeLimit<I>>,
|
||||||
|
fallback: I,
|
||||||
|
) -> I {
|
||||||
range.and_then(|lim| lim.max).unwrap_or(fallback)
|
range.and_then(|lim| lim.max).unwrap_or(fallback)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn card_also_has(card: &dyn sysfuss::SysEntity, extensions: &'static [&'static str]) -> bool {
|
pub fn card_also_has(card: &dyn sysfuss::SysEntity, extensions: &'static [&'static str]) -> bool {
|
||||||
extensions.iter()
|
extensions
|
||||||
|
.iter()
|
||||||
.all(|ext| card.as_ref().join(ext).exists())
|
.all(|ext| card.as_ref().join(ext).exists())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +38,11 @@ pub fn flash_led() {
|
||||||
let mut ec = smokepatio::ec::unnamed_power::UnnamedPowerEC::new();
|
let mut ec = smokepatio::ec::unnamed_power::UnnamedPowerEC::new();
|
||||||
for &code in THINGS {
|
for &code in THINGS {
|
||||||
let on = code != 0;
|
let on = code != 0;
|
||||||
let colour = if on { smokepatio::ec::unnamed_power::StaticColour::Red } else { smokepatio::ec::unnamed_power::StaticColour::Off };
|
let colour = if on {
|
||||||
|
smokepatio::ec::unnamed_power::StaticColour::Red
|
||||||
|
} else {
|
||||||
|
smokepatio::ec::unnamed_power::StaticColour::Off
|
||||||
|
};
|
||||||
if let Err(e) = ec.set(colour) {
|
if let Err(e) = ec.set(colour) {
|
||||||
log::error!("Thing err: {}", e);
|
log::error!("Thing err: {}", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,10 @@ pub trait TGeneral: OnSet + OnResume + OnPowerEvent + Debug + Send {
|
||||||
|
|
||||||
fn get_variant_info(&self) -> crate::api::VariantInfo;
|
fn get_variant_info(&self) -> crate::api::VariantInfo;
|
||||||
|
|
||||||
fn add_variant(&self, variant: crate::persist::SettingsJson) -> Result<Vec<crate::api::VariantInfo>, SettingError>;
|
fn add_variant(
|
||||||
|
&self,
|
||||||
|
variant: crate::persist::SettingsJson,
|
||||||
|
) -> Result<Vec<crate::api::VariantInfo>, SettingError>;
|
||||||
|
|
||||||
fn provider(&self) -> crate::persist::DriverJson;
|
fn provider(&self) -> crate::persist::DriverJson;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@ use std::convert::Into;
|
||||||
use limits_core::json_v2::GenericBatteryLimit;
|
use limits_core::json_v2::GenericBatteryLimit;
|
||||||
|
|
||||||
use crate::persist::BatteryJson;
|
use crate::persist::BatteryJson;
|
||||||
use crate::settings::{TBattery, ProviderBuilder};
|
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
|
use crate::settings::{ProviderBuilder, TBattery};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Battery;
|
pub struct Battery;
|
||||||
|
@ -29,7 +29,11 @@ impl Into<BatteryJson> for Battery {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
||||||
fn from_json_and_limits(_persistent: BatteryJson, _version: u64, _limits: GenericBatteryLimit) -> Self {
|
fn from_json_and_limits(
|
||||||
|
_persistent: BatteryJson,
|
||||||
|
_version: u64,
|
||||||
|
_limits: GenericBatteryLimit,
|
||||||
|
) -> Self {
|
||||||
Battery::system_default()
|
Battery::system_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ use limits_core::json_v2::GenericCpusLimit;
|
||||||
use crate::persist::CpuJson;
|
use crate::persist::CpuJson;
|
||||||
use crate::settings::MinMax;
|
use crate::settings::MinMax;
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
use crate::settings::{TCpu, TCpus, ProviderBuilder};
|
use crate::settings::{ProviderBuilder, TCpu, TCpus};
|
||||||
|
|
||||||
const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present";
|
const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present";
|
||||||
const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control";
|
const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control";
|
||||||
|
@ -146,7 +146,11 @@ impl Cpus {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
impl ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
||||||
fn from_json_and_limits(mut persistent: Vec<CpuJson>, version: u64, _limits: GenericCpusLimit) -> Self {
|
fn from_json_and_limits(
|
||||||
|
mut persistent: Vec<CpuJson>,
|
||||||
|
version: u64,
|
||||||
|
_limits: GenericCpusLimit,
|
||||||
|
) -> Self {
|
||||||
let (_, can_smt) = Self::system_smt_capabilities();
|
let (_, can_smt) = Self::system_smt_capabilities();
|
||||||
let mut result = Vec::with_capacity(persistent.len());
|
let mut result = Vec::with_capacity(persistent.len());
|
||||||
let max_cpus = Self::cpu_count();
|
let max_cpus = Self::cpu_count();
|
||||||
|
@ -284,7 +288,7 @@ impl Cpu {
|
||||||
.unwrap_or("schedutil".to_owned()),
|
.unwrap_or("schedutil".to_owned()),
|
||||||
index: cpu_index,
|
index: cpu_index,
|
||||||
state: crate::state::steam_deck::Cpu::default(),
|
state: crate::state::steam_deck::Cpu::default(),
|
||||||
root: "/".into()
|
root: "/".into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,15 +4,15 @@ use limits_core::json_v2::GenericGpuLimit;
|
||||||
|
|
||||||
use crate::persist::GpuJson;
|
use crate::persist::GpuJson;
|
||||||
use crate::settings::MinMax;
|
use crate::settings::MinMax;
|
||||||
use crate::settings::{TGpu, ProviderBuilder};
|
|
||||||
use crate::settings::{OnResume, OnSet, SettingError};
|
use crate::settings::{OnResume, OnSet, SettingError};
|
||||||
|
use crate::settings::{ProviderBuilder, TGpu};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Gpu {}
|
pub struct Gpu {}
|
||||||
|
|
||||||
impl Gpu {
|
impl Gpu {
|
||||||
pub fn system_default() -> Self {
|
pub fn system_default() -> Self {
|
||||||
Self { }
|
Self {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,15 @@ pub use gpu::Gpu;
|
||||||
fn _impl_checker() {
|
fn _impl_checker() {
|
||||||
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
||||||
|
|
||||||
impl_provider_builder::<Battery, crate::persist::BatteryJson, limits_core::json_v2::GenericBatteryLimit>();
|
impl_provider_builder::<
|
||||||
impl_provider_builder::<Cpus, Vec<crate::persist::CpuJson>, limits_core::json_v2::GenericCpusLimit>();
|
Battery,
|
||||||
|
crate::persist::BatteryJson,
|
||||||
|
limits_core::json_v2::GenericBatteryLimit,
|
||||||
|
>();
|
||||||
|
impl_provider_builder::<
|
||||||
|
Cpus,
|
||||||
|
Vec<crate::persist::CpuJson>,
|
||||||
|
limits_core::json_v2::GenericCpusLimit,
|
||||||
|
>();
|
||||||
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,7 @@ pub fn always_satisfied<'a, X>(_: &'a X) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const CARD_NEEDS: &[&'static str] = &[
|
pub const CARD_NEEDS: &[&'static str] = &["dev", "uevent"];
|
||||||
"dev",
|
|
||||||
"uevent"
|
|
||||||
];
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
|
@ -120,51 +120,66 @@ mod generate {
|
||||||
let limits = limits_core::json_v2::Limits {
|
let limits = limits_core::json_v2::Limits {
|
||||||
cpu: limits_core::json_v2::Limit {
|
cpu: limits_core::json_v2::Limit {
|
||||||
provider: limits_core::json_v2::CpuLimitType::SteamDeck,
|
provider: limits_core::json_v2::CpuLimitType::SteamDeck,
|
||||||
limits: limits_core::json_v2::GenericCpusLimit::default_for(limits_core::json_v2::CpuLimitType::SteamDeck),
|
limits: limits_core::json_v2::GenericCpusLimit::default_for(
|
||||||
|
limits_core::json_v2::CpuLimitType::SteamDeck,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
gpu: limits_core::json_v2::Limit {
|
gpu: limits_core::json_v2::Limit {
|
||||||
provider: limits_core::json_v2::GpuLimitType::SteamDeck,
|
provider: limits_core::json_v2::GpuLimitType::SteamDeck,
|
||||||
limits: limits_core::json_v2::GenericGpuLimit::default_for(limits_core::json_v2::GpuLimitType::SteamDeck),
|
limits: limits_core::json_v2::GenericGpuLimit::default_for(
|
||||||
|
limits_core::json_v2::GpuLimitType::SteamDeck,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
battery: limits_core::json_v2::Limit {
|
battery: limits_core::json_v2::Limit {
|
||||||
provider: limits_core::json_v2::BatteryLimitType::SteamDeck,
|
provider: limits_core::json_v2::BatteryLimitType::SteamDeck,
|
||||||
limits: limits_core::json_v2::GenericBatteryLimit::default_for(limits_core::json_v2::BatteryLimitType::SteamDeck),
|
limits: limits_core::json_v2::GenericBatteryLimit::default_for(
|
||||||
|
limits_core::json_v2::BatteryLimitType::SteamDeck,
|
||||||
|
),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let output_file = std::fs::File::create(format!("../{}", crate::consts::LIMITS_OVERRIDE_FILE)).unwrap();
|
let output_file =
|
||||||
ron::ser::to_writer_pretty(output_file, &limits, crate::utility::ron_pretty_config()).unwrap();
|
std::fs::File::create(format!("../{}", crate::consts::LIMITS_OVERRIDE_FILE)).unwrap();
|
||||||
|
ron::ser::to_writer_pretty(output_file, &limits, crate::utility::ron_pretty_config())
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn generate_default_minimal_save_file() {
|
fn generate_default_minimal_save_file() {
|
||||||
let mut mini_variants = std::collections::HashMap::with_capacity(2);
|
let mut mini_variants = std::collections::HashMap::with_capacity(2);
|
||||||
mini_variants.insert(0, crate::persist::SettingsJson {
|
mini_variants.insert(
|
||||||
version: 0,
|
0,
|
||||||
name: crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned(),
|
crate::persist::SettingsJson {
|
||||||
variant: 0,
|
version: 0,
|
||||||
persistent: false,
|
name: crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned(),
|
||||||
cpus: vec![crate::persist::CpuJson::default(); 8],
|
variant: 0,
|
||||||
gpu: crate::persist::GpuJson::default(),
|
persistent: false,
|
||||||
battery: crate::persist::BatteryJson::default(),
|
cpus: vec![crate::persist::CpuJson::default(); 8],
|
||||||
provider: None,
|
gpu: crate::persist::GpuJson::default(),
|
||||||
});
|
battery: crate::persist::BatteryJson::default(),
|
||||||
mini_variants.insert(42, crate::persist::SettingsJson {
|
provider: None,
|
||||||
version: 0,
|
},
|
||||||
name: "FortySecondary".to_owned(),
|
);
|
||||||
variant: 42,
|
mini_variants.insert(
|
||||||
persistent: false,
|
42,
|
||||||
cpus: vec![crate::persist::CpuJson::default(); 8],
|
crate::persist::SettingsJson {
|
||||||
gpu: crate::persist::GpuJson::default(),
|
version: 0,
|
||||||
battery: crate::persist::BatteryJson::default(),
|
name: "FortySecondary".to_owned(),
|
||||||
provider: None,
|
variant: 42,
|
||||||
});
|
persistent: false,
|
||||||
|
cpus: vec![crate::persist::CpuJson::default(); 8],
|
||||||
|
gpu: crate::persist::GpuJson::default(),
|
||||||
|
battery: crate::persist::BatteryJson::default(),
|
||||||
|
provider: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
let savefile = crate::persist::FileJson {
|
let savefile = crate::persist::FileJson {
|
||||||
version: 0,
|
version: 0,
|
||||||
name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
||||||
variants: mini_variants,
|
variants: mini_variants,
|
||||||
};
|
};
|
||||||
let output_file = std::fs::File::create(format!("../{}", crate::consts::DEFAULT_SETTINGS_FILE)).unwrap();
|
let output_file =
|
||||||
ron::ser::to_writer_pretty(output_file, &savefile, crate::utility::ron_pretty_config()).unwrap();
|
std::fs::File::create(format!("../{}", crate::consts::DEFAULT_SETTINGS_FILE)).unwrap();
|
||||||
|
ron::ser::to_writer_pretty(output_file, &savefile, crate::utility::ron_pretty_config())
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
162
src/index.tsx
162
src/index.tsx
|
@ -16,6 +16,8 @@ import {
|
||||||
Dropdown,
|
Dropdown,
|
||||||
SingleDropdownOption,
|
SingleDropdownOption,
|
||||||
Navigation,
|
Navigation,
|
||||||
|
Focusable,
|
||||||
|
Spinner,
|
||||||
//NotchLabel
|
//NotchLabel
|
||||||
//gamepadDialogClasses,
|
//gamepadDialogClasses,
|
||||||
//joinClassNames,
|
//joinClassNames,
|
||||||
|
@ -89,6 +91,7 @@ var startHook: any = null;
|
||||||
var endHook: any = null;
|
var endHook: any = null;
|
||||||
var userHook: any = null;
|
var userHook: any = null;
|
||||||
var usdplReady = false;
|
var usdplReady = false;
|
||||||
|
var isVariantLoading = false;
|
||||||
|
|
||||||
var tryNotifyProfileChange = function() {};
|
var tryNotifyProfileChange = function() {};
|
||||||
|
|
||||||
|
@ -343,6 +346,12 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
||||||
data: elem,
|
data: elem,
|
||||||
label: <span>{elem.name}</span>,
|
label: <span>{elem.name}</span>,
|
||||||
};});
|
};});
|
||||||
|
console.log("variant options", variantOptions);
|
||||||
|
console.log("current variant", get_value(CURRENT_VARIANT_GEN));
|
||||||
|
console.log("variant selected", variantOptions.find((val: SingleDropdownOption, _index, _arr) => {
|
||||||
|
backend.log(backend.LogLevel.Debug, "POWERTOOLS: looking for variant data.id " + (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).id.toString());
|
||||||
|
return (val.data as backend.VariantInfo).id == (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).id;
|
||||||
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PanelSection>
|
<PanelSection>
|
||||||
|
@ -383,83 +392,102 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
||||||
<Field
|
<Field
|
||||||
label={tr("Profile Variant")} // TODO translate
|
label={tr("Profile Variant")} // TODO translate
|
||||||
>
|
>
|
||||||
<Dropdown
|
{(!isVariantLoading && <Dropdown
|
||||||
menuLabel={tr("Profile Variant")}
|
menuLabel={tr("Profile Variant")}
|
||||||
rgOptions={variantOptions}
|
rgOptions={variantOptions}
|
||||||
selectedOption={variantOptions.find((val: SingleDropdownOption, _index, _arr) => {
|
selectedOption={variantOptions.find((val: SingleDropdownOption, _index, _arr) => {
|
||||||
backend.log(backend.LogLevel.Debug, "POWERTOOLS: looking for data " + (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).toString());
|
backend.log(backend.LogLevel.Debug, "POWERTOOLS: looking for variant data.id " + (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).id.toString());
|
||||||
return (val.data as backend.VariantInfo).id == (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).id;
|
return (val.data as backend.VariantInfo).id == (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).id;
|
||||||
})}
|
})}
|
||||||
strDefaultLabel={(get_value(VARIANTS_GEN) as backend.VariantInfo[])[0].name}
|
strDefaultLabel={(get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo | undefined)?.name?? (get_value(VARIANTS_GEN) as backend.VariantInfo[])[0].name}
|
||||||
onChange={(elem: SingleDropdownOption) => {
|
onChange={(elem: SingleDropdownOption) => {
|
||||||
let data = elem.data as backend.VariantInfo;
|
if (elem.data.id != (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).id) {
|
||||||
backend.log(backend.LogLevel.Debug, "Profile variant dropdown selected " + elem.data.toString());
|
isVariantLoading = true;
|
||||||
backend.loadGeneralSettingsVariant(data.id, data.name);
|
let data = elem.data as backend.VariantInfo;
|
||||||
set_value(CURRENT_VARIANT_GEN, elem.data as backend.VariantInfo);
|
backend.log(backend.LogLevel.Debug, "Profile variant dropdown selected " + elem.data.id.toString());
|
||||||
reloadGUI("ProfileVariantGovernor");
|
//set_value(CURRENT_VARIANT_GEN, elem.data as backend.VariantInfo);
|
||||||
|
backend.resolve(
|
||||||
|
backend.loadGeneralSettingsVariant(data.id, data.name),
|
||||||
|
(ok: boolean) => {
|
||||||
|
backend.log(backend.LogLevel.Debug, "Loaded settings variant ok? " + ok);
|
||||||
|
reload();
|
||||||
|
isVariantLoading = false;
|
||||||
|
backend.resolve(backend.waitForComplete(), (_) => {
|
||||||
|
backend.log(backend.LogLevel.Debug, "Trying to tell UI to re-render due to newly-selected settings variant");
|
||||||
|
tryNotifyProfileChange();
|
||||||
|
//reloadGUI("ProfileVariantSelected");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>)}
|
||||||
|
{(isVariantLoading && <Spinner/>)}
|
||||||
</Field>
|
</Field>
|
||||||
</PanelSectionRow>
|
</PanelSectionRow>
|
||||||
<PanelSectionRow style={{
|
<PanelSectionRow>
|
||||||
alignItems: "center",
|
<Focusable style={{
|
||||||
display: "flex",
|
alignItems: "center",
|
||||||
justifyContent: "space-around",
|
display: "flex",
|
||||||
}}>
|
justifyContent: "space-around",
|
||||||
<DialogButton
|
}}
|
||||||
style={{
|
flow-children="horizontal"
|
||||||
maxWidth: "30%",
|
>
|
||||||
minWidth: "auto",
|
<DialogButton
|
||||||
}}
|
style={{
|
||||||
//layout="below"
|
maxWidth: "30%",
|
||||||
onClick={(_: MouseEvent) => {
|
minWidth: "auto",
|
||||||
backend.log(backend.LogLevel.Debug, "Creating new PowerTools settings variant");
|
}}
|
||||||
backend.resolve(
|
//layout="below"
|
||||||
backend.loadGeneralSettingsVariant("please give me a new ID k thx bye" /* anything that cannot be parsed as a u64 will be set to u64::MAX, which will cause the back-end to auto-generate an ID */, undefined),
|
onClick={(_: MouseEvent) => {
|
||||||
(ok: boolean) => {
|
backend.log(backend.LogLevel.Debug, "Creating new PowerTools settings variant");
|
||||||
backend.log(backend.LogLevel.Debug, "New settings variant ok? " + ok);
|
backend.resolve(
|
||||||
reload();
|
backend.loadGeneralSettingsVariant("please give me a new ID k thx bye" /* anything that cannot be parsed as a u64 will be set to u64::MAX, which will cause the back-end to auto-generate an ID */, undefined),
|
||||||
backend.resolve(backend.waitForComplete(), (_) => {
|
(ok: boolean) => {
|
||||||
backend.log(backend.LogLevel.Debug, "Trying to tell UI to re-render due to new settings variant");
|
backend.log(backend.LogLevel.Debug, "New settings variant ok? " + ok);
|
||||||
tryNotifyProfileChange();
|
reload();
|
||||||
});
|
backend.resolve(backend.waitForComplete(), (_) => {
|
||||||
|
backend.log(backend.LogLevel.Debug, "Trying to tell UI to re-render due to new settings variant");
|
||||||
|
tryNotifyProfileChange();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<HiPlus/>
|
||||||
|
</DialogButton>
|
||||||
|
<DialogButton
|
||||||
|
style={{
|
||||||
|
maxWidth: "30%",
|
||||||
|
minWidth: "auto",
|
||||||
|
}}
|
||||||
|
//layout="below"
|
||||||
|
onClick={(_: MouseEvent) => {
|
||||||
|
const steamId = get_value(INTERNAL_STEAM_ID);
|
||||||
|
const steamName = get_value(INTERNAL_STEAM_USERNAME);
|
||||||
|
if (steamId && steamName) {
|
||||||
|
backend.storeUpload(steamId, steamName);
|
||||||
|
} else {
|
||||||
|
backend.log(backend.LogLevel.Warn, "Cannot upload with null steamID (is null: " + !steamId + ") and/or username (is null: " + !steamName + ")");
|
||||||
}
|
}
|
||||||
);
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<HiUpload/>
|
||||||
<HiPlus/>
|
</DialogButton>
|
||||||
</DialogButton>
|
<DialogButton
|
||||||
<DialogButton
|
style={{
|
||||||
style={{
|
maxWidth: "30%",
|
||||||
maxWidth: "30%",
|
minWidth: "auto",
|
||||||
minWidth: "auto",
|
}}
|
||||||
}}
|
//layout="below"
|
||||||
//layout="below"
|
onClick={(_: MouseEvent) => {
|
||||||
onClick={(_: MouseEvent) => {
|
Navigation.Navigate(STORE_RESULTS_URI);
|
||||||
const steamId = get_value(INTERNAL_STEAM_ID);
|
Navigation.CloseSideMenus();
|
||||||
const steamName = get_value(INTERNAL_STEAM_USERNAME);
|
}}
|
||||||
if (steamId && steamName) {
|
>
|
||||||
backend.storeUpload(steamId, steamName);
|
<TbWorldPlus />
|
||||||
} else {
|
</DialogButton>
|
||||||
backend.log(backend.LogLevel.Warn, "Cannot upload with null steamID (is null: " + !steamId + ") and/or username (is null: " + !steamName + ")");
|
</Focusable>
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<HiUpload/>
|
|
||||||
</DialogButton>
|
|
||||||
<DialogButton
|
|
||||||
style={{
|
|
||||||
maxWidth: "30%",
|
|
||||||
minWidth: "auto",
|
|
||||||
}}
|
|
||||||
//layout="below"
|
|
||||||
onClick={(_: MouseEvent) => {
|
|
||||||
Navigation.Navigate(STORE_RESULTS_URI);
|
|
||||||
Navigation.CloseSideMenus();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<TbWorldPlus />
|
|
||||||
</DialogButton>
|
|
||||||
</PanelSectionRow>
|
</PanelSectionRow>
|
||||||
|
|
||||||
<Debug idc={idc}/>
|
<Debug idc={idc}/>
|
||||||
|
|
Loading…
Reference in a new issue