diff --git a/backend/src/api/api_types.rs b/backend/src/api/api_types.rs index 8854656..7d8e6bf 100644 --- a/backend/src/api/api_types.rs +++ b/backend/src/api/api_types.rs @@ -67,4 +67,5 @@ pub struct GpuLimits { pub struct VariantInfo { pub id: String, pub name: String, + pub id_num: u64, } diff --git a/backend/src/api/general.rs b/backend/src/api/general.rs index 2fb27d4..feda6af 100644 --- a/backend/src/api/general.rs +++ b/backend/src/api/general.rs @@ -59,7 +59,13 @@ pub fn load_settings( sender .lock() .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") }; 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(variant_id)) = params_in.get(2) { if let Some(Primitive::String(variant_name)) = params_in.get(3) { - setter(id.parse().unwrap_or_default(), - name.to_owned(), - variant_id.parse().unwrap_or_default(), - Some(variant_name.to_owned())); + setter( + id.parse().unwrap_or_default(), + name.to_owned(), + variant_id.parse().unwrap_or_default(), + Some(variant_name.to_owned()), + ); vec![true.into()] } else { - setter(id.parse().unwrap_or_default(), - name.to_owned(), - variant_id.parse().unwrap_or_default(), - None); + setter( + id.parse().unwrap_or_default(), + name.to_owned(), + variant_id.parse().unwrap_or_default(), + None, + ); vec![true.into()] } } else { @@ -101,26 +111,32 @@ pub fn load_variant( ) -> impl Fn(super::ApiParameterType) -> super::ApiParameterType { let sender = Mutex::new(sender); // Sender is not Sync; this is required for safety let setter = move |variant: u64, variant_name: Option| { + log::debug!("load_variant(variant: {}, variant_name: {:?})", variant, variant_name); sender .lock() .unwrap() - .send(ApiMessage::LoadVariant(variant, variant_name.unwrap_or_else(|| crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned()))) - .expect("load_settings send failed") + .send(ApiMessage::LoadVariant( + variant, + variant_name + .unwrap_or_else(|| "".to_owned()), + )) + .expect("load_variant send failed") }; move |params_in: super::ApiParameterType| { if let Some(Primitive::String(variant_id)) = params_in.get(0) { if let Some(Primitive::String(variant_name)) = params_in.get(1) { - setter(variant_id.parse().unwrap_or(u64::MAX), - Some(variant_name.to_owned())); + setter( + variant_id.parse().unwrap_or(u64::MAX), + Some(variant_name.to_owned()), + ); vec![true.into()] } else { - setter(variant_id.parse().unwrap_or_default(), - None); + setter(variant_id.parse().unwrap_or(u64::MAX), None); vec![true.into()] } } else { - log::warn!("load_settings missing variant id parameter"); - vec!["load_settings missing variant id parameter".into()] + log::warn!("load_variant missing variant id parameter"); + vec!["load_variant missing variant id parameter".into()] } } } @@ -375,32 +391,60 @@ pub fn get_periodicals(sender: Sender) -> impl AsyncCallable { let sender2 = sender.clone(); move || { 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_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_charge_now, callback_charge_now) = + build_comms("battery charge now 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 sender_locked = sender2 - .lock() - .unwrap(); - let curr = wait_for_response(&*sender_locked, rx_curr, - ApiMessage::Battery(super::handler::BatteryMessage::ReadCurrentNow(callback_curr)), "battery current"); - let charge_now = wait_for_response(&*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 sender_locked = sender2.lock().unwrap(); + let curr = wait_for_response( + &*sender_locked, + rx_curr, + ApiMessage::Battery(super::handler::BatteryMessage::ReadCurrentNow( + callback_curr, + )), + "battery current", + ); + let charge_now = wait_for_response( + &*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, - ApiMessage::General(GeneralMessage::GetPath(callback_path)), "general get path"); + let settings_path = wait_for_response( + &*sender_locked, + rx_path, + ApiMessage::General(GeneralMessage::GetPath(callback_path)), + "general get path", + ); vec![ super::utility::map_optional(curr), super::utility::map_optional(charge_now), super::utility::map_optional(charge_full), super::utility::map_optional(charge_power), - super::utility::map_optional(settings_path.to_str()), ] } @@ -411,13 +455,20 @@ pub fn get_periodicals(sender: Sender) -> impl AsyncCallable { } } -fn build_comms<'a, T: Send + 'a>(msg: &'static str) -> (mpsc::Receiver, Box) { +fn build_comms<'a, T: Send + 'a>( + msg: &'static str, +) -> (mpsc::Receiver, Box) { let (tx, rx) = mpsc::channel(); let callback = move |t: T| tx.send(t).expect(msg); (rx, Box::new(callback)) } -fn wait_for_response(sender: &Sender, rx: mpsc::Receiver, api_msg: ApiMessage, op: &str) -> T { +fn wait_for_response( + sender: &Sender, + rx: mpsc::Receiver, + api_msg: ApiMessage, + op: &str, +) -> T { sender.send(api_msg).expect(&format!("{} send failed", op)); rx.recv().expect(&format!("{} callback recv failed", op)) } @@ -429,8 +480,10 @@ pub fn get_all_variants(sender: Sender) -> impl AsyncCallable { let sender2 = sender.clone(); move || { let (tx, rx) = mpsc::channel(); - let callback = - move |variants: Vec| tx.send(variants).expect("get_all_variants callback send failed"); + let callback = move |variants: Vec| { + tx.send(variants) + .expect("get_all_variants callback send failed") + }; sender2 .lock() .unwrap() @@ -438,7 +491,9 @@ pub fn get_all_variants(sender: Sender) -> impl AsyncCallable { Box::new(callback), ))) .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 { @@ -446,7 +501,10 @@ pub fn get_all_variants(sender: Sender) -> impl AsyncCallable { trans_getter: |result| { let mut output = Vec::with_capacity(result.len()); 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 }, @@ -460,8 +518,10 @@ pub fn get_current_variant(sender: Sender) -> impl AsyncCallable { let sender2 = sender.clone(); move || { let (tx, rx) = mpsc::channel(); - let callback = - move |variant: super::VariantInfo| tx.send(variant).expect("get_all_variants callback send failed"); + let callback = move |variant: super::VariantInfo| { + tx.send(variant) + .expect("get_all_variants callback send failed") + }; sender2 .lock() .unwrap() @@ -475,7 +535,9 @@ pub fn get_current_variant(sender: Sender) -> impl AsyncCallable { super::async_utils::AsyncIshGetter { set_get: getter, 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"), + )] }, } } diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index 95fba2c..194b179 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -66,7 +66,10 @@ impl BatteryMessage { /// Message instructs the driver to modify settings 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), GetCurrentVariant(Callback), GetAllVariants(Callback>), - AddVariant(crate::persist::SettingsJson, Callback>), + AddVariant( + crate::persist::SettingsJson, + Callback>, + ), ApplyNow, } @@ -248,11 +254,14 @@ impl GeneralMessage { Self::AddVariant(variant, cb) => match settings.add_variant(variant) { Ok(variants) => cb(variants), 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)) - }, + } }, - Self::ApplyNow => {}, + Self::ApplyNow => {} } dirty } @@ -300,13 +309,21 @@ impl ApiMessageHandler { // save log::debug!("api_worker is saving..."); let is_persistent = *settings.general.persistent(); - let save_path = - crate::utility::settings_dir().join(settings.general.get_path()); + let save_path = crate::utility::settings_dir().join(settings.general.get_path()); if is_persistent { let settings_clone = settings.json(); 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()) { - log::error!("Failed to create/update settings file {}: {}", save_path.display(), e); + 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(), + ) { + log::error!( + "Failed to create/update settings file {}: {}", + save_path.display(), + e + ); } //unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings"); log::debug!("Saved settings to {}", save_path.display()); @@ -393,8 +410,15 @@ impl ApiMessageHandler { ApiMessage::LoadVariant(variant_id, variant_name) => { let path = settings.general.get_path(); 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) { - Ok(success) => log::info!("Loaded settings file? {}", success), + match settings.load_file( + 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), } true @@ -414,7 +438,11 @@ impl ApiMessageHandler { true } 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 } ApiMessage::GetLimits(cb) => { @@ -434,13 +462,18 @@ impl ApiMessageHandler { _ => settings.general.provider(), }); false - }, + } ApiMessage::UploadCurrentVariant(steam_id, steam_username) => { //TODO 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 - }, + } } } diff --git a/backend/src/api/message.rs b/backend/src/api/message.rs index 3ac093e..0a7b435 100644 --- a/backend/src/api/message.rs +++ b/backend/src/api/message.rs @@ -1,14 +1,17 @@ -use std::sync::{atomic::{AtomicU64, Ordering}, Arc}; +use std::sync::{ + atomic::{AtomicU64, Ordering}, + Arc, +}; use serde::{Deserialize, Serialize}; -use usdpl_back::AsyncCallable; use usdpl_back::core::serdes::Primitive; +use usdpl_back::AsyncCallable; use limits_core::json::DeveloperMessage; -use crate::MESSAGE_SEEN_ID_FILE; use crate::utility::settings_dir; +use crate::MESSAGE_SEEN_ID_FILE; #[derive(Serialize, Deserialize)] pub struct ApiMessage { @@ -34,7 +37,10 @@ impl std::convert::From for ApiMessage { } fn get_dev_messages() -> Vec { - 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 { @@ -43,8 +49,12 @@ pub struct MessageHandler { impl MessageHandler { 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)) { - if last_seen_id_bytes.len() >= 8 /* bytes in u64 */ { + let last_seen_id = if let Ok(last_seen_id_bytes) = + std::fs::read(settings_dir().join(MESSAGE_SEEN_ID_FILE)) + { + if last_seen_id_bytes.len() >= 8 + /* bytes in u64 */ + { u64::from_le_bytes([ last_seen_id_bytes[0], last_seen_id_bytes[1], @@ -73,7 +83,7 @@ impl MessageHandler { }, AsyncMessageDismisser { seen: self.seen.clone(), - } + }, ) } } @@ -83,8 +93,17 @@ pub struct AsyncMessageGetter { } impl AsyncMessageGetter { - fn remove_before_id(id: u64, messages: impl Iterator) -> impl Iterator { - messages.skip_while(move |msg| if let Some(msg_id) = msg.id { msg_id <= id } else { true }) + fn remove_before_id( + id: u64, + messages: impl Iterator, + ) -> impl Iterator { + messages.skip_while(move |msg| { + if let Some(msg_id) = msg.id { + msg_id <= id + } else { + true + } + }) } } diff --git a/backend/src/api/web.rs b/backend/src/api/web.rs index 81d5cb0..385ec92 100644 --- a/backend/src/api/web.rs +++ b/backend/src/api/web.rs @@ -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); match ureq::get(&req_url).call() { Ok(response) => { - let json_res: std::io::Result> = response.into_json(); + let json_res: std::io::Result> = + response.into_json(); match json_res { Ok(search_results) => { // 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) { - 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, } } @@ -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 { version: crate::persist::LATEST_VERSION, 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 persistent: true, - cpus: meta.config.cpus.into_iter().map(|cpu| crate::persist::CpuJson { - online: cpu.online, - clock_limits: cpu.clock_limits.map(|lim| crate::persist::MinMaxJson { - min: lim.min, - max: lim.max, - }), - governor: cpu.governor, - root: None, - }).collect(), + cpus: meta + .config + .cpus + .into_iter() + .map(|cpu| crate::persist::CpuJson { + online: cpu.online, + clock_limits: cpu.clock_limits.map(|lim| crate::persist::MinMaxJson { + min: lim.min, + max: lim.max, + }), + governor: cpu.governor, + root: None, + }) + .collect(), gpu: crate::persist::GpuJson { fast_ppt: meta.config.gpu.fast_ppt, slow_ppt: meta.config.gpu.slow_ppt, tdp: meta.config.gpu.tdp, tdp_boost: meta.config.gpu.tdp_boost, - clock_limits: meta.config.gpu.clock_limits.map(|lim| crate::persist::MinMaxJson { - min: lim.min, - max: lim.max, - }), + clock_limits: meta + .config + .gpu + .clock_limits + .map(|lim| crate::persist::MinMaxJson { + min: lim.min, + max: lim.max, + }), memory_clock: meta.config.gpu.memory_clock, root: None, }, battery: crate::persist::BatteryJson { charge_rate: meta.config.battery.charge_rate, charge_mode: meta.config.battery.charge_mode, - events: meta.config.battery.events.into_iter().map(|be| crate::persist::BatteryEventJson { - charge_rate: be.charge_rate, - charge_mode: be.charge_mode, - trigger: be.trigger, - }).collect(), + events: meta + .config + .battery + .events + .into_iter() + .map(|be| crate::persist::BatteryEventJson { + charge_rate: be.charge_rate, + charge_mode: be.charge_mode, + trigger: be.trigger, + }) + .collect(), root: None, }, 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 { let req_url = format!("{}/api/setting/by_id/{}", BASE_URL, id); - let response = ureq::get(&req_url).call() - .map_err(|e| { - log::warn!("GET to {} failed: {}", req_url, e); - std::io::Error::new(std::io::ErrorKind::ConnectionAborted, e) - })?; + let response = ureq::get(&req_url).call().map_err(|e| { + log::warn!("GET to {} failed: {}", req_url, e); + std::io::Error::new(std::io::ErrorKind::ConnectionAborted, e) + })?; response.into_json() } -pub fn upload_settings(id: u64, user_id: String, username: String, settings: crate::persist::SettingsJson) { - log::info!("Uploading settings {} by {} ({})", settings.name, username, user_id); +pub fn upload_settings( + 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() { Ok(id) => id, 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; } }; @@ -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 { name: settings.name, 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()], id: "".to_owned(), config: community_settings_core::v1::Config { - cpus: settings.cpus.into_iter().map(|cpu| community_settings_core::v1::Cpu { - online: cpu.online, - clock_limits: cpu.clock_limits.map(|lim| community_settings_core::v1::MinMax { - min: lim.min, - max: lim.max, - }), - governor: cpu.governor, - }).collect(), + cpus: settings + .cpus + .into_iter() + .map(|cpu| community_settings_core::v1::Cpu { + online: cpu.online, + clock_limits: cpu + .clock_limits + .map(|lim| community_settings_core::v1::MinMax { + min: lim.min, + max: lim.max, + }), + governor: cpu.governor, + }) + .collect(), gpu: community_settings_core::v1::Gpu { fast_ppt: settings.gpu.fast_ppt, slow_ppt: settings.gpu.slow_ppt, tdp: settings.gpu.tdp, tdp_boost: settings.gpu.tdp_boost, - clock_limits: settings.gpu.clock_limits.map(|lim| community_settings_core::v1::MinMax { - min: lim.min, - max: lim.max, + clock_limits: settings.gpu.clock_limits.map(|lim| { + community_settings_core::v1::MinMax { + min: lim.min, + max: lim.max, + } }), memory_clock: settings.gpu.memory_clock, }, battery: community_settings_core::v1::Battery { charge_rate: settings.battery.charge_rate, charge_mode: settings.battery.charge_mode, - events: settings.battery.events.into_iter().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(), + events: settings + .battery + .events + .into_iter() + .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) -> impl AsyncCallable { match download_config(id) { Ok(meta) => { let (tx, rx) = mpsc::channel(); - let callback = - move |values: Vec| tx.send(values).expect("download_new_config callback send failed"); + let callback = move |values: Vec| { + tx.send(values) + .expect("download_new_config callback send failed") + }; sender2 .lock() .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"); return rx.recv().expect("download_new_config callback recv failed"); - }, + } Err(e) => { log::error!("Invalid response from download: {}", e); } @@ -194,7 +252,10 @@ pub fn download_new_config(sender: Sender) -> impl AsyncCallable { if let Some(Primitive::String(id)) = params.get(0) { match id.parse::() { 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 { Err("download_new_config missing/invalid parameter 0".to_owned()) @@ -204,7 +265,10 @@ pub fn download_new_config(sender: Sender) -> impl AsyncCallable { trans_getter: |result| { let mut output = Vec::with_capacity(result.len()); 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 }, @@ -238,8 +302,6 @@ pub fn upload_current_variant(sender: Sender) -> impl AsyncCallable } }, set_get: getter, - trans_getter: |result| { - vec![result.into()] - }, + trans_getter: |result| vec![result.into()], } } diff --git a/backend/src/consts.rs b/backend/src/consts.rs index 531ce20..502f6ce 100644 --- a/backend/src/consts.rs +++ b/backend/src/consts.rs @@ -10,5 +10,4 @@ pub const DEFAULT_SETTINGS_VARIANT_NAME: &str = "Primary"; pub const LIMITS_FILE: &str = "limits_cache.ron"; pub const LIMITS_OVERRIDE_FILE: &str = "limits_override.ron"; - pub const MESSAGE_SEEN_ID_FILE: &str = "seen_message.bin"; diff --git a/backend/src/main.rs b/backend/src/main.rs index 3a52085..0a245ca 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -76,14 +76,29 @@ fn main() -> Result<(), ()> { let mut loaded_settings = persist::FileJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE)) - .map(|mut file| file.variants.remove(&0) - .map(|settings| settings::Settings::from_json(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()))) + .map(|mut file| { + let mut keys: Vec = file.variants.keys().map(|x| *x).collect(); + keys.sort(); + keys.get(0) + .and_then(|id| file.variants.remove(id)) + .map(|settings| { + settings::Settings::from_json( + 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(|_| { settings::Settings::system_default( DEFAULT_SETTINGS_FILE.into(), @@ -96,7 +111,8 @@ fn main() -> Result<(), ()> { log::info!( "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); @@ -307,29 +323,26 @@ fn main() -> Result<(), ()> { ) .register_async( "GENERAL_get_periodicals", - api::general::get_periodicals(api_sender.clone()) + api::general::get_periodicals(api_sender.clone()), ) .register_async( "GENERAL_get_all_variants", - api::general::get_all_variants(api_sender.clone()) + api::general::get_all_variants(api_sender.clone()), ) .register_async( "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_dismiss", message_dismisser) - .register_async( - "WEB_search_by_app", - api::web::search_by_app_id() - ) + .register_async("WEB_search_by_app", api::web::search_by_app_id()) .register_async( "WEB_download_new", - api::web::download_new_config(api_sender.clone()) + api::web::download_new_config(api_sender.clone()), ) .register_async( "WEB_upload_new", - api::web::upload_current_variant(api_sender.clone()) + api::web::upload_current_variant(api_sender.clone()), ); utility::ioperm_power_ec(); diff --git a/backend/src/persist/file.rs b/backend/src/persist/file.rs index c4a4010..0999517 100644 --- a/backend/src/persist/file.rs +++ b/backend/src/persist/file.rs @@ -22,7 +22,8 @@ impl FileJson { std::fs::create_dir_all(parent).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 { if path.exists() { // 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 { - self.variants.keys() - .max() - .map(|k| k+1) - .unwrap_or(0) + self.variants.keys().max().map(|k| k + 1).unwrap_or(0) } - pub fn update_variant_or_create>(path: P, app_id: u64, mut setting: SettingsJson, given_name: String) -> Result { - if !setting.persistent { - return Self::open(path) - } + pub fn update_variant_or_create>( + path: P, + 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 file = if path.exists() { + if !setting.persistent { 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 { setting.variant = file.next_available_id(); } - file.variants.insert(setting.variant, setting); - file + // Generate new name if empty + 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 { + // 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); - setting_variants.insert(setting.variant, setting); - Self { + setting_variants.insert(setting.variant, setting.clone()); + (Self { version: 0, app_id: app_id, - name: given_name, + name: app_name, variants: setting_variants, - } + }, setting) }; file.save(path)?; - Ok(file) + Ok((file, variant_id)) } } diff --git a/backend/src/persist/general.rs b/backend/src/persist/general.rs index d3f7ab4..fe18898 100644 --- a/backend/src/persist/general.rs +++ b/backend/src/persist/general.rs @@ -4,7 +4,7 @@ use serde::{Deserialize, Serialize}; use super::{BatteryJson, CpuJson, DriverJson, GpuJson}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone)] pub struct SettingsJson { pub version: u64, pub name: String, diff --git a/backend/src/settings/detect/auto_detect.rs b/backend/src/settings/detect/auto_detect.rs index 31ded4d..5ee8e4b 100644 --- a/backend/src/settings/detect/auto_detect.rs +++ b/backend/src/settings/detect/auto_detect.rs @@ -5,7 +5,7 @@ use regex::RegexBuilder; use limits_core::json_v2::{BatteryLimitType, CpuLimitType, GpuLimitType, Limits}; 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 { let limits_path = super::utility::limits_path(); @@ -151,20 +151,22 @@ pub fn auto_detect0( if let Some(settings) = &settings_opt { *general_driver.persistent() = true; let cpu_driver: Box = match relevant_limits.cpu.provider { - CpuLimitType::SteamDeck => { - Box::new(crate::settings::steam_deck::Cpus::from_json_and_limits( + CpuLimitType::SteamDeck => Box::new( + crate::settings::steam_deck::Cpus::from_json_and_limits( settings.cpus.clone(), settings.version, relevant_limits.cpu.limits, - ).variant(super::super::steam_deck::Model::LCD)) - } - CpuLimitType::SteamDeckOLED => { - Box::new(crate::settings::steam_deck::Cpus::from_json_and_limits( + ) + .variant(super::super::steam_deck::Model::LCD), + ), + CpuLimitType::SteamDeckOLED => Box::new( + crate::settings::steam_deck::Cpus::from_json_and_limits( settings.cpus.clone(), settings.version, 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::< crate::settings::generic::Cpu, >::from_json_and_limits( @@ -172,20 +174,20 @@ pub fn auto_detect0( settings.version, relevant_limits.cpu.limits, )), - CpuLimitType::GenericAMD => Box::new( - crate::settings::generic_amd::Cpus::from_json_and_limits( + CpuLimitType::GenericAMD => { + Box::new(crate::settings::generic_amd::Cpus::from_json_and_limits( settings.cpus.clone(), settings.version, relevant_limits.cpu.limits, - ), - ), + )) + } CpuLimitType::Unknown => { Box::new(crate::settings::unknown::Cpus::from_json_and_limits( settings.cpus.clone(), settings.version, relevant_limits.cpu.limits, )) - }, + } CpuLimitType::DevMode => { Box::new(crate::settings::dev_mode::Cpus::from_json_and_limits( settings.cpus.clone(), @@ -196,20 +198,22 @@ pub fn auto_detect0( }; let gpu_driver: Box = match relevant_limits.gpu.provider { - GpuLimitType::SteamDeck => { - Box::new(crate::settings::steam_deck::Gpu::from_json_and_limits( + GpuLimitType::SteamDeck => Box::new( + crate::settings::steam_deck::Gpu::from_json_and_limits( settings.gpu.clone(), settings.version, relevant_limits.gpu.limits, - ).variant(super::super::steam_deck::Model::LCD)) - } - GpuLimitType::SteamDeckOLED => { - Box::new(crate::settings::steam_deck::Gpu::from_json_and_limits( + ) + .variant(super::super::steam_deck::Model::LCD), + ), + GpuLimitType::SteamDeckOLED => Box::new( + crate::settings::steam_deck::Gpu::from_json_and_limits( settings.gpu.clone(), settings.version, relevant_limits.gpu.limits, - ).variant(super::super::steam_deck::Model::OLED)) - } + ) + .variant(super::super::steam_deck::Model::OLED), + ), GpuLimitType::Generic => { Box::new(crate::settings::generic::Gpu::from_json_and_limits( settings.gpu.clone(), @@ -217,20 +221,20 @@ pub fn auto_detect0( relevant_limits.gpu.limits, )) } - GpuLimitType::GenericAMD => Box::new( - crate::settings::generic_amd::Gpu::from_json_and_limits( + GpuLimitType::GenericAMD => { + Box::new(crate::settings::generic_amd::Gpu::from_json_and_limits( settings.gpu.clone(), settings.version, relevant_limits.gpu.limits, - ), - ), + )) + } GpuLimitType::Unknown => { Box::new(crate::settings::unknown::Gpu::from_json_and_limits( settings.gpu.clone(), settings.version, relevant_limits.gpu.limits, )) - }, + } GpuLimitType::DevMode => { Box::new(crate::settings::dev_mode::Gpu::from_json_and_limits( settings.gpu.clone(), @@ -240,34 +244,36 @@ pub fn auto_detect0( } }; let battery_driver: Box = match relevant_limits.battery.provider { - BatteryLimitType::SteamDeck => { - Box::new(crate::settings::steam_deck::Battery::from_json_and_limits( + BatteryLimitType::SteamDeck => 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::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, - ), + ) + .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::Unknown => { Box::new(crate::settings::unknown::Battery::from_json_and_limits( settings.battery.clone(), settings.version, relevant_limits.battery.limits, )) - }, + } BatteryLimitType::DevMode => { Box::new(crate::settings::dev_mode::Battery::from_json_and_limits( settings.battery.clone(), @@ -285,62 +291,78 @@ pub fn auto_detect0( }; } else { let cpu_driver: Box = match relevant_limits.cpu.provider { - CpuLimitType::SteamDeck => { - Box::new(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::Generic => { - Box::new(crate::settings::generic::Cpus::< - crate::settings::generic::Cpu, - >::from_limits(relevant_limits.cpu.limits)) - } - CpuLimitType::GenericAMD => { - Box::new(crate::settings::generic_amd::Cpus::from_limits(relevant_limits.cpu.limits)) - } - CpuLimitType::Unknown => { - Box::new(crate::settings::unknown::Cpus::from_limits(relevant_limits.cpu.limits)) - } - CpuLimitType::DevMode => { - Box::new(crate::settings::dev_mode::Cpus::from_limits(relevant_limits.cpu.limits)) - } + CpuLimitType::SteamDeck => Box::new( + 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::Generic => Box::new(crate::settings::generic::Cpus::< + crate::settings::generic::Cpu, + >::from_limits( + relevant_limits.cpu.limits + )), + CpuLimitType::GenericAMD => Box::new( + crate::settings::generic_amd::Cpus::from_limits(relevant_limits.cpu.limits), + ), + CpuLimitType::Unknown => Box::new(crate::settings::unknown::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 = match relevant_limits.gpu.provider { - GpuLimitType::SteamDeck => { - Box::new(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::Generic => { - Box::new(crate::settings::generic::Gpu::from_limits(relevant_limits.gpu.limits)) - } - GpuLimitType::GenericAMD => { - Box::new(crate::settings::generic_amd::Gpu::from_limits(relevant_limits.gpu.limits)) - } - GpuLimitType::Unknown => { - Box::new(crate::settings::unknown::Gpu::from_limits(relevant_limits.gpu.limits)) - } - GpuLimitType::DevMode => { - Box::new(crate::settings::dev_mode::Gpu::from_limits(relevant_limits.gpu.limits)) - } + GpuLimitType::SteamDeck => Box::new( + 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::Generic => Box::new(crate::settings::generic::Gpu::from_limits( + relevant_limits.gpu.limits, + )), + GpuLimitType::GenericAMD => Box::new( + crate::settings::generic_amd::Gpu::from_limits(relevant_limits.gpu.limits), + ), + GpuLimitType::Unknown => Box::new(crate::settings::unknown::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 = match relevant_limits.battery.provider { - BatteryLimitType::SteamDeck => { - Box::new(crate::settings::steam_deck::Battery::from_limits(relevant_limits.battery.limits).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::SteamDeck => Box::new( + crate::settings::steam_deck::Battery::from_limits( + relevant_limits.battery.limits, + ) + .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 => { - 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 => { - 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 => { - 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 { diff --git a/backend/src/settings/detect/limits_worker.rs b/backend/src/settings/detect/limits_worker.rs index ad10f56..3665b11 100644 --- a/backend/src/settings/detect/limits_worker.rs +++ b/backend/src/settings/detect/limits_worker.rs @@ -93,14 +93,16 @@ pub fn get_limits_cached() -> Base { fn save_base(new_base: &Base, path: impl AsRef) { let limits_path = path.as_ref(); match std::fs::File::create(&limits_path) { - Ok(f) => match ron::ser::to_writer_pretty(f, &new_base, crate::utility::ron_pretty_config()) { - Ok(_) => log::info!("Successfully saved new limits to {}", limits_path.display()), - Err(e) => log::error!( - "Failed to save limits json to file `{}`: {}", - limits_path.display(), - e - ), - }, + Ok(f) => { + match ron::ser::to_writer_pretty(f, &new_base, crate::utility::ron_pretty_config()) { + Ok(_) => log::info!("Successfully saved new limits to {}", limits_path.display()), + Err(e) => log::error!( + "Failed to save limits json to file `{}`: {}", + limits_path.display(), + e + ), + } + } Err(e) => log::error!("Cannot create {}: {}", limits_path.display(), e), } } diff --git a/backend/src/settings/detect/utility.rs b/backend/src/settings/detect/utility.rs index 7f14b5f..27d37a8 100644 --- a/backend/src/settings/detect/utility.rs +++ b/backend/src/settings/detect/utility.rs @@ -1,4 +1,4 @@ -use limits_core::json::{DeveloperMessage, Base}; +use limits_core::json::{Base, DeveloperMessage}; pub fn limits_path() -> std::path::PathBuf { crate::utility::settings_dir().join(crate::consts::LIMITS_FILE) diff --git a/backend/src/settings/dev_mode/battery.rs b/backend/src/settings/dev_mode/battery.rs index ac7cf79..a57e736 100644 --- a/backend/src/settings/dev_mode/battery.rs +++ b/backend/src/settings/dev_mode/battery.rs @@ -3,8 +3,8 @@ use std::convert::Into; use limits_core::json_v2::GenericBatteryLimit; use crate::persist::BatteryJson; -use crate::settings::{TBattery, ProviderBuilder}; use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::{ProviderBuilder, TBattery}; #[derive(Clone)] pub struct Battery { @@ -32,7 +32,11 @@ impl Into for Battery { } impl ProviderBuilder 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 { persist, version, @@ -43,7 +47,12 @@ impl ProviderBuilder for Battery { fn from_limits(limits: GenericBatteryLimit) -> Self { 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, limits, charge_limit: None, @@ -71,10 +80,16 @@ impl TBattery for Battery { fn limits(&self) -> crate::api::BatteryLimits { log::debug!("dev_mode_Battery::limits(self) -> {{...}}"); 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_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, } } @@ -90,7 +105,10 @@ impl TBattery for Battery { } fn get_charge_rate(&self) -> Option { - 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 } @@ -100,7 +118,10 @@ impl TBattery for Battery { } fn get_charge_mode(&self) -> Option { - 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() } @@ -135,7 +156,10 @@ impl TBattery for Battery { } fn get_charge_limit(&self) -> Option { - 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 } diff --git a/backend/src/settings/dev_mode/cpu.rs b/backend/src/settings/dev_mode/cpu.rs index c278fe1..a505b69 100644 --- a/backend/src/settings/dev_mode/cpu.rs +++ b/backend/src/settings/dev_mode/cpu.rs @@ -1,11 +1,11 @@ use std::convert::Into; -use limits_core::json_v2::{GenericCpusLimit, GenericCpuLimit}; +use limits_core::json_v2::{GenericCpuLimit, GenericCpusLimit}; use crate::persist::CpuJson; use crate::settings::MinMax; use crate::settings::{OnResume, OnSet, SettingError}; -use crate::settings::{TCpu, TCpus, ProviderBuilder}; +use crate::settings::{ProviderBuilder, TCpu, TCpus}; #[derive(Debug, Clone)] pub struct Cpus { @@ -40,13 +40,22 @@ impl OnResume for Cpus { impl crate::settings::OnPowerEvent for Cpus {} impl ProviderBuilder, GenericCpusLimit> for Cpus { - fn from_json_and_limits(persistent: Vec, version: u64, limits: GenericCpusLimit) -> Self { + fn from_json_and_limits( + persistent: Vec, + version: u64, + limits: GenericCpusLimit, + ) -> Self { let mut cpus = Vec::with_capacity(persistent.len()); 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(|| { - log::warn!("No cpu limit for index {}, using default", i); - Default::default() - }))); + cpus.push(Cpu::from_json_and_limits( + cpu.to_owned(), + 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); Self { @@ -78,7 +87,12 @@ impl TCpus for Cpus { cpus: self.cpus.iter().map(|x| x.limits()).collect(), count: self.cpus.len(), 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 { #[inline] - pub fn from_json_and_limits(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 }); + pub fn from_json_and_limits( + 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 { 0 => Self { persist: other, @@ -153,7 +175,12 @@ impl Cpu { #[inline] pub fn from_limits(i: usize, limits: GenericCpuLimit) -> 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, index: i, limits, @@ -163,10 +190,21 @@ impl Cpu { fn limits(&self) -> 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_max_limits: self.limits.clock_max.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(4200), max: lim.max.unwrap_or(4300) }), + 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_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), - 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>) { log::debug!("dev_mode_Cpu::clock_limits(self, {:?})", 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> { - 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() } } diff --git a/backend/src/settings/dev_mode/gpu.rs b/backend/src/settings/dev_mode/gpu.rs index b9f6e76..919d905 100644 --- a/backend/src/settings/dev_mode/gpu.rs +++ b/backend/src/settings/dev_mode/gpu.rs @@ -4,8 +4,8 @@ use limits_core::json_v2::GenericGpuLimit; use crate::persist::GpuJson; use crate::settings::MinMax; -use crate::settings::{TGpu, ProviderBuilder}; use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::{ProviderBuilder, TGpu}; #[derive(Clone)] pub struct Gpu { @@ -27,7 +27,10 @@ impl std::fmt::Debug for Gpu { impl ProviderBuilder for Gpu { 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 { persist, version, @@ -83,16 +86,37 @@ impl TGpu for Gpu { let ppt_divisor = self.limits.ppt_divisor.unwrap_or(1_000_000); let tdp_divisor = self.limits.tdp_divisor.unwrap_or(1_000_000); 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 }), - 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 }), + 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, + }), + 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), - 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_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_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_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), - 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_max_limits: self.limits.clock_max.map(|lim| crate::api::RangeLimit { min: lim.min.unwrap_or(1100), max: lim.max.unwrap_or(4200) }), + 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_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), - 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), } } @@ -103,24 +127,41 @@ impl TGpu for Gpu { } fn ppt(&mut self, fast: Option, slow: Option) { - 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.slow_ppt = slow; } fn get_ppt(&self) -> (Option, Option) { - 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) } fn clock_limits(&mut self, limits: Option>) { log::debug!("dev_mode_Gpu::clock_limits(self, {:?})", 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> { - 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() } @@ -130,7 +171,10 @@ impl TGpu for Gpu { } fn get_memory_clock(&self) -> Option { - 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 } diff --git a/backend/src/settings/dev_mode/mod.rs b/backend/src/settings/dev_mode/mod.rs index 200c1ea..58b6ac1 100644 --- a/backend/src/settings/dev_mode/mod.rs +++ b/backend/src/settings/dev_mode/mod.rs @@ -9,7 +9,15 @@ pub use gpu::Gpu; fn _impl_checker() { fn impl_provider_builder, J, L>() {} - impl_provider_builder::(); - impl_provider_builder::, limits_core::json_v2::GenericCpusLimit>(); + impl_provider_builder::< + Battery, + crate::persist::BatteryJson, + limits_core::json_v2::GenericBatteryLimit, + >(); + impl_provider_builder::< + Cpus, + Vec, + limits_core::json_v2::GenericCpusLimit, + >(); impl_provider_builder::(); } diff --git a/backend/src/settings/driver.rs b/backend/src/settings/driver.rs index adae096..128cf30 100644 --- a/backend/src/settings/driver.rs +++ b/backend/src/settings/driver.rs @@ -20,7 +20,13 @@ impl Driver { 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) } } diff --git a/backend/src/settings/general.rs b/backend/src/settings/general.rs index d1d913a..b873b0a 100644 --- a/backend/src/settings/general.rs +++ b/backend/src/settings/general.rs @@ -4,7 +4,7 @@ use std::path::PathBuf; //use super::{Battery, Cpus, Gpu}; use super::{OnResume, OnSet, SettingError}; use super::{TBattery, TCpus, TGeneral, TGpu}; -use crate::persist::{SettingsJson, FileJson}; +use crate::persist::{FileJson, SettingsJson}; //use crate::utility::unwrap_lock; const LATEST_VERSION: u64 = 0; @@ -103,11 +103,14 @@ impl TGeneral for General { } fn get_variants(&self) -> Vec { - if let Ok(file) = crate::persist::FileJson::open(self.get_path()) { - file.variants.into_iter() + let json_path = crate::utility::settings_dir().join(self.get_path()); + if let Ok(file) = crate::persist::FileJson::open(json_path) { + file.variants + .into_iter() .map(|(id, conf)| crate::api::VariantInfo { id: id.to_string(), name: conf.name, + id_num: id, }) .collect() } else { @@ -115,25 +118,40 @@ impl TGeneral for General { } } - fn add_variant(&self, variant: crate::persist::SettingsJson) -> Result, SettingError> { + fn add_variant( + &self, + variant: crate::persist::SettingsJson, + ) -> Result, SettingError> { let variant_name = variant.name.clone(); - crate::persist::FileJson::update_variant_or_create(self.get_path(), self.get_app_id(), variant, variant_name) - .map_err(|e| SettingError { - msg: format!("failed to add variant: {}", e), - setting: SettingVariant::General, - }) - .map(|file| file.variants.into_iter() + let json_path = crate::utility::settings_dir().join(self.get_path()); + crate::persist::FileJson::update_variant_or_create( + json_path, + self.get_app_id(), + variant, + 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 { id: id.to_string(), name: conf.name, + id_num: id, }) - .collect()) + .collect() + }) } fn get_variant_info(&self) -> crate::api::VariantInfo { + log::debug!("Current variant `{}` ({})", self.variant_name, self.variant_id); crate::api::VariantInfo { id: self.variant_id.to_string(), 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 { - let driver = super::Driver::system_default(json_path, app_id, name, variant_id, variant_name); + pub fn system_default( + 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 { general: driver.general, cpus: driver.cpus, @@ -210,19 +235,47 @@ impl Settings { } 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.gpu = driver.gpu; self.battery = driver.battery; 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) { 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 { 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, }) } @@ -240,13 +293,8 @@ impl Settings { let json_path = crate::utility::settings_dir().join(&filename); if json_path.exists() { if variant == u64::MAX { - *self.general.persistent() = true; - let file_json = FileJson::update_variant_or_create(&json_path, app_id, self.json(), variant_name.clone()).map_err(|e| SettingError { - 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); + log::debug!("Creating new variant `{}` in existing settings file {}", variant_name, json_path.display()); + self.create_and_load_variant(&json_path, app_id, variant_name)?; } else { let file_json = FileJson::open(&json_path).map_err(|e| SettingError { msg: format!("Failed to open settings {}: {}", json_path.display(), e), @@ -261,31 +309,61 @@ impl Settings { ); *self.general.persistent() = false; self.general.name(name); + self.general.variant_name(settings_json.name.clone()); + self.general.variant_id(settings_json.variant); } else { 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.cpus = x.cpus; self.gpu = x.gpu; self.battery = x.battery; } } - } else { if system_defaults { - self.load_system_default(name, variant, variant_name); + self.load_system_default(name, variant, variant_name.clone()); } else { 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; + 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.path(filename); - self.general.variant_id(variant); 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 { let json_path = crate::utility::settings_dir().join(filename); diff --git a/backend/src/settings/generic/battery.rs b/backend/src/settings/generic/battery.rs index af08b11..cfe201a 100644 --- a/backend/src/settings/generic/battery.rs +++ b/backend/src/settings/generic/battery.rs @@ -4,8 +4,8 @@ use limits_core::json_v2::GenericBatteryLimit; use sysfuss::{SysEntity, SysEntityAttributesExt}; use crate::persist::BatteryJson; -use crate::settings::{TBattery, ProviderBuilder}; use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::{ProviderBuilder, TBattery}; #[derive(Debug, Clone)] pub struct Battery { @@ -21,7 +21,10 @@ impl Into for Battery { charge_rate: None, charge_mode: None, 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 { - match self.sysfs.attribute::(sysfuss::PowerSupplyAttribute::VoltageMax) { - Ok(x) => Some(x/1000000.0), + match self + .sysfs + .attribute::(sysfuss::PowerSupplyAttribute::VoltageMax) + { + Ok(x) => Some(x / 1000000.0), 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 - Ok(x) => Some(x/1000000.0), + match sysfuss::SysEntityRawExt::attribute::<_, f64, _>( + &self.sysfs, + "voltage_min_design".to_owned(), + ) { + // Framework 13 AMD + Ok(x) => Some(x / 1000000.0), Err(e) => { log::debug!("get_design_voltage voltage_min_design err: {}", e); - match self.sysfs.attribute::(sysfuss::PowerSupplyAttribute::VoltageMin) { - Ok(x) => Some(x/1000000.0), + match self + .sysfs + .attribute::(sysfuss::PowerSupplyAttribute::VoltageMin) + { + Ok(x) => Some(x / 1000000.0), Err(e) => { log::debug!("get_design_voltage voltage_min err: {}", e); None @@ -90,7 +103,7 @@ impl ProviderBuilder for Battery { // TODO Self { 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 { if let Some(battery_voltage) = self.get_design_voltage() { - match self.sysfs.attribute::(sysfuss::PowerSupplyAttribute::ChargeFull) { - Ok(x) => Some(x/1000000.0 * battery_voltage), + match self + .sysfs + .attribute::(sysfuss::PowerSupplyAttribute::ChargeFull) + { + Ok(x) => Some(x / 1000000.0 * battery_voltage), Err(e) => { log::warn!("read_charge_full err: {}", e); None @@ -162,8 +178,11 @@ impl TBattery for Battery { fn read_charge_now(&self) -> Option { if let Some(battery_voltage) = self.get_design_voltage() { - match self.sysfs.attribute::(sysfuss::PowerSupplyAttribute::ChargeNow) { - Ok(x) => Some(x/1000000.0 * battery_voltage), + match self + .sysfs + .attribute::(sysfuss::PowerSupplyAttribute::ChargeNow) + { + Ok(x) => Some(x / 1000000.0 * battery_voltage), Err(e) => { log::warn!("read_charge_now err: {}", e); None @@ -176,8 +195,11 @@ impl TBattery for Battery { fn read_charge_design(&self) -> Option { if let Some(battery_voltage) = self.get_design_voltage() { - match self.sysfs.attribute::(sysfuss::PowerSupplyAttribute::ChargeFullDesign) { - Ok(x) => Some(x/1000000.0 * battery_voltage), + match self + .sysfs + .attribute::(sysfuss::PowerSupplyAttribute::ChargeFullDesign) + { + Ok(x) => Some(x / 1000000.0 * battery_voltage), Err(e) => { log::warn!("read_charge_design err: {}", e); None @@ -189,8 +211,11 @@ impl TBattery for Battery { } fn read_current_now(&self) -> Option { - match self.sysfs.attribute::(sysfuss::PowerSupplyAttribute::CurrentNow) { - Ok(x) => Some(x/1000.0), // expects mA, reads uA + match self + .sysfs + .attribute::(sysfuss::PowerSupplyAttribute::CurrentNow) + { + Ok(x) => Some(x / 1000.0), // expects mA, reads uA Err(e) => { log::warn!("read_current_now err: {}", e); None diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index 75d0d1e..0083028 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -1,13 +1,13 @@ use std::convert::{AsMut, AsRef, Into}; -use limits_core::json_v2::{GenericCpusLimit, GenericCpuLimit}; +use limits_core::json_v2::{GenericCpuLimit, GenericCpusLimit}; use super::FromGenericCpuInfo; use crate::api::RangeLimit; use crate::persist::CpuJson; use crate::settings::{min_max_from_json, MinMax}; use crate::settings::{OnResume, OnSet, SettingError}; -use crate::settings::{TCpu, TCpus, ProviderBuilder}; +use crate::settings::{ProviderBuilder, TCpu, TCpus}; const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; @@ -89,8 +89,14 @@ impl + AsRef + TCpu + FromGenericCpuInfo> Cpus { } } -impl + AsRef + TCpu + FromGenericCpuInfo> ProviderBuilder, GenericCpusLimit> for Cpus { - fn from_json_and_limits(mut other: Vec, version: u64, limits: GenericCpusLimit) -> Self { +impl + AsRef + TCpu + FromGenericCpuInfo> + ProviderBuilder, GenericCpusLimit> for Cpus +{ + fn from_json_and_limits( + mut other: Vec, + version: u64, + limits: GenericCpusLimit, + ) -> Self { let (_, can_smt) = Self::system_smt_capabilities(); let mut result = Vec::with_capacity(other.len()); let max_cpus = Self::cpu_count(); @@ -103,9 +109,12 @@ impl + AsRef + TCpu + FromGenericCpuInfo> ProviderBuilder + AsRef + TCpu + FromGenericCpuInfo> ProviderBuilder 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()) } } diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs index 3e2b5cf..1cc61db 100644 --- a/backend/src/settings/generic/gpu.rs +++ b/backend/src/settings/generic/gpu.rs @@ -5,9 +5,9 @@ use sysfuss::{BasicEntityPath, SysEntity}; use crate::api::RangeLimit; use crate::persist::GpuJson; -use crate::settings::{TGpu, ProviderBuilder}; use crate::settings::{min_max_from_json, MinMax}; use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::{ProviderBuilder, TGpu}; #[derive(Debug, Clone)] pub struct Gpu { @@ -38,15 +38,17 @@ impl Gpu { fn find_card_sysfs(root: Option>) -> BasicEntityPath { let root = crate::settings::util::root_or_default_sysfs(root); match root.class("drm", crate::settings::util::always_satisfied) { - Ok(mut iter) => { - iter.next() - .unwrap_or_else(|| { - 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")) - }) - }, + Ok(mut iter) => iter.next().unwrap_or_else(|| { + 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")) + }), 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")) } } @@ -56,7 +58,9 @@ impl Gpu { impl ProviderBuilder for Gpu { 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() { - persistent.clock_limits.map(|x| min_max_from_json(x, version)) + persistent + .clock_limits + .map(|x| min_max_from_json(x, version)) } else { None }; @@ -84,7 +88,7 @@ impl ProviderBuilder for Gpu { }, clock_limits: clock_lims, limits, - sysfs: Self::find_card_sysfs(persistent.root) + sysfs: Self::find_card_sysfs(persistent.root), } } @@ -112,7 +116,10 @@ impl Into for Gpu { tdp_boost: self.tdp_boost, clock_limits: self.clock_limits.map(|x| x.into()), 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 .clone() .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 { - x.min /= ppt_divisor; - x.max /= ppt_divisor; - x - } else {x}), + .map(|mut x| { + if let Some(ppt_divisor) = self.limits.ppt_divisor { + x.min /= ppt_divisor; + x.max /= ppt_divisor; + x + } else { + x + } + }), slow_ppt_limits: self .limits .slow_ppt .clone() .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 { - x.min /= ppt_divisor; - x.max /= ppt_divisor; - x - } else {x}), + .map(|mut x| { + if let Some(ppt_divisor) = self.limits.ppt_divisor { + x.min /= ppt_divisor; + x.max /= ppt_divisor; + x + } else { + x + } + }), ppt_step: self.limits.ppt_step.unwrap_or(1), tdp_limits: self .limits @@ -188,28 +203,56 @@ impl TGpu for Gpu { fn ppt(&mut self, fast: Option, slow: Option) { 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 }) - .map(|x| { - x.clamp( - fast_lims.min.unwrap_or(0), - fast_lims.max.unwrap_or(u64::MAX), - ) - }); + self.fast_ppt = fast + .map(|x| { + if let Some(ppt_divisor) = self.limits.ppt_divisor { + x * ppt_divisor + } 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 { - self.slow_ppt = slow.map(|x| if let Some(ppt_divisor) = self.limits.ppt_divisor { x * ppt_divisor } else { x }) - .map(|x| { - x.clamp( - slow_lims.min.unwrap_or(0), - slow_lims.max.unwrap_or(u64::MAX), - ) - }); + self.slow_ppt = slow + .map(|x| { + if let Some(ppt_divisor) = self.limits.ppt_divisor { + x * ppt_divisor + } else { + x + } + }) + .map(|x| { + x.clamp( + slow_lims.min.unwrap_or(0), + slow_lims.max.unwrap_or(u64::MAX), + ) + }); } } fn get_ppt(&self) -> (Option, Option) { - (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>) { diff --git a/backend/src/settings/generic/mod.rs b/backend/src/settings/generic/mod.rs index 9a99d47..1abd444 100644 --- a/backend/src/settings/generic/mod.rs +++ b/backend/src/settings/generic/mod.rs @@ -11,7 +11,15 @@ pub use traits::FromGenericCpuInfo; fn _impl_checker() { fn impl_provider_builder, J, L>() {} - impl_provider_builder::(); - impl_provider_builder::, Vec, limits_core::json_v2::GenericCpusLimit>(); + impl_provider_builder::< + Battery, + crate::persist::BatteryJson, + limits_core::json_v2::GenericBatteryLimit, + >(); + impl_provider_builder::< + Cpus, + Vec, + limits_core::json_v2::GenericCpusLimit, + >(); impl_provider_builder::(); } diff --git a/backend/src/settings/generic_amd/cpu.rs b/backend/src/settings/generic_amd/cpu.rs index 07aef41..2f618b2 100644 --- a/backend/src/settings/generic_amd/cpu.rs +++ b/backend/src/settings/generic_amd/cpu.rs @@ -2,7 +2,7 @@ use crate::persist::CpuJson; use crate::settings::generic::{Cpu as GenericCpu, Cpus as GenericCpus, FromGenericCpuInfo}; use crate::settings::MinMax; use crate::settings::{OnResume, OnSet, SettingError}; -use crate::settings::{TCpu, TCpus, ProviderBuilder}; +use crate::settings::{ProviderBuilder, TCpu, TCpus}; #[derive(Debug)] pub struct Cpus { diff --git a/backend/src/settings/generic_amd/gpu.rs b/backend/src/settings/generic_amd/gpu.rs index 0a1331a..4b5066e 100644 --- a/backend/src/settings/generic_amd/gpu.rs +++ b/backend/src/settings/generic_amd/gpu.rs @@ -4,10 +4,14 @@ use std::sync::Mutex; use crate::persist::GpuJson; use crate::settings::generic::Gpu as GenericGpu; use crate::settings::MinMax; -use crate::settings::{TGpu, ProviderBuilder}; use crate::settings::{OnResume, OnSet, SettingError, SettingVariant}; +use crate::settings::{ProviderBuilder, TGpu}; -fn msg_or_err(output: &mut String, msg: &str, result: Result) { +fn msg_or_err( + output: &mut String, + msg: &str, + result: Result, +) { use std::fmt::Write; match result { Ok(val) => writeln!(output, "{}: {}", msg, val).unwrap(), @@ -16,20 +20,41 @@ fn msg_or_err(output: &mut String, m } 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")] if let Some(x) = ryzenadj.get_init_table_err() { log::warn!("RyzenAdj table init error: {}", x); } 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, "refresh", ryzenadj.refresh().map(|_| "success")); - msg_or_err(&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, + "refresh", + ryzenadj.refresh().map(|_| "success"), + ); + msg_or_err( + &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_volt", ryzenadj.get_gfx_volt()); @@ -41,7 +66,7 @@ fn ryzen_adj_or_log() -> Option> { Ok(x) => { log_capabilities(&x); Some(Mutex::new(x)) - }, + } Err(e) => { log::error!("RyzenAdj init error: {}", e); None @@ -90,7 +115,6 @@ impl ProviderBuilder for Gpu { } impl Gpu { - fn set_all(&mut self) -> Result<(), Vec> { let mutex = match &self.implementor { Some(x) => x, diff --git a/backend/src/settings/generic_amd/mod.rs b/backend/src/settings/generic_amd/mod.rs index 89a2292..c395fc1 100644 --- a/backend/src/settings/generic_amd/mod.rs +++ b/backend/src/settings/generic_amd/mod.rs @@ -7,6 +7,10 @@ pub use gpu::Gpu; fn _impl_checker() { fn impl_provider_builder, J, L>() {} - impl_provider_builder::, limits_core::json_v2::GenericCpusLimit>(); + impl_provider_builder::< + Cpus, + Vec, + limits_core::json_v2::GenericCpusLimit, + >(); impl_provider_builder::(); } diff --git a/backend/src/settings/mod.rs b/backend/src/settings/mod.rs index e18fa4b..91e4662 100644 --- a/backend/src/settings/mod.rs +++ b/backend/src/settings/mod.rs @@ -6,25 +6,37 @@ mod min_max; mod traits; mod util; +pub mod dev_mode; pub mod generic; pub mod generic_amd; pub mod steam_deck; 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 general::{General, SettingVariant, Settings}; pub use min_max::{min_max_from_json, MinMax}; 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)] mod tests { #[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); } } diff --git a/backend/src/settings/steam_deck/battery.rs b/backend/src/settings/steam_deck/battery.rs index c0325eb..f47d9bd 100644 --- a/backend/src/settings/steam_deck/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -1,16 +1,22 @@ use std::convert::Into; use std::sync::{Arc, Mutex}; -use sysfuss::{PowerSupplyAttribute, PowerSupplyPath, HwMonAttribute, HwMonAttributeItem, HwMonAttributeType, HwMonPath, SysEntity, SysEntityAttributesExt, SysAttribute}; use sysfuss::capability::attributes; +use sysfuss::{ + HwMonAttribute, HwMonAttributeItem, HwMonAttributeType, HwMonPath, PowerSupplyAttribute, + PowerSupplyPath, SysAttribute, SysEntity, SysEntityAttributesExt, +}; use limits_core::json_v2::GenericBatteryLimit; -use smokepatio::ec::{ControllerSet, unnamed_power::{UnnamedPowerEC, ChargeMode}}; use crate::api::RangeLimit; use crate::persist::{BatteryEventJson, BatteryJson}; -use crate::settings::{TBattery, ProviderBuilder}; use crate::settings::{OnPowerEvent, OnResume, OnSet, PowerMode, SettingError}; +use crate::settings::{ProviderBuilder, TBattery}; +use smokepatio::ec::{ + unnamed_power::{ChargeMode, UnnamedPowerEC}, + ControllerSet, +}; #[derive(Debug, Clone)] pub struct Battery { @@ -121,7 +127,12 @@ impl EventInstruction { } } - fn from_json(other: BatteryEventJson, _version: u64, hwmon: Arc, ec: Arc>) -> Self { + fn from_json( + other: BatteryEventJson, + _version: u64, + hwmon: Arc, + ec: Arc>, + ) -> Self { Self { trigger: Self::str_to_trigger(&other.trigger).unwrap_or(EventTrigger::Ignored), charge_rate: other.charge_rate, @@ -137,7 +148,10 @@ impl EventInstruction { fn set_charge_mode(&self) -> Result<(), SettingError> { 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 { msg: format!("Failed to set charge mode"), setting: crate::settings::SettingVariant::Battery, @@ -149,12 +163,15 @@ impl EventInstruction { fn set_charge_rate(&self) -> Result<(), SettingError> { if let Some(charge_rate) = self.charge_rate { - self.sysfs_hwmon.set(MAX_BATTERY_CHARGE_RATE_ATTR, charge_rate).map_err( - |e| SettingError { - msg: format!("Failed to write to `{:?}`: {}", MAX_BATTERY_CHARGE_RATE_ATTR, e), + self.sysfs_hwmon + .set(MAX_BATTERY_CHARGE_RATE_ATTR, charge_rate) + .map_err(|e| SettingError { + msg: format!( + "Failed to write to `{:?}`: {}", + MAX_BATTERY_CHARGE_RATE_ATTR, e + ), setting: crate::settings::SettingVariant::Battery, - }, - ) + }) } else { 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_CURRENT_PATH: &str = "/sys/class/hwmon/hwmon5/curr1_input"; // read-only*/ - const BATTERY_NEEDS: &[PowerSupplyAttribute] = &[ PowerSupplyAttribute::Type, PowerSupplyAttribute::CurrentNow, @@ -213,8 +229,10 @@ const HWMON_NEEDS: &[HwMonAttribute] = &[ //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_LEVEL_ATTR: HwMonAttribute = HwMonAttribute::custom("max_battery_charge_level"); +const MAX_BATTERY_CHARGE_RATE_ATTR: HwMonAttribute = + 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 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"); 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 - }, + } Err(e) => { log::error!("Failed to find SteamDeck battery power_supply in sysfs ({}), using naive fallback", e); root.power_supply_by_name("BAT1") @@ -245,11 +266,15 @@ impl Battery { Ok(hwmon) => { 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); - } else { - log::info!("Found SteamDeck battery hwmon {} in sysfs: {}", super::util::JUPITER_HWMON_NAME, hwmon.as_ref().display()); + } else { + log::info!( + "Found SteamDeck battery hwmon {} in sysfs: {}", + super::util::JUPITER_HWMON_NAME, + hwmon.as_ref().display() + ); } hwmon - }, + } Err(e) => { log::warn!("Failed to find SteamDeck battery hwmon {} in sysfs ({}), trying alternate name", super::util::JUPITER_HWMON_NAME, e); @@ -258,10 +283,14 @@ impl Battery { 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); } 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 - }, + } Err(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) @@ -295,21 +324,27 @@ impl Battery { if let Some(charge_rate) = self.charge_rate { self.state.charge_rate_set = true; let path = MAX_BATTERY_CHARGE_RATE_ATTR.path(&*self.sysfs_hwmon); - self.sysfs_hwmon.set(MAX_BATTERY_CHARGE_RATE_ATTR, charge_rate).map_err( - |e| SettingError { + self.sysfs_hwmon + .set(MAX_BATTERY_CHARGE_RATE_ATTR, charge_rate) + .map_err(|e| SettingError { msg: format!("Failed to write to `{}`: {}", path.display(), e), setting: crate::settings::SettingVariant::Battery, - }, - ) + }) } else if self.state.charge_rate_set { self.state.charge_rate_set = false; 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( - |e| SettingError { + self.sysfs_hwmon + .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), setting: crate::settings::SettingVariant::Battery, - }, - ) + }) } else { Ok(()) } @@ -318,14 +353,20 @@ impl Battery { fn set_charge_mode(&mut self) -> Result<(), SettingError> { if let Some(charge_mode) = self.charge_mode { self.state.charge_mode_set = true; - 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 { msg: format!("Failed to set charge mode"), setting: crate::settings::SettingVariant::Battery, }) } else if self.state.charge_mode_set { 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 { msg: format!("Failed to set charge mode"), setting: crate::settings::SettingVariant::Battery, @@ -337,23 +378,35 @@ impl Battery { fn set_charge_limit(&mut self) -> Result<(), SettingError> { 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 { self.state.charge_limit_set = true; - self.sysfs_hwmon.set(MAX_BATTERY_CHARGE_LEVEL_ATTR, (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, - } + self.sysfs_hwmon + .set( + MAX_BATTERY_CHARGE_LEVEL_ATTR, + (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 { 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 { - msg: format!("Failed to reset (write to) {:?}: {}", MAX_BATTERY_CHARGE_LEVEL_ATTR, e), - setting: crate::settings::SettingVariant::Battery, - } - ) + msg: format!( + "Failed to reset (write to) {:?}: {}", + MAX_BATTERY_CHARGE_LEVEL_ATTR, e + ), + setting: crate::settings::SettingVariant::Battery, + }) } else { Ok(()) } @@ -373,8 +426,16 @@ impl Battery { fn clamp_all(&mut self) { if let Some(charge_rate) = &mut self.charge_rate { - *charge_rate = - (*charge_rate).clamp(self.limits.charge_rate.and_then(|lim| lim.min).unwrap_or(MIN_CHARGE_RATE), self.limits.charge_rate.and_then(|lim| lim.max).unwrap_or(MAX_CHARGE_RATE)); + *charge_rate = (*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), + ); } } @@ -558,13 +619,21 @@ impl Into for Battery { charge_rate: self.charge_rate, charge_mode: self.charge_mode.map(Self::charge_mode_to_str), 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 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 ec = Arc::new(Mutex::new(UnnamedPowerEC::new())); match version { @@ -586,14 +655,15 @@ impl ProviderBuilder for Battery { sysfs_hwmon: hwmon_sys, bat_ec: ec, variant: super::Model::LCD, - }.remove_charge_limit_instructions(), + } + .remove_charge_limit_instructions(), _ => Self { charge_rate: persistent.charge_rate, charge_mode: persistent .charge_mode .map(|x| Self::str_to_charge_mode(&x)) .flatten(), - charge_limit: None, + charge_limit: None, events: persistent .events .into_iter() @@ -605,7 +675,8 @@ impl ProviderBuilder for Battery { sysfs_hwmon: hwmon_sys, bat_ec: ec, variant: super::Model::LCD, - }.remove_charge_limit_instructions(), + } + .remove_charge_limit_instructions(), } } @@ -621,7 +692,8 @@ impl ProviderBuilder for Battery { sysfs_hwmon: Arc::new(Self::find_hwmon_sysfs(None::<&'static str>)), bat_ec: Arc::new(Mutex::new(UnnamedPowerEC::new())), 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 { crate::api::BatteryLimits { charge_current: Some(RangeLimit { - min: self.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), + min: self + .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_modes: vec![ diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 34671c5..a1c78b6 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -2,22 +2,20 @@ use std::convert::Into; 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::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT; use crate::api::RangeLimit; use crate::persist::CpuJson; use crate::settings::{min_max_from_json, MinMax}; use crate::settings::{OnResume, OnSet, SettingError}; -use crate::settings::{TCpu, TCpus, ProviderBuilder}; +use crate::settings::{ProviderBuilder, TCpu, TCpus}; const CPU_PRESENT_PATH: &str = "/sys/devices/system/cpu/present"; const CPU_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; -const CARD_EXTENSIONS: &[&'static str] = &[ - super::DPM_FORCE_LIMITS_ATTRIBUTE -]; +const CARD_EXTENSIONS: &[&'static str] = &[super::DPM_FORCE_LIMITS_ATTRIBUTE]; const MAX_CLOCK: u64 = 3500; const MIN_MAX_CLOCK: u64 = 200; // minimum value allowed for maximum CPU clock, MHz @@ -109,7 +107,11 @@ impl Cpus { } impl ProviderBuilder, GenericCpusLimit> for Cpus { - fn from_json_and_limits(mut persistent: Vec, version: u64, limits: GenericCpusLimit) -> Self { + fn from_json_and_limits( + mut persistent: Vec, + version: u64, + limits: GenericCpusLimit, + ) -> Self { POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.reset(); let (_, can_smt) = Self::system_smt_capabilities(); let mut result = Vec::with_capacity(persistent.len()); @@ -123,18 +125,9 @@ impl ProviderBuilder, GenericCpusLimit> for Cpus { } } let new_cpu = if let Some(cpu_limit) = limits.cpus.get(i) { - Cpu::from_json_and_limits( - cpu, - version, - i, - cpu_limit.to_owned() - ) + Cpu::from_json_and_limits(cpu, version, i, cpu_limit.to_owned()) } else { - Cpu::from_json( - cpu, - version, - i, - ) + Cpu::from_json(cpu, version, i) }; result.push(new_cpu); } @@ -160,10 +153,7 @@ impl ProviderBuilder, GenericCpusLimit> for Cpus { let mut sys_cpus = Vec::with_capacity(max_cpu); for i in 0..max_cpu { let new_cpu = if let Some(cpu_limit) = limits.cpus.get(i) { - Cpu::from_limits( - i, - cpu_limit.to_owned() - ) + Cpu::from_limits(i, cpu_limit.to_owned()) } else { Cpu::system_default(i) }; @@ -255,7 +245,12 @@ enum ClockType { impl Cpu { #[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 { 0 => Self { online: other.online, @@ -280,13 +275,21 @@ impl Cpu { #[inline] 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) } fn find_card_sysfs(root: Option>) -> BasicEntityPath { 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) => { let card = iter .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()); card - }, + } 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")) } } } - 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); - self.sysfs.set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), &payload).map_err(|e| { - SettingError { + self.sysfs + .set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), &payload) + .map_err(|e| SettingError { msg: format!( "Failed to write `{}` to `{}`: {}", &payload, CPU_CLOCK_LIMITS_ATTRIBUTE, e ), setting: crate::settings::SettingVariant::Cpu, - } - }) + }) } fn reset_clock_limits(&self) -> Result<(), SettingError> { - self.sysfs.set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), "r\n").map_err(|e| { - SettingError { + self.sysfs + .set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), "r\n") + .map_err(|e| SettingError { msg: format!( "Failed to write `r` to `{}`: {}", CPU_CLOCK_LIMITS_ATTRIBUTE, e ), setting: crate::settings::SettingVariant::Cpu, - } - }) + }) } fn set_clock_limits(&mut self) -> Result<(), Vec> { @@ -350,11 +361,12 @@ impl Cpu { } // min clock if let Some(min) = clock_limits.min { - let valid_min = if min < range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK) { - range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK) - } else { - min - }; + let valid_min = + if min < range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK) { + range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK) + } else { + min + }; self.set_clock_limit(self.index, valid_min, ClockType::Min) .unwrap_or_else(|e| errors.push(e)); } @@ -371,22 +383,30 @@ impl Cpu { let mut errors = Vec::new(); self.state.clock_limits_set = false; POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(false, self.index); - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT - .enforce_level(&self.sysfs)?; + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs)?; if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { // always set clock speeds, since it doesn't reset correctly (kernel/hardware bug) POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs)?; // disable manual clock limits log::debug!("Setting CPU {} to default clockspeed", self.index); // max clock - self.set_clock_limit(self.index, range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK), ClockType::Max) - .unwrap_or_else(|e| errors.push(e)); + self.set_clock_limit( + self.index, + range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK), + ClockType::Max, + ) + .unwrap_or_else(|e| errors.push(e)); // min clock - self.set_clock_limit(self.index, range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK), ClockType::Min) - .unwrap_or_else(|e| errors.push(e)); + self.set_clock_limit( + 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 - 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() { Ok(()) } else { @@ -407,11 +427,19 @@ impl Cpu { // disable manual clock limits log::debug!("Setting CPU {} to default clockspeed", self.index); // max clock - self.set_clock_limit(self.index, range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK), ClockType::Max) - .unwrap_or_else(|e| errors.push(e)); + self.set_clock_limit( + self.index, + range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK), + ClockType::Max, + ) + .unwrap_or_else(|e| errors.push(e)); // min clock - self.set_clock_limit(self.index, range_min_or_fallback(&self.limits.clock_min, MIN_MIN_CLOCK), ClockType::Min) - .unwrap_or_else(|e| errors.push(e)); + self.set_clock_limit( + 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)); @@ -430,12 +458,15 @@ impl Cpu { } fn set_confirm(&self) -> Result<(), SettingError> { - self.sysfs.set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), "c\n").map_err(|e| { - SettingError { - msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_ATTRIBUTE, e), + self.sysfs + .set(CPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), "c\n") + .map_err(|e| SettingError { + msg: format!( + "Failed to write `c` to `{}`: {}", + CPU_CLOCK_LIMITS_ATTRIBUTE, e + ), setting: crate::settings::SettingVariant::Cpu, - } - }) + }) } fn set_force_performance_related(&mut self) -> Result<(), Vec> { @@ -504,12 +535,16 @@ impl Cpu { fn clamp_all(&mut self) { if let Some(clock_limits) = &mut self.clock_limits { if let Some(min) = clock_limits.min { - clock_limits.min = - Some(min.clamp(range_min_or_fallback(&self.limits.clock_max, MIN_MAX_CLOCK), range_max_or_fallback(&self.limits.clock_min, MAX_CLOCK))); + clock_limits.min = Some(min.clamp( + 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 { - clock_limits.max = - Some(max.clamp(range_min_or_fallback(&self.limits.clock_max, MIN_MAX_CLOCK), range_max_or_fallback(&self.limits.clock_max, MAX_CLOCK))); + clock_limits.max = Some(max.clamp( + 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, index: cpu_index, 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 { - 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 { @@ -578,7 +616,10 @@ impl Into for Cpu { online: self.online, clock_limits: self.clock_limits.map(|x| x.into()), 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())), } } } diff --git a/backend/src/settings/steam_deck/gpu.rs b/backend/src/settings/steam_deck/gpu.rs index e8aafb0..8ca3faa 100644 --- a/backend/src/settings/steam_deck/gpu.rs +++ b/backend/src/settings/steam_deck/gpu.rs @@ -1,15 +1,18 @@ 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 super::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT; use crate::api::RangeLimit; use crate::persist::GpuJson; -use crate::settings::{TGpu, ProviderBuilder}; use crate::settings::{min_max_from_json, MinMax}; use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::{ProviderBuilder, TGpu}; // usually in /sys/class/hwmon/hwmon4/ const SLOW_PPT_ATTRIBUTE: sysfuss::HwMonAttribute = sysfuss::HwMonAttribute::custom("power1_cap"); @@ -60,7 +63,14 @@ const PPT_DIVISOR: u64 = 1_000; impl Gpu { fn find_card_sysfs(root: Option>) -> BasicEntityPath { 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) => { let card = iter .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"); 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 - }, + } 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")) } } @@ -82,33 +98,47 @@ impl Gpu { fn find_hwmon_sysfs(root: Option>) -> HwMonPath { 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| { - log::error!("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()); + let hwmon = root + .hwmon_by_name(super::util::GPU_HWMON_NAME) + .unwrap_or_else(|e| { + log::error!( + "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 } fn set_clock_limit(&self, speed: u64, mode: ClockType) -> Result<(), SettingError> { let payload = format!("s {} {}\n", mode as u8, speed); let path = GPU_CLOCK_LIMITS_ATTRIBUTE.path(&self.sysfs_card); - self.sysfs_card.set(GPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), &payload).map_err(|e| { - SettingError { - msg: format!("Failed to write `{}` to `{}`: {}", &payload, path.display(), e), + self.sysfs_card + .set(GPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), &payload) + .map_err(|e| SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload, + path.display(), + e + ), setting: crate::settings::SettingVariant::Gpu, - } - }) + }) } fn set_confirm(&self) -> Result<(), SettingError> { 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| { - SettingError { + self.sysfs_card + .set(GPU_CLOCK_LIMITS_ATTRIBUTE.to_owned(), "c\n") + .map_err(|e| SettingError { msg: format!("Failed to write `c` to `{}`: {}", path.display(), e), setting: crate::settings::SettingVariant::Gpu, - } - }) + }) } 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) = &limit.max { 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); } else { log::debug!("chosen_clock: {}, limit_clock: {}", clock, limit); @@ -129,7 +164,10 @@ impl Gpu { } 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)); // round (and find) nearest valid clock step // roughly price is right strategy (clock step will always be lower or equal to chosen) @@ -142,7 +180,7 @@ impl Gpu { if i == 0 { return *current_val_opt as _; } else { - return options[i-1].0 as _; + return options[i - 1].0 as _; } } } @@ -160,9 +198,11 @@ impl Gpu { use std::fmt::Write; let mut payload = String::from("0"); 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 } } @@ -177,11 +217,13 @@ impl Gpu { self.state.clock_limits_set = true; // max clock 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 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)); @@ -195,11 +237,23 @@ impl Gpu { POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs_card)?; // disable manual clock limits // max clock - self.set_clock_limit(self.limits.clock_max.and_then(|lim| lim.max).unwrap_or(MAX_CLOCK), ClockType::Max) - .unwrap_or_else(|e| errors.push(e)); + self.set_clock_limit( + self.limits + .clock_max + .and_then(|lim| lim.max) + .unwrap_or(MAX_CLOCK), + ClockType::Max, + ) + .unwrap_or_else(|e| errors.push(e)); // min clock - self.set_clock_limit(self.limits.clock_min.and_then(|lim| lim.min).unwrap_or(MIN_CLOCK), ClockType::Min) - .unwrap_or_else(|e| errors.push(e)); + self.set_clock_limit( + 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)); } else { @@ -218,28 +272,37 @@ impl Gpu { fn set_memory_speed(&self, clock: u64) -> Result<(), SettingError> { let path = GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.path(&self.sysfs_card); let payload = self.build_memory_clock_payload(clock); - log::debug!("Generated payload for gpu fclk (memory): `{}` (is maxed? {})", payload, self.is_memory_clock_maxed()); - self.sysfs_card.set(GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.to_owned(), payload).map_err(|e| { - SettingError { + log::debug!( + "Generated payload for gpu fclk (memory): `{}` (is maxed? {})", + 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), setting: crate::settings::SettingVariant::Gpu, - } - }) + }) } fn set_force_performance_related(&mut self) -> Result<(), Vec> { 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 - .enforce_level(&self.sysfs_card) - .unwrap_or_else(|mut e| errors.append(&mut e)); + .set_gpu(!self.is_memory_clock_maxed() || self.clock_limits.is_some()); + 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?) self.set_memory_speed( self.memory_clock - .or_else(|| self.limits.memory_clock - .map(|lim| lim.max.unwrap_or(MAX_MEMORY_CLOCK)) - ).unwrap_or(MAX_MEMORY_CLOCK) - ).unwrap_or_else(|e| errors.push(e)); + .or_else(|| { + self.limits + .memory_clock + .map(|lim| lim.max.unwrap_or(MAX_MEMORY_CLOCK)) + }) + .unwrap_or(MAX_MEMORY_CLOCK), + ) + .unwrap_or_else(|e| errors.push(e)); self.set_clocks() .unwrap_or_else(|mut e| errors.append(&mut e)); // commit changes (if no errors have already occured) @@ -262,7 +325,8 @@ impl Gpu { // set fast PPT if let Some(fast_ppt) = &self.fast_ppt { 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 { msg: format!( "Failed to write `{}` to `{:?}`: {}", @@ -276,7 +340,8 @@ impl Gpu { } else if self.state.fast_ppt_set { self.state.fast_ppt_set = false; 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 { msg: format!( "Failed to write `{}` to `{:?}`: {}", @@ -291,7 +356,8 @@ impl Gpu { // set slow PPT if let Some(slow_ppt) = &self.slow_ppt { 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 { msg: format!( "Failed to write `{}` to `{:?}`: {}", @@ -305,7 +371,8 @@ impl Gpu { } else if self.state.slow_ppt_set { self.state.slow_ppt_set = false; 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 { msg: format!( "Failed to write `{}` to `{:?}`: {}", @@ -328,23 +395,72 @@ impl Gpu { fn clamp_all(&mut self) { if let Some(fast_ppt) = &mut self.fast_ppt { - *fast_ppt = (*fast_ppt).clamp(self.limits.fast_ppt.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 { - *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(min) = clock_limits.min { - clock_limits.min = - 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))); + clock_limits.min = 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), + ), + ); } if let Some(max) = clock_limits.max { - clock_limits.max = - 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))); + clock_limits.max = 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), + ), + ); } } 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 for Gpu { tdp_boost: None, clock_limits: self.clock_limits.map(|x| x.into()), 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 for Gpu { 0 => Self { fast_ppt: persistent.fast_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, limits: limits, state: crate::state::steam_deck::Gpu::default(), @@ -386,7 +508,9 @@ impl ProviderBuilder for Gpu { _ => Self { fast_ppt: persistent.fast_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, limits: limits, state: crate::state::steam_deck::Gpu::default(), @@ -433,12 +557,16 @@ impl TGpu for Gpu { fn limits(&self) -> crate::api::GpuLimits { crate::api::GpuLimits { 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), - max: super::util::range_max_or_fallback(&self.limits.fast_ppt, MAX_FAST_PPT) / self.limits.ppt_divisor.unwrap_or(PPT_DIVISOR), + min: super::util::range_min_or_fallback(&self.limits.fast_ppt, MIN_FAST_PPT) + / 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 { - min: super::util::range_min_or_fallback(&self.limits.slow_ppt, MIN_SLOW_PPT) / 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), + min: super::util::range_min_or_fallback(&self.limits.slow_ppt, MIN_SLOW_PPT) + / 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), tdp_limits: None, @@ -454,8 +582,14 @@ impl TGpu for Gpu { }), clock_step: self.limits.clock_step.unwrap_or(100), memory_control: Some(RangeLimit { - min: super::util::range_min_or_fallback(&self.limits.memory_clock, MIN_MEMORY_CLOCK), - max: super::util::range_max_or_fallback(&self.limits.memory_clock, MAX_MEMORY_CLOCK), + min: super::util::range_min_or_fallback( + &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), } @@ -472,8 +606,10 @@ impl TGpu for Gpu { fn get_ppt(&self) -> (Option, Option) { ( - self.fast_ppt.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)), + self.fast_ppt + .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(); for line in s.split('\n') { if !line.is_empty() { if let Some((val, freq_mess)) = line.split_once(':') { if let Ok(val) = val.parse::() { - 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::() { result.push((val, freq)); } diff --git a/backend/src/settings/steam_deck/mod.rs b/backend/src/settings/steam_deck/mod.rs index 5adc6c6..c5a64ce 100644 --- a/backend/src/settings/steam_deck/mod.rs +++ b/backend/src/settings/steam_deck/mod.rs @@ -7,7 +7,9 @@ mod util; pub use battery::Battery; pub use cpu::Cpus; 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)] pub enum Model { @@ -20,7 +22,15 @@ pub use util::flash_led; fn _impl_checker() { fn impl_provider_builder, J, L>() {} - impl_provider_builder::(); - impl_provider_builder::, limits_core::json_v2::GenericCpusLimit>(); + impl_provider_builder::< + Battery, + crate::persist::BatteryJson, + limits_core::json_v2::GenericBatteryLimit, + >(); + impl_provider_builder::< + Cpus, + Vec, + limits_core::json_v2::GenericCpusLimit, + >(); impl_provider_builder::(); } diff --git a/backend/src/settings/steam_deck/power_dpm_force.rs b/backend/src/settings/steam_deck/power_dpm_force.rs index d804a18..039026a 100644 --- a/backend/src/settings/steam_deck/power_dpm_force.rs +++ b/backend/src/settings/steam_deck/power_dpm_force.rs @@ -5,7 +5,7 @@ use std::sync::atomic::{AtomicU64, Ordering}; -use sysfuss::{BasicEntityPath, SysEntityAttributesExt, SysAttribute}; +use sysfuss::{BasicEntityPath, SysAttribute, SysEntityAttributesExt}; use crate::settings::SettingError; @@ -63,7 +63,8 @@ impl PDFPLManager { let needs = self.needs_manual(); let mut errors = Vec::new(); 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| { vec![SettingError { msg: format!("Failed to read `{}`: {}", path.display(), e), @@ -73,7 +74,8 @@ impl PDFPLManager { if mode != "manual" && needs { log::info!("Setting `{}` to manual", path.display()); // set manual control - entity.set(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned(), "manual") + entity + .set(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned(), "manual") .map_err(|e| { errors.push(SettingError { msg: format!("Failed to write `manual` to `{}`: {}", path.display(), e), @@ -84,7 +86,8 @@ impl PDFPLManager { } else if mode != "auto" && !needs { log::info!("Setting `{}` to auto", path.display()); // unset manual control - entity.set(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned(), "auto") + entity + .set(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned(), "auto") .map_err(|e| { errors.push(SettingError { msg: format!("Failed to write `auto` to `{}`: {}", path.display(), e), @@ -93,10 +96,13 @@ impl PDFPLManager { }) .unwrap_or(()); } - if let Ok(mode_now) = - entity.attribute::(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned()) - { - log::debug!("Mode for `{}` is now `{}` ({:#b})", path.display(), mode_now, self.get()); + if let Ok(mode_now) = entity.attribute::(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned()) { + log::debug!( + "Mode for `{}` is now `{}` ({:#b})", + path.display(), + mode_now, + self.get() + ); } else { log::debug!("Error getting new mode for debugging purposes"); } diff --git a/backend/src/settings/steam_deck/util.rs b/backend/src/settings/steam_deck/util.rs index 2d37f51..88d940c 100644 --- a/backend/src/settings/steam_deck/util.rs +++ b/backend/src/settings/steam_deck/util.rs @@ -4,16 +4,23 @@ pub const JUPITER_HWMON_NAME: &'static str = "jupiter"; pub const STEAMDECK_HWMON_NAME: &'static str = "steamdeck_hwmon"; pub const GPU_HWMON_NAME: &'static str = "amdgpu"; -pub fn range_min_or_fallback(range: &Option>, fallback: I) -> I { +pub fn range_min_or_fallback( + range: &Option>, + fallback: I, +) -> I { range.and_then(|lim| lim.min).unwrap_or(fallback) } -pub fn range_max_or_fallback(range: &Option>, fallback: I) -> I { +pub fn range_max_or_fallback( + range: &Option>, + fallback: I, +) -> I { range.and_then(|lim| lim.max).unwrap_or(fallback) } 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()) } @@ -31,7 +38,11 @@ pub fn flash_led() { let mut ec = smokepatio::ec::unnamed_power::UnnamedPowerEC::new(); for &code in THINGS { 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) { log::error!("Thing err: {}", e); } diff --git a/backend/src/settings/traits.rs b/backend/src/settings/traits.rs index 5f993b2..f68f5cf 100644 --- a/backend/src/settings/traits.rs +++ b/backend/src/settings/traits.rs @@ -125,7 +125,10 @@ pub trait TGeneral: OnSet + OnResume + OnPowerEvent + Debug + Send { fn get_variant_info(&self) -> crate::api::VariantInfo; - fn add_variant(&self, variant: crate::persist::SettingsJson) -> Result, SettingError>; + fn add_variant( + &self, + variant: crate::persist::SettingsJson, + ) -> Result, SettingError>; fn provider(&self) -> crate::persist::DriverJson; } diff --git a/backend/src/settings/unknown/battery.rs b/backend/src/settings/unknown/battery.rs index 6c1a2e3..cdd5c96 100644 --- a/backend/src/settings/unknown/battery.rs +++ b/backend/src/settings/unknown/battery.rs @@ -3,8 +3,8 @@ use std::convert::Into; use limits_core::json_v2::GenericBatteryLimit; use crate::persist::BatteryJson; -use crate::settings::{TBattery, ProviderBuilder}; use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::{ProviderBuilder, TBattery}; #[derive(Debug, Clone)] pub struct Battery; @@ -29,7 +29,11 @@ impl Into for Battery { } impl ProviderBuilder 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() } diff --git a/backend/src/settings/unknown/cpu.rs b/backend/src/settings/unknown/cpu.rs index 25130ca..2aed5c8 100644 --- a/backend/src/settings/unknown/cpu.rs +++ b/backend/src/settings/unknown/cpu.rs @@ -5,7 +5,7 @@ use limits_core::json_v2::GenericCpusLimit; use crate::persist::CpuJson; use crate::settings::MinMax; 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_SMT_PATH: &str = "/sys/devices/system/cpu/smt/control"; @@ -146,7 +146,11 @@ impl Cpus { } impl ProviderBuilder, GenericCpusLimit> for Cpus { - fn from_json_and_limits(mut persistent: Vec, version: u64, _limits: GenericCpusLimit) -> Self { + fn from_json_and_limits( + mut persistent: Vec, + version: u64, + _limits: GenericCpusLimit, + ) -> Self { let (_, can_smt) = Self::system_smt_capabilities(); let mut result = Vec::with_capacity(persistent.len()); let max_cpus = Self::cpu_count(); @@ -284,7 +288,7 @@ impl Cpu { .unwrap_or("schedutil".to_owned()), index: cpu_index, state: crate::state::steam_deck::Cpu::default(), - root: "/".into() + root: "/".into(), } } diff --git a/backend/src/settings/unknown/gpu.rs b/backend/src/settings/unknown/gpu.rs index c676cda..4adcfec 100644 --- a/backend/src/settings/unknown/gpu.rs +++ b/backend/src/settings/unknown/gpu.rs @@ -4,15 +4,15 @@ use limits_core::json_v2::GenericGpuLimit; use crate::persist::GpuJson; use crate::settings::MinMax; -use crate::settings::{TGpu, ProviderBuilder}; use crate::settings::{OnResume, OnSet, SettingError}; +use crate::settings::{ProviderBuilder, TGpu}; #[derive(Debug, Clone)] pub struct Gpu {} impl Gpu { pub fn system_default() -> Self { - Self { } + Self {} } } diff --git a/backend/src/settings/unknown/mod.rs b/backend/src/settings/unknown/mod.rs index 200c1ea..58b6ac1 100644 --- a/backend/src/settings/unknown/mod.rs +++ b/backend/src/settings/unknown/mod.rs @@ -9,7 +9,15 @@ pub use gpu::Gpu; fn _impl_checker() { fn impl_provider_builder, J, L>() {} - impl_provider_builder::(); - impl_provider_builder::, limits_core::json_v2::GenericCpusLimit>(); + impl_provider_builder::< + Battery, + crate::persist::BatteryJson, + limits_core::json_v2::GenericBatteryLimit, + >(); + impl_provider_builder::< + Cpus, + Vec, + limits_core::json_v2::GenericCpusLimit, + >(); impl_provider_builder::(); } diff --git a/backend/src/settings/util.rs b/backend/src/settings/util.rs index 6d4e8ed..cebd95b 100644 --- a/backend/src/settings/util.rs +++ b/backend/src/settings/util.rs @@ -18,10 +18,7 @@ pub fn always_satisfied<'a, X>(_: &'a X) -> bool { true } -pub const CARD_NEEDS: &[&'static str] = &[ - "dev", - "uevent" -]; +pub const CARD_NEEDS: &[&'static str] = &["dev", "uevent"]; #[cfg(test)] mod test { diff --git a/backend/src/utility.rs b/backend/src/utility.rs index f6999c7..2aa20f4 100644 --- a/backend/src/utility.rs +++ b/backend/src/utility.rs @@ -120,51 +120,66 @@ mod generate { let limits = limits_core::json_v2::Limits { cpu: limits_core::json_v2::Limit { 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 { 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 { 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(); - ron::ser::to_writer_pretty(output_file, &limits, crate::utility::ron_pretty_config()).unwrap(); + let output_file = + 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] fn generate_default_minimal_save_file() { let mut mini_variants = std::collections::HashMap::with_capacity(2); - mini_variants.insert(0, crate::persist::SettingsJson { - version: 0, - name: crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned(), - variant: 0, - persistent: false, - cpus: vec![crate::persist::CpuJson::default(); 8], - gpu: crate::persist::GpuJson::default(), - battery: crate::persist::BatteryJson::default(), - provider: None, - }); - mini_variants.insert(42, crate::persist::SettingsJson { - version: 0, - name: "FortySecondary".to_owned(), - variant: 42, - persistent: false, - cpus: vec![crate::persist::CpuJson::default(); 8], - gpu: crate::persist::GpuJson::default(), - battery: crate::persist::BatteryJson::default(), - provider: None, - }); + mini_variants.insert( + 0, + crate::persist::SettingsJson { + version: 0, + name: crate::consts::DEFAULT_SETTINGS_VARIANT_NAME.to_owned(), + variant: 0, + persistent: false, + cpus: vec![crate::persist::CpuJson::default(); 8], + gpu: crate::persist::GpuJson::default(), + battery: crate::persist::BatteryJson::default(), + provider: None, + }, + ); + mini_variants.insert( + 42, + crate::persist::SettingsJson { + version: 0, + name: "FortySecondary".to_owned(), + 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 { version: 0, name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(), variants: mini_variants, }; - let output_file = 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(); + let output_file = + 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(); } } - diff --git a/src/index.tsx b/src/index.tsx index 1c8bef7..e3b8e95 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -16,6 +16,8 @@ import { Dropdown, SingleDropdownOption, Navigation, + Focusable, + Spinner, //NotchLabel //gamepadDialogClasses, //joinClassNames, @@ -89,6 +91,7 @@ var startHook: any = null; var endHook: any = null; var userHook: any = null; var usdplReady = false; +var isVariantLoading = false; var tryNotifyProfileChange = function() {}; @@ -343,6 +346,12 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { data: elem, label: {elem.name}, };}); + 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 ( @@ -383,83 +392,102 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { - { - 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; })} - 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) => { - let data = elem.data as backend.VariantInfo; - backend.log(backend.LogLevel.Debug, "Profile variant dropdown selected " + elem.data.toString()); - backend.loadGeneralSettingsVariant(data.id, data.name); - set_value(CURRENT_VARIANT_GEN, elem.data as backend.VariantInfo); - reloadGUI("ProfileVariantGovernor"); + if (elem.data.id != (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).id) { + isVariantLoading = true; + let data = elem.data as backend.VariantInfo; + backend.log(backend.LogLevel.Debug, "Profile variant dropdown selected " + elem.data.id.toString()); + //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 && )} - - { - backend.log(backend.LogLevel.Debug, "Creating new PowerTools settings variant"); - backend.resolve( - 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), - (ok: boolean) => { - backend.log(backend.LogLevel.Debug, "New settings variant ok? " + ok); - reload(); - backend.resolve(backend.waitForComplete(), (_) => { - backend.log(backend.LogLevel.Debug, "Trying to tell UI to re-render due to new settings variant"); - tryNotifyProfileChange(); - }); + + + { + backend.log(backend.LogLevel.Debug, "Creating new PowerTools settings variant"); + backend.resolve( + 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), + (ok: boolean) => { + backend.log(backend.LogLevel.Debug, "New settings variant ok? " + ok); + reload(); + backend.resolve(backend.waitForComplete(), (_) => { + backend.log(backend.LogLevel.Debug, "Trying to tell UI to re-render due to new settings variant"); + tryNotifyProfileChange(); + }); + } + ); + }} + > + + + { + 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 + ")"); } - ); - }} - > - - - { - 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 + ")"); - } - }} - > - - - { - Navigation.Navigate(STORE_RESULTS_URI); - Navigation.CloseSideMenus(); - }} - > - - + }} + > + + + { + Navigation.Navigate(STORE_RESULTS_URI); + Navigation.CloseSideMenus(); + }} + > + + +