cargo fmt and fix profile variant loading
This commit is contained in:
parent
85a9fc8f7e
commit
59a0727f88
40 changed files with 1640 additions and 720 deletions
|
@ -67,4 +67,5 @@ pub struct GpuLimits {
|
|||
pub struct VariantInfo {
|
||||
pub id: String,
|
||||
pub name: String,
|
||||
pub id_num: u64,
|
||||
}
|
||||
|
|
|
@ -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<String>| {
|
||||
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<ApiMessage>) -> 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<ApiMessage>) -> impl AsyncCallable {
|
|||
}
|
||||
}
|
||||
|
||||
fn build_comms<'a, T: Send + 'a>(msg: &'static str) -> (mpsc::Receiver<T>, Box<dyn FnOnce(T) + Send + 'a>) {
|
||||
fn build_comms<'a, T: Send + 'a>(
|
||||
msg: &'static str,
|
||||
) -> (mpsc::Receiver<T>, Box<dyn FnOnce(T) + Send + 'a>) {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let callback = move |t: T| tx.send(t).expect(msg);
|
||||
(rx, Box::new(callback))
|
||||
}
|
||||
|
||||
fn wait_for_response<T>(sender: &Sender<ApiMessage>, rx: mpsc::Receiver<T>, api_msg: ApiMessage, op: &str) -> T {
|
||||
fn wait_for_response<T>(
|
||||
sender: &Sender<ApiMessage>,
|
||||
rx: mpsc::Receiver<T>,
|
||||
api_msg: ApiMessage,
|
||||
op: &str,
|
||||
) -> T {
|
||||
sender.send(api_msg).expect(&format!("{} send failed", op));
|
||||
rx.recv().expect(&format!("{} callback recv failed", op))
|
||||
}
|
||||
|
@ -429,8 +480,10 @@ pub fn get_all_variants(sender: Sender<ApiMessage>) -> impl AsyncCallable {
|
|||
let sender2 = sender.clone();
|
||||
move || {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let callback =
|
||||
move |variants: Vec<super::VariantInfo>| tx.send(variants).expect("get_all_variants callback send failed");
|
||||
let callback = move |variants: Vec<super::VariantInfo>| {
|
||||
tx.send(variants)
|
||||
.expect("get_all_variants callback send failed")
|
||||
};
|
||||
sender2
|
||||
.lock()
|
||||
.unwrap()
|
||||
|
@ -438,7 +491,9 @@ pub fn get_all_variants(sender: Sender<ApiMessage>) -> 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<ApiMessage>) -> 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<ApiMessage>) -> 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<ApiMessage>) -> 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"),
|
||||
)]
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<std::path::PathBuf>),
|
||||
GetCurrentVariant(Callback<super::VariantInfo>),
|
||||
GetAllVariants(Callback<Vec<super::VariantInfo>>),
|
||||
AddVariant(crate::persist::SettingsJson, Callback<Vec<super::VariantInfo>>),
|
||||
AddVariant(
|
||||
crate::persist::SettingsJson,
|
||||
Callback<Vec<super::VariantInfo>>,
|
||||
),
|
||||
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
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<DeveloperMessage> for ApiMessage {
|
|||
}
|
||||
|
||||
fn get_dev_messages() -> Vec<ApiMessage> {
|
||||
crate::settings::get_dev_messages().drain(..).map(|msg| ApiMessage::from(msg)).collect()
|
||||
crate::settings::get_dev_messages()
|
||||
.drain(..)
|
||||
.map(|msg| ApiMessage::from(msg))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub struct MessageHandler {
|
||||
|
@ -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<Item=ApiMessage>) -> impl Iterator<Item=ApiMessage> {
|
||||
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<Item = ApiMessage>,
|
||||
) -> impl Iterator<Item = ApiMessage> {
|
||||
messages.skip_while(move |msg| {
|
||||
if let Some(msg_id) = msg.id {
|
||||
msg_id <= id
|
||||
} else {
|
||||
true
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,12 +14,17 @@ pub fn search_by_app_id() -> impl AsyncCallable {
|
|||
let req_url = format!("{}/api/setting/by_app_id/{}", BASE_URL, steam_app_id);
|
||||
match ureq::get(&req_url).call() {
|
||||
Ok(response) => {
|
||||
let json_res: std::io::Result<Vec<community_settings_core::v1::Metadata>> = response.into_json();
|
||||
let json_res: std::io::Result<Vec<community_settings_core::v1::Metadata>> =
|
||||
response.into_json();
|
||||
match json_res {
|
||||
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<community_settings_core::v1::Metadata> {
|
||||
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<ApiMessage>) -> impl AsyncCallable {
|
|||
match download_config(id) {
|
||||
Ok(meta) => {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let callback =
|
||||
move |values: Vec<super::VariantInfo>| tx.send(values).expect("download_new_config callback send failed");
|
||||
let callback = move |values: Vec<super::VariantInfo>| {
|
||||
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<ApiMessage>) -> impl AsyncCallable {
|
|||
if let Some(Primitive::String(id)) = params.get(0) {
|
||||
match id.parse::<u128>() {
|
||||
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<ApiMessage>) -> 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<ApiMessage>) -> impl AsyncCallable
|
|||
}
|
||||
},
|
||||
set_get: getter,
|
||||
trans_getter: |result| {
|
||||
vec![result.into()]
|
||||
},
|
||||
trans_getter: |result| vec![result.into()],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,5 +10,4 @@ pub const DEFAULT_SETTINGS_VARIANT_NAME: &str = "Primary";
|
|||
pub const LIMITS_FILE: &str = "limits_cache.ron";
|
||||
pub const LIMITS_OVERRIDE_FILE: &str = "limits_override.ron";
|
||||
|
||||
|
||||
pub const MESSAGE_SEEN_ID_FILE: &str = "seen_message.bin";
|
||||
|
|
|
@ -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<u64> = 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();
|
||||
|
|
|
@ -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<P: AsRef<std::path::Path>>(path: P, app_id: u64, mut setting: SettingsJson, given_name: String) -> Result<Self, SerdeError> {
|
||||
if !setting.persistent {
|
||||
return Self::open(path)
|
||||
}
|
||||
pub fn update_variant_or_create<P: AsRef<std::path::Path>>(
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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<dyn TCpus> = 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<dyn TGpu> = 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<dyn TBattery> = 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<dyn TCpus> = 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<dyn TGpu> = 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<dyn TBattery> = 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 {
|
||||
|
|
|
@ -93,14 +93,16 @@ pub fn get_limits_cached() -> Base {
|
|||
fn save_base(new_base: &Base, path: impl AsRef<std::path::Path>) {
|
||||
let limits_path = path.as_ref();
|
||||
match std::fs::File::create(&limits_path) {
|
||||
Ok(f) => match 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),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<BatteryJson> for Battery {
|
|||
}
|
||||
|
||||
impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
||||
fn from_json_and_limits(persist: BatteryJson, version: u64, limits: GenericBatteryLimit) -> Self {
|
||||
fn from_json_and_limits(
|
||||
persist: BatteryJson,
|
||||
version: u64,
|
||||
limits: GenericBatteryLimit,
|
||||
) -> Self {
|
||||
Battery {
|
||||
persist,
|
||||
version,
|
||||
|
@ -43,7 +47,12 @@ impl ProviderBuilder<BatteryJson, GenericBatteryLimit> 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<u64> {
|
||||
log::debug!("dev_mode_Battery::get_charge_rate(self) -> {:?}", self.persist.charge_rate);
|
||||
log::debug!(
|
||||
"dev_mode_Battery::get_charge_rate(self) -> {:?}",
|
||||
self.persist.charge_rate
|
||||
);
|
||||
self.persist.charge_rate
|
||||
}
|
||||
|
||||
|
@ -100,7 +118,10 @@ impl TBattery for Battery {
|
|||
}
|
||||
|
||||
fn get_charge_mode(&self) -> Option<String> {
|
||||
log::debug!("dev_mode_Battery::get_charge_mode(self) -> {:?}", self.persist.charge_mode);
|
||||
log::debug!(
|
||||
"dev_mode_Battery::get_charge_mode(self) -> {:?}",
|
||||
self.persist.charge_mode
|
||||
);
|
||||
self.persist.charge_mode.clone()
|
||||
}
|
||||
|
||||
|
@ -135,7 +156,10 @@ impl TBattery for Battery {
|
|||
}
|
||||
|
||||
fn get_charge_limit(&self) -> Option<f64> {
|
||||
log::debug!("dev_mode_Battery::get_charge_limit(self) -> {:?}", self.charge_limit);
|
||||
log::debug!(
|
||||
"dev_mode_Battery::get_charge_limit(self) -> {:?}",
|
||||
self.charge_limit
|
||||
);
|
||||
self.charge_limit
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
||||
fn from_json_and_limits(persistent: Vec<CpuJson>, version: u64, limits: GenericCpusLimit) -> Self {
|
||||
fn from_json_and_limits(
|
||||
persistent: Vec<CpuJson>,
|
||||
version: u64,
|
||||
limits: GenericCpusLimit,
|
||||
) -> Self {
|
||||
let mut cpus = Vec::with_capacity(persistent.len());
|
||||
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<MinMax<u64>>) {
|
||||
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<u64>> {
|
||||
log::debug!("dev_mode_Cpu::get_clock_limits(self) -> {:?}", self.clock_limits.as_ref());
|
||||
log::debug!(
|
||||
"dev_mode_Cpu::get_clock_limits(self) -> {:?}",
|
||||
self.clock_limits.as_ref()
|
||||
);
|
||||
self.clock_limits.as_ref()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<GpuJson, GenericGpuLimit> 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<u64>, slow: Option<u64>) {
|
||||
log::debug!("dev_mode_Gpu::ppt(self, fast: {:?}, slow: {:?})", fast, slow);
|
||||
log::debug!(
|
||||
"dev_mode_Gpu::ppt(self, fast: {:?}, slow: {:?})",
|
||||
fast,
|
||||
slow
|
||||
);
|
||||
self.persist.fast_ppt = fast;
|
||||
self.persist.slow_ppt = slow;
|
||||
}
|
||||
|
||||
fn get_ppt(&self) -> (Option<u64>, Option<u64>) {
|
||||
log::debug!("dev_mode_Gpu::get_ppt(self) -> (fast: {:?}, slow: {:?})", self.persist.fast_ppt, self.persist.slow_ppt);
|
||||
log::debug!(
|
||||
"dev_mode_Gpu::get_ppt(self) -> (fast: {:?}, slow: {:?})",
|
||||
self.persist.fast_ppt,
|
||||
self.persist.slow_ppt
|
||||
);
|
||||
(self.persist.fast_ppt, self.persist.slow_ppt)
|
||||
}
|
||||
|
||||
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) {
|
||||
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<u64>> {
|
||||
log::debug!("dev_mode_Gpu::get_clock_limits(self) -> {:?}", self.clock_limits.as_ref());
|
||||
log::debug!(
|
||||
"dev_mode_Gpu::get_clock_limits(self) -> {:?}",
|
||||
self.clock_limits.as_ref()
|
||||
);
|
||||
self.clock_limits.as_ref()
|
||||
}
|
||||
|
||||
|
@ -130,7 +171,10 @@ impl TGpu for Gpu {
|
|||
}
|
||||
|
||||
fn get_memory_clock(&self) -> Option<u64> {
|
||||
log::debug!("dev_mode_Gpu::memory_clock(self) -> {:?}", self.persist.memory_clock);
|
||||
log::debug!(
|
||||
"dev_mode_Gpu::memory_clock(self) -> {:?}",
|
||||
self.persist.memory_clock
|
||||
);
|
||||
self.persist.memory_clock
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,15 @@ pub use gpu::Gpu;
|
|||
fn _impl_checker() {
|
||||
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
||||
|
||||
impl_provider_builder::<Battery, crate::persist::BatteryJson, limits_core::json_v2::GenericBatteryLimit>();
|
||||
impl_provider_builder::<Cpus, Vec<crate::persist::CpuJson>, limits_core::json_v2::GenericCpusLimit>();
|
||||
impl_provider_builder::<
|
||||
Battery,
|
||||
crate::persist::BatteryJson,
|
||||
limits_core::json_v2::GenericBatteryLimit,
|
||||
>();
|
||||
impl_provider_builder::<
|
||||
Cpus,
|
||||
Vec<crate::persist::CpuJson>,
|
||||
limits_core::json_v2::GenericCpusLimit,
|
||||
>();
|
||||
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<crate::api::VariantInfo> {
|
||||
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<Vec<crate::api::VariantInfo>, SettingError> {
|
||||
fn add_variant(
|
||||
&self,
|
||||
variant: crate::persist::SettingsJson,
|
||||
) -> Result<Vec<crate::api::VariantInfo>, SettingError> {
|
||||
let variant_name = variant.name.clone();
|
||||
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<bool, SettingError> {
|
||||
let json_path = crate::utility::settings_dir().join(filename);
|
||||
|
|
|
@ -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<BatteryJson> 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<f64> {
|
||||
match self.sysfs.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::VoltageMax) {
|
||||
Ok(x) => Some(x/1000000.0),
|
||||
match self
|
||||
.sysfs
|
||||
.attribute::<f64, _>(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::<f64, _>(sysfuss::PowerSupplyAttribute::VoltageMin) {
|
||||
Ok(x) => Some(x/1000000.0),
|
||||
match self
|
||||
.sysfs
|
||||
.attribute::<f64, _>(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<BatteryJson, GenericBatteryLimit> 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<f64> {
|
||||
if let Some(battery_voltage) = self.get_design_voltage() {
|
||||
match self.sysfs.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::ChargeFull) {
|
||||
Ok(x) => Some(x/1000000.0 * battery_voltage),
|
||||
match self
|
||||
.sysfs
|
||||
.attribute::<f64, _>(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<f64> {
|
||||
if let Some(battery_voltage) = self.get_design_voltage() {
|
||||
match self.sysfs.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::ChargeNow) {
|
||||
Ok(x) => Some(x/1000000.0 * battery_voltage),
|
||||
match self
|
||||
.sysfs
|
||||
.attribute::<f64, _>(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<f64> {
|
||||
if let Some(battery_voltage) = self.get_design_voltage() {
|
||||
match self.sysfs.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::ChargeFullDesign) {
|
||||
Ok(x) => Some(x/1000000.0 * battery_voltage),
|
||||
match self
|
||||
.sysfs
|
||||
.attribute::<f64, _>(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<f64> {
|
||||
match self.sysfs.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::CurrentNow) {
|
||||
Ok(x) => Some(x/1000.0), // expects mA, reads uA
|
||||
match self
|
||||
.sysfs
|
||||
.attribute::<f64, _>(sysfuss::PowerSupplyAttribute::CurrentNow)
|
||||
{
|
||||
Ok(x) => Some(x / 1000.0), // expects mA, reads uA
|
||||
Err(e) => {
|
||||
log::warn!("read_current_now err: {}", e);
|
||||
None
|
||||
|
|
|
@ -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<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> Cpus<C> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus<C> {
|
||||
fn from_json_and_limits(mut other: Vec<CpuJson>, version: u64, limits: GenericCpusLimit) -> Self {
|
||||
impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo>
|
||||
ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus<C>
|
||||
{
|
||||
fn from_json_and_limits(
|
||||
mut other: Vec<CpuJson>,
|
||||
version: u64,
|
||||
limits: GenericCpusLimit,
|
||||
) -> Self {
|
||||
let (_, can_smt) = Self::system_smt_capabilities();
|
||||
let mut result = Vec::with_capacity(other.len());
|
||||
let max_cpus = Self::cpu_count();
|
||||
|
@ -103,9 +109,12 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> ProviderBuilder<Vec
|
|||
break;
|
||||
}
|
||||
}
|
||||
let cpu_limit = limits.cpus.get(i)
|
||||
let cpu_limit = limits
|
||||
.cpus
|
||||
.get(i)
|
||||
.or_else(|| limits.cpus.get(0))
|
||||
.unwrap_or_else(|| &fallback_cpu_limit).clone();
|
||||
.unwrap_or_else(|| &fallback_cpu_limit)
|
||||
.clone();
|
||||
let new_cpu = C::from_json_and_limits(cpu, version, i, cpu_limit);
|
||||
result.push(new_cpu);
|
||||
}
|
||||
|
@ -130,9 +139,12 @@ impl<C: AsMut<Cpu> + AsRef<Cpu> + TCpu + FromGenericCpuInfo> ProviderBuilder<Vec
|
|||
let mut new_cpus = Vec::with_capacity(cpu_count);
|
||||
let fallback_cpu_limit = GenericCpuLimit::default();
|
||||
for i in 0..cpu_count {
|
||||
let cpu_limit = limits.cpus.get(i)
|
||||
let cpu_limit = limits
|
||||
.cpus
|
||||
.get(i)
|
||||
.or_else(|| limits.cpus.get(0))
|
||||
.unwrap_or_else(|| &fallback_cpu_limit).clone();
|
||||
.unwrap_or_else(|| &fallback_cpu_limit)
|
||||
.clone();
|
||||
let new_cpu = C::from_limits(i, cpu_limit);
|
||||
new_cpus.push(new_cpu);
|
||||
}
|
||||
|
@ -221,7 +233,8 @@ pub struct Cpu {
|
|||
impl Cpu {
|
||||
#[inline]
|
||||
fn current_governor(index: usize) -> String {
|
||||
usdpl_back::api::files::read_single(cpu_governor_path(index)).unwrap_or_else(|_| "schedutil".to_owned())
|
||||
usdpl_back::api::files::read_single(cpu_governor_path(index))
|
||||
.unwrap_or_else(|_| "schedutil".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,9 @@ use sysfuss::{BasicEntityPath, SysEntity};
|
|||
|
||||
use crate::api::RangeLimit;
|
||||
use crate::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<impl AsRef<std::path::Path>>) -> 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<GpuJson, GenericGpuLimit> 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<GpuJson, GenericGpuLimit> 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<GpuJson> 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<u64>, slow: Option<u64>) {
|
||||
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<u64>, Option<u64>) {
|
||||
(self.fast_ppt.map(|x| if let Some(ppt_divisor) = self.limits.ppt_divisor { x / ppt_divisor } else { x }),
|
||||
self.slow_ppt.map(|x| if let Some(ppt_divisor) = self.limits.ppt_divisor { x / ppt_divisor } else { x }))
|
||||
(
|
||||
self.fast_ppt.map(|x| {
|
||||
if let Some(ppt_divisor) = self.limits.ppt_divisor {
|
||||
x / ppt_divisor
|
||||
} else {
|
||||
x
|
||||
}
|
||||
}),
|
||||
self.slow_ppt.map(|x| {
|
||||
if let Some(ppt_divisor) = self.limits.ppt_divisor {
|
||||
x / ppt_divisor
|
||||
} else {
|
||||
x
|
||||
}
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
fn clock_limits(&mut self, limits: Option<MinMax<u64>>) {
|
||||
|
|
|
@ -11,7 +11,15 @@ pub use traits::FromGenericCpuInfo;
|
|||
fn _impl_checker() {
|
||||
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
||||
|
||||
impl_provider_builder::<Battery, crate::persist::BatteryJson, limits_core::json_v2::GenericBatteryLimit>();
|
||||
impl_provider_builder::<Cpus<Cpu>, Vec<crate::persist::CpuJson>, limits_core::json_v2::GenericCpusLimit>();
|
||||
impl_provider_builder::<
|
||||
Battery,
|
||||
crate::persist::BatteryJson,
|
||||
limits_core::json_v2::GenericBatteryLimit,
|
||||
>();
|
||||
impl_provider_builder::<
|
||||
Cpus<Cpu>,
|
||||
Vec<crate::persist::CpuJson>,
|
||||
limits_core::json_v2::GenericCpusLimit,
|
||||
>();
|
||||
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<D: std::fmt::Display, E: std::fmt::Display>(output: &mut String, msg: &str, result: Result<D, E>) {
|
||||
fn msg_or_err<D: std::fmt::Display, E: std::fmt::Display>(
|
||||
output: &mut String,
|
||||
msg: &str,
|
||||
result: Result<D, E>,
|
||||
) {
|
||||
use std::fmt::Write;
|
||||
match result {
|
||||
Ok(val) => writeln!(output, "{}: {}", msg, val).unwrap(),
|
||||
|
@ -16,20 +20,41 @@ fn msg_or_err<D: std::fmt::Display, E: std::fmt::Display>(output: &mut String, m
|
|||
}
|
||||
|
||||
fn log_capabilities(ryzenadj: &RyzenAdj) {
|
||||
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<Mutex<RyzenAdj>> {
|
|||
Ok(x) => {
|
||||
log_capabilities(&x);
|
||||
Some(Mutex::new(x))
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("RyzenAdj init error: {}", e);
|
||||
None
|
||||
|
@ -90,7 +115,6 @@ impl ProviderBuilder<GpuJson, limits_core::json_v2::GenericGpuLimit> for Gpu {
|
|||
}
|
||||
|
||||
impl Gpu {
|
||||
|
||||
fn set_all(&mut self) -> Result<(), Vec<SettingError>> {
|
||||
let mutex = match &self.implementor {
|
||||
Some(x) => x,
|
||||
|
|
|
@ -7,6 +7,10 @@ pub use gpu::Gpu;
|
|||
fn _impl_checker() {
|
||||
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
||||
|
||||
impl_provider_builder::<Cpus, Vec<crate::persist::CpuJson>, limits_core::json_v2::GenericCpusLimit>();
|
||||
impl_provider_builder::<
|
||||
Cpus,
|
||||
Vec<crate::persist::CpuJson>,
|
||||
limits_core::json_v2::GenericCpusLimit,
|
||||
>();
|
||||
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<HwMonPath>, ec: Arc<Mutex<UnnamedPowerEC>>) -> Self {
|
||||
fn from_json(
|
||||
other: BatteryEventJson,
|
||||
_version: u64,
|
||||
hwmon: Arc<HwMonPath>,
|
||||
ec: Arc<Mutex<UnnamedPowerEC>>,
|
||||
) -> 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<BatteryJson> 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<BatteryJson, GenericBatteryLimit> for Battery {
|
||||
fn from_json_and_limits(persistent: BatteryJson, version: u64, limits: GenericBatteryLimit) -> Self {
|
||||
fn from_json_and_limits(
|
||||
persistent: BatteryJson,
|
||||
version: u64,
|
||||
limits: GenericBatteryLimit,
|
||||
) -> Self {
|
||||
let hwmon_sys = Arc::new(Self::find_hwmon_sysfs(None::<&'static str>));
|
||||
let ec = Arc::new(Mutex::new(UnnamedPowerEC::new()));
|
||||
match version {
|
||||
|
@ -586,14 +655,15 @@ impl ProviderBuilder<BatteryJson, GenericBatteryLimit> 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<BatteryJson, GenericBatteryLimit> 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<BatteryJson, GenericBatteryLimit> 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![
|
||||
|
|
|
@ -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<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
||||
fn from_json_and_limits(mut persistent: Vec<CpuJson>, version: u64, limits: GenericCpusLimit) -> Self {
|
||||
fn from_json_and_limits(
|
||||
mut persistent: Vec<CpuJson>,
|
||||
version: u64,
|
||||
limits: GenericCpusLimit,
|
||||
) -> Self {
|
||||
POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.reset();
|
||||
let (_, can_smt) = Self::system_smt_capabilities();
|
||||
let mut result = Vec::with_capacity(persistent.len());
|
||||
|
@ -123,18 +125,9 @@ impl ProviderBuilder<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
|||
}
|
||||
}
|
||||
let new_cpu = if let Some(cpu_limit) = limits.cpus.get(i) {
|
||||
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<Vec<CpuJson>, 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<impl AsRef<std::path::Path>>) -> 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<SettingError>> {
|
||||
|
@ -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<SettingError>> {
|
||||
|
@ -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<CpuJson> 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())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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/<attribute>
|
||||
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<impl AsRef<std::path::Path>>) -> 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<impl AsRef<std::path::Path>>) -> 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<SettingError>> {
|
||||
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<GpuJson> 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<GpuJson, GenericGpuLimit> 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<GpuJson, GenericGpuLimit> 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<u64>, Option<u64>) {
|
||||
(
|
||||
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::<usize>() {
|
||||
if let Some((freq, _unit)) = freq_mess.trim().split_once(|c: char| !c.is_digit(10)) {
|
||||
if let Some((freq, _unit)) =
|
||||
freq_mess.trim().split_once(|c: char| !c.is_digit(10))
|
||||
{
|
||||
if let Ok(freq) = freq.parse::<usize>() {
|
||||
result.push((val, freq));
|
||||
}
|
||||
|
|
|
@ -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<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
||||
|
||||
impl_provider_builder::<Battery, crate::persist::BatteryJson, limits_core::json_v2::GenericBatteryLimit>();
|
||||
impl_provider_builder::<Cpus, Vec<crate::persist::CpuJson>, limits_core::json_v2::GenericCpusLimit>();
|
||||
impl_provider_builder::<
|
||||
Battery,
|
||||
crate::persist::BatteryJson,
|
||||
limits_core::json_v2::GenericBatteryLimit,
|
||||
>();
|
||||
impl_provider_builder::<
|
||||
Cpus,
|
||||
Vec<crate::persist::CpuJson>,
|
||||
limits_core::json_v2::GenericCpusLimit,
|
||||
>();
|
||||
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
||||
}
|
||||
|
|
|
@ -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::<String, _>(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::<String, _>(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");
|
||||
}
|
||||
|
|
|
@ -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<I: Copy>(range: &Option<limits_core::json_v2::RangeLimit<I>>, fallback: I) -> I {
|
||||
pub fn range_min_or_fallback<I: Copy>(
|
||||
range: &Option<limits_core::json_v2::RangeLimit<I>>,
|
||||
fallback: I,
|
||||
) -> I {
|
||||
range.and_then(|lim| lim.min).unwrap_or(fallback)
|
||||
}
|
||||
|
||||
pub fn range_max_or_fallback<I: Copy>(range: &Option<limits_core::json_v2::RangeLimit<I>>, fallback: I) -> I {
|
||||
pub fn range_max_or_fallback<I: Copy>(
|
||||
range: &Option<limits_core::json_v2::RangeLimit<I>>,
|
||||
fallback: I,
|
||||
) -> I {
|
||||
range.and_then(|lim| lim.max).unwrap_or(fallback)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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<Vec<crate::api::VariantInfo>, SettingError>;
|
||||
fn add_variant(
|
||||
&self,
|
||||
variant: crate::persist::SettingsJson,
|
||||
) -> Result<Vec<crate::api::VariantInfo>, SettingError>;
|
||||
|
||||
fn provider(&self) -> crate::persist::DriverJson;
|
||||
}
|
||||
|
|
|
@ -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<BatteryJson> for Battery {
|
|||
}
|
||||
|
||||
impl ProviderBuilder<BatteryJson, GenericBatteryLimit> for Battery {
|
||||
fn from_json_and_limits(_persistent: BatteryJson, _version: u64, _limits: GenericBatteryLimit) -> Self {
|
||||
fn from_json_and_limits(
|
||||
_persistent: BatteryJson,
|
||||
_version: u64,
|
||||
_limits: GenericBatteryLimit,
|
||||
) -> Self {
|
||||
Battery::system_default()
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Vec<CpuJson>, GenericCpusLimit> for Cpus {
|
||||
fn from_json_and_limits(mut persistent: Vec<CpuJson>, version: u64, _limits: GenericCpusLimit) -> Self {
|
||||
fn from_json_and_limits(
|
||||
mut persistent: Vec<CpuJson>,
|
||||
version: u64,
|
||||
_limits: GenericCpusLimit,
|
||||
) -> Self {
|
||||
let (_, can_smt) = Self::system_smt_capabilities();
|
||||
let 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(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,15 @@ pub use gpu::Gpu;
|
|||
fn _impl_checker() {
|
||||
fn impl_provider_builder<T: crate::settings::ProviderBuilder<J, L>, J, L>() {}
|
||||
|
||||
impl_provider_builder::<Battery, crate::persist::BatteryJson, limits_core::json_v2::GenericBatteryLimit>();
|
||||
impl_provider_builder::<Cpus, Vec<crate::persist::CpuJson>, limits_core::json_v2::GenericCpusLimit>();
|
||||
impl_provider_builder::<
|
||||
Battery,
|
||||
crate::persist::BatteryJson,
|
||||
limits_core::json_v2::GenericBatteryLimit,
|
||||
>();
|
||||
impl_provider_builder::<
|
||||
Cpus,
|
||||
Vec<crate::persist::CpuJson>,
|
||||
limits_core::json_v2::GenericCpusLimit,
|
||||
>();
|
||||
impl_provider_builder::<Gpu, crate::persist::GpuJson, limits_core::json_v2::GenericGpuLimit>();
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
162
src/index.tsx
162
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: <span>{elem.name}</span>,
|
||||
};});
|
||||
console.log("variant options", variantOptions);
|
||||
console.log("current variant", get_value(CURRENT_VARIANT_GEN));
|
||||
console.log("variant selected", variantOptions.find((val: SingleDropdownOption, _index, _arr) => {
|
||||
backend.log(backend.LogLevel.Debug, "POWERTOOLS: looking for variant data.id " + (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).id.toString());
|
||||
return (val.data as backend.VariantInfo).id == (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).id;
|
||||
}));
|
||||
|
||||
return (
|
||||
<PanelSection>
|
||||
|
@ -383,83 +392,102 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => {
|
|||
<Field
|
||||
label={tr("Profile Variant")} // TODO translate
|
||||
>
|
||||
<Dropdown
|
||||
{(!isVariantLoading && <Dropdown
|
||||
menuLabel={tr("Profile Variant")}
|
||||
rgOptions={variantOptions}
|
||||
selectedOption={variantOptions.find((val: SingleDropdownOption, _index, _arr) => {
|
||||
backend.log(backend.LogLevel.Debug, "POWERTOOLS: looking for data " + (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).toString());
|
||||
backend.log(backend.LogLevel.Debug, "POWERTOOLS: looking for variant data.id " + (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).id.toString());
|
||||
return (val.data as backend.VariantInfo).id == (get_value(CURRENT_VARIANT_GEN) as backend.VariantInfo).id;
|
||||
})}
|
||||
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 && <Spinner/>)}
|
||||
</Field>
|
||||
</PanelSectionRow>
|
||||
<PanelSectionRow style={{
|
||||
alignItems: "center",
|
||||
display: "flex",
|
||||
justifyContent: "space-around",
|
||||
}}>
|
||||
<DialogButton
|
||||
style={{
|
||||
maxWidth: "30%",
|
||||
minWidth: "auto",
|
||||
}}
|
||||
//layout="below"
|
||||
onClick={(_: MouseEvent) => {
|
||||
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();
|
||||
});
|
||||
<PanelSectionRow>
|
||||
<Focusable style={{
|
||||
alignItems: "center",
|
||||
display: "flex",
|
||||
justifyContent: "space-around",
|
||||
}}
|
||||
flow-children="horizontal"
|
||||
>
|
||||
<DialogButton
|
||||
style={{
|
||||
maxWidth: "30%",
|
||||
minWidth: "auto",
|
||||
}}
|
||||
//layout="below"
|
||||
onClick={(_: MouseEvent) => {
|
||||
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();
|
||||
});
|
||||
}
|
||||
);
|
||||
}}
|
||||
>
|
||||
<HiPlus/>
|
||||
</DialogButton>
|
||||
<DialogButton
|
||||
style={{
|
||||
maxWidth: "30%",
|
||||
minWidth: "auto",
|
||||
}}
|
||||
//layout="below"
|
||||
onClick={(_: MouseEvent) => {
|
||||
const steamId = get_value(INTERNAL_STEAM_ID);
|
||||
const steamName = get_value(INTERNAL_STEAM_USERNAME);
|
||||
if (steamId && steamName) {
|
||||
backend.storeUpload(steamId, steamName);
|
||||
} else {
|
||||
backend.log(backend.LogLevel.Warn, "Cannot upload with null steamID (is null: " + !steamId + ") and/or username (is null: " + !steamName + ")");
|
||||
}
|
||||
);
|
||||
}}
|
||||
>
|
||||
<HiPlus/>
|
||||
</DialogButton>
|
||||
<DialogButton
|
||||
style={{
|
||||
maxWidth: "30%",
|
||||
minWidth: "auto",
|
||||
}}
|
||||
//layout="below"
|
||||
onClick={(_: MouseEvent) => {
|
||||
const steamId = get_value(INTERNAL_STEAM_ID);
|
||||
const steamName = get_value(INTERNAL_STEAM_USERNAME);
|
||||
if (steamId && steamName) {
|
||||
backend.storeUpload(steamId, steamName);
|
||||
} else {
|
||||
backend.log(backend.LogLevel.Warn, "Cannot upload with null steamID (is null: " + !steamId + ") and/or username (is null: " + !steamName + ")");
|
||||
}
|
||||
}}
|
||||
>
|
||||
<HiUpload/>
|
||||
</DialogButton>
|
||||
<DialogButton
|
||||
style={{
|
||||
maxWidth: "30%",
|
||||
minWidth: "auto",
|
||||
}}
|
||||
//layout="below"
|
||||
onClick={(_: MouseEvent) => {
|
||||
Navigation.Navigate(STORE_RESULTS_URI);
|
||||
Navigation.CloseSideMenus();
|
||||
}}
|
||||
>
|
||||
<TbWorldPlus />
|
||||
</DialogButton>
|
||||
}}
|
||||
>
|
||||
<HiUpload/>
|
||||
</DialogButton>
|
||||
<DialogButton
|
||||
style={{
|
||||
maxWidth: "30%",
|
||||
minWidth: "auto",
|
||||
}}
|
||||
//layout="below"
|
||||
onClick={(_: MouseEvent) => {
|
||||
Navigation.Navigate(STORE_RESULTS_URI);
|
||||
Navigation.CloseSideMenus();
|
||||
}}
|
||||
>
|
||||
<TbWorldPlus />
|
||||
</DialogButton>
|
||||
</Focusable>
|
||||
</PanelSectionRow>
|
||||
|
||||
<Debug idc={idc}/>
|
||||
|
|
Loading…
Reference in a new issue