Add hardware limits provider and auto detection with online updater (cached locally)
This commit is contained in:
parent
d1d5265224
commit
3766386726
34 changed files with 1864 additions and 139 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -44,3 +44,4 @@ yalc.lock
|
||||||
/backend/target
|
/backend/target
|
||||||
/bin
|
/bin
|
||||||
/backend/out
|
/backend/out
|
||||||
|
/**/target
|
||||||
|
|
129
backend/Cargo.lock
generated
129
backend/Cargo.lock
generated
|
@ -2,6 +2,12 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aead"
|
name = "aead"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
|
@ -38,6 +44,30 @@ dependencies = [
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aho-corasick"
|
||||||
|
version = "0.7.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloc-no-stdlib"
|
||||||
|
version = "2.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "alloc-stdlib"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
|
||||||
|
dependencies = [
|
||||||
|
"alloc-no-stdlib",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-recursion"
|
name = "async-recursion"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
@ -96,6 +126,16 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "brotli-decompressor"
|
||||||
|
version = "2.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80"
|
||||||
|
dependencies = [
|
||||||
|
"alloc-no-stdlib",
|
||||||
|
"alloc-stdlib",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "buf_redux"
|
name = "buf_redux"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
|
@ -124,6 +164,12 @@ version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chunked_transfer"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cipher"
|
name = "cipher"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -142,6 +188,15 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
@ -180,6 +235,15 @@ dependencies = [
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encoding_rs"
|
||||||
|
version = "0.8.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "1.8.0"
|
version = "1.8.0"
|
||||||
|
@ -189,6 +253,16 @@ dependencies = [
|
||||||
"instant",
|
"instant",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "flate2"
|
||||||
|
version = "1.0.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
|
||||||
|
dependencies = [
|
||||||
|
"crc32fast",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
@ -433,6 +507,14 @@ version = "0.2.126"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "limits_core"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.17"
|
version = "0.4.17"
|
||||||
|
@ -470,6 +552,15 @@ dependencies = [
|
||||||
"unicase",
|
"unicase",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.6.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
|
||||||
|
dependencies = [
|
||||||
|
"adler",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
|
@ -592,11 +683,14 @@ name = "powertools-rs"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
"limits_core",
|
||||||
"log",
|
"log",
|
||||||
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"simplelog",
|
"simplelog",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"ureq",
|
||||||
"usdpl-back",
|
"usdpl-back",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -669,6 +763,23 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
|
||||||
|
dependencies = [
|
||||||
|
"aho-corasick",
|
||||||
|
"memchr",
|
||||||
|
"regex-syntax",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex-syntax"
|
||||||
|
version = "0.6.28"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "remove_dir_all"
|
name = "remove_dir_all"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
@ -1063,6 +1174,24 @@ dependencies = [
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ureq"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b97acb4c28a254fd7a4aeec976c46a7fa404eac4d7c134b30c75144846d7cb8f"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"brotli-decompressor",
|
||||||
|
"chunked_transfer",
|
||||||
|
"encoding_rs",
|
||||||
|
"flate2",
|
||||||
|
"log",
|
||||||
|
"once_cell",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.2.2"
|
version = "2.2.2"
|
||||||
|
|
|
@ -18,11 +18,18 @@ async-trait = { version = "0.1" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
simplelog = "0.12"
|
simplelog = "0.12"
|
||||||
|
|
||||||
|
# limits & driver functionality
|
||||||
|
limits_core = { version = "0.1.0", path = "./limits_core" }
|
||||||
|
regex = "1"
|
||||||
|
# ureq's tls feature does not like musl targets
|
||||||
|
ureq = { version = "2.5", features = ["json", "gzip", "brotli", "charset"], default-features = false, optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = ["online"]
|
||||||
decky = ["usdpl-back/decky"]
|
decky = ["usdpl-back/decky"]
|
||||||
crankshaft = ["usdpl-back/crankshaft"]
|
crankshaft = ["usdpl-back/crankshaft"]
|
||||||
encrypt = ["usdpl-back/encrypt"]
|
encrypt = ["usdpl-back/encrypt"]
|
||||||
|
online = ["ureq"]
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
debug = false
|
debug = false
|
||||||
|
|
10
backend/limits_core/Cargo.toml
Normal file
10
backend/limits_core/Cargo.toml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
[package]
|
||||||
|
name = "limits_core"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0"
|
49
backend/limits_core/src/json/base.rs
Normal file
49
backend/limits_core/src/json/base.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
use std::default::Default;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// Base JSON limits information
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct Base {
|
||||||
|
/// System-specific configurations
|
||||||
|
pub configs: Vec<super::Config>,
|
||||||
|
/// URL from which to grab the next update
|
||||||
|
pub refresh: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Base {
|
||||||
|
fn default() -> Self {
|
||||||
|
Base {
|
||||||
|
configs: vec![
|
||||||
|
super::Config {
|
||||||
|
name: "Steam Deck".to_owned(),
|
||||||
|
conditions: super::Conditions {
|
||||||
|
dmi: None,
|
||||||
|
cpuinfo: Some("model name\t: AMD Custom APU 0405\n".to_owned()),
|
||||||
|
os: None,
|
||||||
|
command: None,
|
||||||
|
},
|
||||||
|
limits: vec![
|
||||||
|
super::Limits::Cpu(super::CpuLimit::SteamDeck),
|
||||||
|
super::Limits::Gpu(super::GpuLimit::SteamDeck),
|
||||||
|
super::Limits::Battery(super::BatteryLimit::SteamDeck),
|
||||||
|
]
|
||||||
|
},
|
||||||
|
super::Config {
|
||||||
|
name: "Fallback".to_owned(),
|
||||||
|
conditions: super::Conditions {
|
||||||
|
dmi: None,
|
||||||
|
cpuinfo: None,
|
||||||
|
os: None,
|
||||||
|
command: None,
|
||||||
|
},
|
||||||
|
limits: vec![
|
||||||
|
super::Limits::Cpu(super::CpuLimit::Unknown),
|
||||||
|
super::Limits::Gpu(super::GpuLimit::Unknown),
|
||||||
|
super::Limits::Battery(super::BatteryLimit::Unknown),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
refresh: Some("http://limits.ngni.us:45000/powertools/v1".to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
backend/limits_core/src/json/battery_limit.rs
Normal file
15
backend/limits_core/src/json/battery_limit.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(tag = "target")]
|
||||||
|
pub enum BatteryLimit {
|
||||||
|
SteamDeck,
|
||||||
|
SteamDeckAdvance,
|
||||||
|
Generic(GenericBatteryLimit),
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct GenericBatteryLimit {
|
||||||
|
/* TODO */
|
||||||
|
}
|
20
backend/limits_core/src/json/conditions.rs
Normal file
20
backend/limits_core/src/json/conditions.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// Conditions under which a config applies
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct Conditions {
|
||||||
|
/// Regex pattern for dmidecode output
|
||||||
|
pub dmi: Option<String>,
|
||||||
|
/// Regex pattern for /proc/cpuinfo reading
|
||||||
|
pub cpuinfo: Option<String>,
|
||||||
|
/// Regex pattern for /etc/os-release reading
|
||||||
|
pub os: Option<String>,
|
||||||
|
/// Custom command to run, where an exit code of 0 means a successful match
|
||||||
|
pub command: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Conditions {
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.dmi.is_none() && self.cpuinfo.is_none() && self.os.is_none() && self.command.is_none()
|
||||||
|
}
|
||||||
|
}
|
8
backend/limits_core/src/json/config.rs
Normal file
8
backend/limits_core/src/json/config.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct Config {
|
||||||
|
pub name: String,
|
||||||
|
pub conditions: super::Conditions,
|
||||||
|
pub limits: Vec<super::Limits>,
|
||||||
|
}
|
15
backend/limits_core/src/json/cpu_limit.rs
Normal file
15
backend/limits_core/src/json/cpu_limit.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(tag = "target")]
|
||||||
|
pub enum CpuLimit {
|
||||||
|
SteamDeck,
|
||||||
|
SteamDeckAdvance,
|
||||||
|
Generic(GenericCpuLimit),
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct GenericCpuLimit {
|
||||||
|
/* TODO */
|
||||||
|
}
|
15
backend/limits_core/src/json/gpu_limit.rs
Normal file
15
backend/limits_core/src/json/gpu_limit.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(tag = "target")]
|
||||||
|
pub enum GpuLimit {
|
||||||
|
SteamDeck,
|
||||||
|
SteamDeckAdvance,
|
||||||
|
Generic(GenericGpuLimit),
|
||||||
|
Unknown,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct GenericGpuLimit {
|
||||||
|
/* TODO */
|
||||||
|
}
|
9
backend/limits_core/src/json/limits.rs
Normal file
9
backend/limits_core/src/json/limits.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
#[serde(tag = "limits")]
|
||||||
|
pub enum Limits {
|
||||||
|
Cpu(super::CpuLimit),
|
||||||
|
Gpu(super::GpuLimit),
|
||||||
|
Battery(super::BatteryLimit),
|
||||||
|
}
|
17
backend/limits_core/src/json/mod.rs
Normal file
17
backend/limits_core/src/json/mod.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
mod base;
|
||||||
|
mod battery_limit;
|
||||||
|
mod conditions;
|
||||||
|
mod config;
|
||||||
|
mod cpu_limit;
|
||||||
|
mod gpu_limit;
|
||||||
|
mod limits;
|
||||||
|
mod target;
|
||||||
|
|
||||||
|
pub use base::Base;
|
||||||
|
pub use battery_limit::{BatteryLimit, GenericBatteryLimit};
|
||||||
|
pub use conditions::Conditions;
|
||||||
|
pub use cpu_limit::{CpuLimit, GenericCpuLimit};
|
||||||
|
pub use gpu_limit::{GpuLimit, GenericGpuLimit};
|
||||||
|
pub use config::Config;
|
||||||
|
pub use limits::Limits;
|
||||||
|
pub use target::Target;
|
9
backend/limits_core/src/json/target.rs
Normal file
9
backend/limits_core/src/json/target.rs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub enum Target {
|
||||||
|
SteamDeck,
|
||||||
|
SteamDeckAdvance,
|
||||||
|
Generic,
|
||||||
|
Unknown,
|
||||||
|
}
|
1
backend/limits_core/src/lib.rs
Normal file
1
backend/limits_core/src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod json;
|
1026
backend/limits_srv/Cargo.lock
generated
Normal file
1026
backend/limits_srv/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
12
backend/limits_srv/Cargo.toml
Normal file
12
backend/limits_srv/Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "limits_srv"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
limits_core = { version = "0.1.0", path = "../limits_core" }
|
||||||
|
serde_json = "1.0"
|
||||||
|
warp = { version = "0.3" }
|
||||||
|
tokio = { version = "1.22", features = ["macros", "rt", "rt-multi-thread"] }
|
43
backend/limits_srv/pt_limits.json
Normal file
43
backend/limits_srv/pt_limits.json
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
{
|
||||||
|
"configs": [
|
||||||
|
{
|
||||||
|
"name": "Steam Deck",
|
||||||
|
"conditions": {
|
||||||
|
"cpuinfo": "model name\t: AMD Custom APU 0405\n"
|
||||||
|
},
|
||||||
|
"limits": [
|
||||||
|
{
|
||||||
|
"limits": "Cpu",
|
||||||
|
"target": "SteamDeck"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"limits": "Gpu",
|
||||||
|
"target": "SteamDeck"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"limits": "Battery",
|
||||||
|
"target": "SteamDeck"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Fallback",
|
||||||
|
"conditions": {},
|
||||||
|
"limits": [
|
||||||
|
{
|
||||||
|
"limits": "Cpu",
|
||||||
|
"target": "Unknown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"limits": "Gpu",
|
||||||
|
"target": "Unknown"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"limits": "Battery",
|
||||||
|
"target": "Unknown"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"refresh": "http://limits.ngni.us:45000/powertools/v1"
|
||||||
|
}
|
53
backend/limits_srv/src/main.rs
Normal file
53
backend/limits_srv/src/main.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
use std::sync::atomic::{Ordering, AtomicU64};
|
||||||
|
use std::sync::{RwLock, Arc};
|
||||||
|
|
||||||
|
use warp::Filter;
|
||||||
|
|
||||||
|
use limits_core::json::Base;
|
||||||
|
|
||||||
|
static VISIT_COUNT: AtomicU64 = AtomicU64::new(0);
|
||||||
|
|
||||||
|
fn get_limits(base: Base) -> impl warp::Reply {
|
||||||
|
VISIT_COUNT.fetch_add(1, Ordering::AcqRel);
|
||||||
|
//println!("Count: {} + 1", old_count);
|
||||||
|
warp::reply::json(&base)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_visits() -> impl warp::Reply {
|
||||||
|
let count = VISIT_COUNT.load(Ordering::Relaxed);
|
||||||
|
//println!("Count: {}", count);
|
||||||
|
warp::reply::json(&count)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn routes(base: Arc<RwLock<Base>>) -> impl Filter<Extract = impl warp::Reply, Error = warp::Rejection> + Clone {
|
||||||
|
warp::get().and(
|
||||||
|
warp::path!("powertools" / "v1")
|
||||||
|
.map(move || {
|
||||||
|
let base = base.read().expect("Failed to acquire base limits read lock").clone();
|
||||||
|
get_limits(base)
|
||||||
|
})
|
||||||
|
.or(
|
||||||
|
warp::path!("powertools" / "count")
|
||||||
|
.map(get_visits)
|
||||||
|
)
|
||||||
|
).recover(recovery)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn recovery(reject: warp::Rejection) -> Result<impl warp::Reply, warp::Rejection> {
|
||||||
|
if reject.is_not_found() {
|
||||||
|
Ok(warp::hyper::StatusCode::NOT_FOUND)
|
||||||
|
} else {
|
||||||
|
Err(reject)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
let file = std::fs::File::open("./pt_limits.json").expect("Failed to read limits file");
|
||||||
|
let limits: Base = serde_json::from_reader(file).expect("Failed to parse limits file");
|
||||||
|
assert!(limits.refresh.is_some(), "`refresh` cannot be null, since it will brick future refreshes");
|
||||||
|
|
||||||
|
warp::serve(routes(Arc::new(RwLock::new(limits))))
|
||||||
|
.run(([0, 0, 0, 0], 8080))
|
||||||
|
.await;
|
||||||
|
}
|
|
@ -5,3 +5,5 @@ pub const PACKAGE_VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
||||||
pub const DEFAULT_SETTINGS_FILE: &str = "default_settings.json";
|
pub const DEFAULT_SETTINGS_FILE: &str = "default_settings.json";
|
||||||
pub const DEFAULT_SETTINGS_NAME: &str = "Main";
|
pub const DEFAULT_SETTINGS_NAME: &str = "Main";
|
||||||
|
|
||||||
|
pub const LIMITS_FILE: &str = "limits_cache.json";
|
||||||
|
|
|
@ -53,7 +53,8 @@ fn main() -> Result<(), ()> {
|
||||||
log::info!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION);
|
log::info!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION);
|
||||||
println!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION);
|
println!("Starting back-end ({} v{})", PACKAGE_NAME, PACKAGE_VERSION);
|
||||||
|
|
||||||
crate::settings::driver::auto_detect_loud();
|
let _limits_handle = crate::settings::limits_worker_spawn();
|
||||||
|
log::info!("Detected device automatically, starting with driver: {:?} (This can be overriden)", crate::settings::auto_detect_provider());
|
||||||
|
|
||||||
let mut loaded_settings = persist::SettingsJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE))
|
let mut loaded_settings = persist::SettingsJson::open(utility::settings_dir().join(DEFAULT_SETTINGS_FILE))
|
||||||
.map(|settings| settings::Settings::from_json(settings, DEFAULT_SETTINGS_FILE.into()))
|
.map(|settings| settings::Settings::from_json(settings, DEFAULT_SETTINGS_FILE.into()))
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::default::Default;
|
||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct BatteryJson {
|
pub struct BatteryJson {
|
||||||
pub charge_rate: Option<u64>,
|
pub charge_rate: Option<u64>,
|
||||||
pub charge_mode: Option<String>,
|
pub charge_mode: Option<String>,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use super::MinMaxJson;
|
||||||
|
|
||||||
//const SCALING_FREQUENCIES: &[u64] = &[1700000, 2400000, 2800000];
|
//const SCALING_FREQUENCIES: &[u64] = &[1700000, 2400000, 2800000];
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct CpuJson {
|
pub struct CpuJson {
|
||||||
pub online: bool,
|
pub online: bool,
|
||||||
pub clock_limits: Option<MinMaxJson<u64>>,
|
pub clock_limits: Option<MinMaxJson<u64>>,
|
||||||
|
|
|
@ -4,7 +4,6 @@ use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Default, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Default, Debug, Clone)]
|
||||||
pub enum DriverJson {
|
pub enum DriverJson {
|
||||||
#[default]
|
|
||||||
#[serde(rename = "steam-deck", alias = "gabe-boy")]
|
#[serde(rename = "steam-deck", alias = "gabe-boy")]
|
||||||
SteamDeck,
|
SteamDeck,
|
||||||
#[serde(rename = "steam-deck-oc", alias = "gabe-boy-advance")]
|
#[serde(rename = "steam-deck-oc", alias = "gabe-boy-advance")]
|
||||||
|
@ -13,4 +12,7 @@ pub enum DriverJson {
|
||||||
Generic,
|
Generic,
|
||||||
#[serde(rename = "unknown")]
|
#[serde(rename = "unknown")]
|
||||||
Unknown,
|
Unknown,
|
||||||
|
#[default]
|
||||||
|
#[serde(rename = "auto")]
|
||||||
|
AutoDetect,
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ impl SettingsJson {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct MinMaxJson<T> {
|
pub struct MinMaxJson<T> {
|
||||||
pub max: T,
|
pub max: T,
|
||||||
pub min: T,
|
pub min: T,
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::default::Default;
|
||||||
use super::MinMaxJson;
|
use super::MinMaxJson;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct GpuJson {
|
pub struct GpuJson {
|
||||||
pub fast_ppt: Option<u64>,
|
pub fast_ppt: Option<u64>,
|
||||||
pub slow_ppt: Option<u64>,
|
pub slow_ppt: Option<u64>,
|
||||||
|
|
191
backend/src/settings/detect/auto_detect.rs
Normal file
191
backend/src/settings/detect/auto_detect.rs
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
use std::fs::File;
|
||||||
|
|
||||||
|
use regex::RegexBuilder;
|
||||||
|
|
||||||
|
use limits_core::json::{Limits, BatteryLimit, CpuLimit, GpuLimit};
|
||||||
|
|
||||||
|
use crate::persist::{DriverJson, SettingsJson};
|
||||||
|
use crate::settings::{TGeneral, TCpus, TGpu, TBattery, Driver, General};
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn auto_detect_provider() -> DriverJson {
|
||||||
|
let provider = auto_detect0(None, crate::utility::settings_dir().join("autodetect.json"))
|
||||||
|
.general
|
||||||
|
.provider();
|
||||||
|
//log::info!("Detected device automatically, compatible driver: {:?}", provider);
|
||||||
|
provider
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Device detection logic
|
||||||
|
pub fn auto_detect0(settings_opt: Option<SettingsJson>, json_path: std::path::PathBuf) -> Driver {
|
||||||
|
let mut builder = DriverBuilder::new(json_path);
|
||||||
|
|
||||||
|
let cpu_info: String = usdpl_back::api::files::read_single("/proc/cpuinfo").unwrap_or_default();
|
||||||
|
log::debug!("Read from /proc/cpuinfo:\n{}", cpu_info);
|
||||||
|
let os_info: String = usdpl_back::api::files::read_single("/etc/os-release").unwrap_or_default();
|
||||||
|
log::debug!("Read from /etc/os-release:\n{}", os_info);
|
||||||
|
let dmi_info: String = std::process::Command::new("dmidecode").output().map(|out| String::from_utf8_lossy(&out.stdout).into_owned()).unwrap_or_default();
|
||||||
|
log::debug!("Read dmidecode:\n{}", dmi_info);
|
||||||
|
|
||||||
|
let limits_path = super::utility::limits_path();
|
||||||
|
let limits = match File::open(&limits_path) {
|
||||||
|
Ok(f) => {
|
||||||
|
match serde_json::from_reader(f) {
|
||||||
|
Ok(lim) => lim,
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Failed to parse limits file `{}`, cannot use for auto_detect: {}", limits_path.display(), e);
|
||||||
|
limits_core::json::Base::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Failed to open limits file `{}` (trying force refresh...): {}", limits_path.display(), e);
|
||||||
|
super::limits_worker::get_limits_blocking()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// build driver based on limits conditions
|
||||||
|
for conf in limits.configs {
|
||||||
|
let conditions = conf.conditions;
|
||||||
|
let mut matches = true;
|
||||||
|
if conditions.is_empty() {
|
||||||
|
matches = !builder.is_complete();
|
||||||
|
} else {
|
||||||
|
if let Some(dmi) = &conditions.dmi {
|
||||||
|
let pattern = RegexBuilder::new(dmi)
|
||||||
|
.multi_line(true)
|
||||||
|
.build()
|
||||||
|
.expect("Invalid DMI regex");
|
||||||
|
matches &=pattern.is_match(&dmi_info);
|
||||||
|
}
|
||||||
|
if let Some(cpuinfo) = &conditions.cpuinfo {
|
||||||
|
let pattern = RegexBuilder::new(cpuinfo)
|
||||||
|
.multi_line(true)
|
||||||
|
.build()
|
||||||
|
.expect("Invalid CPU regex");
|
||||||
|
matches &=pattern.is_match(&cpu_info);
|
||||||
|
}
|
||||||
|
if let Some(os) = &conditions.os {
|
||||||
|
let pattern = RegexBuilder::new(os)
|
||||||
|
.multi_line(true)
|
||||||
|
.build()
|
||||||
|
.expect("Invalid OS regex");
|
||||||
|
matches &=pattern.is_match(&os_info);
|
||||||
|
}
|
||||||
|
if let Some(cmd) = &conditions.command {
|
||||||
|
match std::process::Command::new("bash")
|
||||||
|
.args(["-c", cmd])
|
||||||
|
.status() {
|
||||||
|
Ok(status) => matches &= status.code().map(|c| c == 0).unwrap_or(false),
|
||||||
|
Err(e) => log::warn!("Ignoring bash limits error: {}", e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matches {
|
||||||
|
if let Some(settings) = &settings_opt {
|
||||||
|
for limit in conf.limits {
|
||||||
|
match limit {
|
||||||
|
Limits::Cpu(cpus) => {
|
||||||
|
let cpu_driver: Box<dyn TCpus> = match cpus {
|
||||||
|
CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::from_json(settings.cpus.clone(), settings.version)),
|
||||||
|
CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Cpus::from_json(settings.cpus.clone(), settings.version)),
|
||||||
|
CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_json_and_limits(settings.cpus.clone(), settings.version, x)),
|
||||||
|
CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::from_json(settings.cpus.clone(), settings.version)),
|
||||||
|
};
|
||||||
|
builder.cpus = Some(cpu_driver);
|
||||||
|
},
|
||||||
|
Limits::Gpu(gpu) => {
|
||||||
|
let driver: Box<dyn TGpu> = match gpu {
|
||||||
|
GpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Gpu::from_json(settings.gpu.clone(), settings.version)),
|
||||||
|
GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Gpu::from_json(settings.gpu.clone(), settings.version)),
|
||||||
|
GpuLimit::Generic(x) => Box::new(crate::settings::generic::Gpu::from_json_and_limits(settings.gpu.clone(), settings.version, x)),
|
||||||
|
GpuLimit::Unknown => Box::new(crate::settings::unknown::Gpu::from_json(settings.gpu.clone(), settings.version)),
|
||||||
|
};
|
||||||
|
builder.gpu = Some(driver);
|
||||||
|
},
|
||||||
|
Limits::Battery(batt) => {
|
||||||
|
let driver: Box<dyn TBattery> = match batt {
|
||||||
|
BatteryLimit::SteamDeck => Box::new(crate::settings::steam_deck::Battery::from_json(settings.battery.clone(), settings.version)),
|
||||||
|
BatteryLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Battery::from_json(settings.battery.clone(), settings.version)),
|
||||||
|
BatteryLimit::Generic(x) => Box::new(crate::settings::generic::Battery::from_json_and_limits(settings.battery.clone(), settings.version, x)),
|
||||||
|
BatteryLimit::Unknown => Box::new(crate::settings::unknown::Battery),
|
||||||
|
};
|
||||||
|
builder.battery = Some(driver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for limit in conf.limits {
|
||||||
|
match limit {
|
||||||
|
Limits::Cpu(cpus) => {
|
||||||
|
let cpu_driver: Box<dyn TCpus> = match cpus {
|
||||||
|
CpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Cpus::system_default()),
|
||||||
|
CpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Cpus::system_default()),
|
||||||
|
CpuLimit::Generic(x) => Box::new(crate::settings::generic::Cpus::from_limits(x)),
|
||||||
|
CpuLimit::Unknown => Box::new(crate::settings::unknown::Cpus::system_default()),
|
||||||
|
};
|
||||||
|
builder.cpus = Some(cpu_driver);
|
||||||
|
},
|
||||||
|
Limits::Gpu(gpu) => {
|
||||||
|
let driver: Box<dyn TGpu> = match gpu {
|
||||||
|
GpuLimit::SteamDeck => Box::new(crate::settings::steam_deck::Gpu::system_default()),
|
||||||
|
GpuLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck_adv::Gpu::system_default()),
|
||||||
|
GpuLimit::Generic(x) => Box::new(crate::settings::generic::Gpu::from_limits(x)),
|
||||||
|
GpuLimit::Unknown => Box::new(crate::settings::unknown::Gpu::system_default()),
|
||||||
|
};
|
||||||
|
builder.gpu = Some(driver);
|
||||||
|
},
|
||||||
|
Limits::Battery(batt) => {
|
||||||
|
let driver: Box<dyn TBattery> = match batt {
|
||||||
|
BatteryLimit::SteamDeck => Box::new(crate::settings::steam_deck::Battery::system_default()),
|
||||||
|
BatteryLimit::SteamDeckAdvance => Box::new(crate::settings::steam_deck::Battery::system_default()),
|
||||||
|
BatteryLimit::Generic(x) => Box::new(crate::settings::generic::Battery::from_limits(x)),
|
||||||
|
BatteryLimit::Unknown => Box::new(crate::settings::unknown::Battery),
|
||||||
|
};
|
||||||
|
builder.battery = Some(driver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DriverBuilder {
|
||||||
|
general: Box<dyn TGeneral>,
|
||||||
|
cpus: Option<Box<dyn TCpus>>,
|
||||||
|
gpu: Option<Box<dyn TGpu>>,
|
||||||
|
battery: Option<Box<dyn TBattery>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DriverBuilder {
|
||||||
|
fn new(json_path: std::path::PathBuf) -> Self {
|
||||||
|
Self {
|
||||||
|
general: Box::new(General {
|
||||||
|
persistent: false,
|
||||||
|
path: json_path,
|
||||||
|
name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
||||||
|
driver: DriverJson::AutoDetect,
|
||||||
|
}),
|
||||||
|
cpus: None,
|
||||||
|
gpu: None,
|
||||||
|
battery: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_complete(&self) -> bool {
|
||||||
|
self.cpus.is_some() && self.gpu.is_some() && self.battery.is_some()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build(self) -> Driver {
|
||||||
|
Driver {
|
||||||
|
general: self.general,
|
||||||
|
cpus: self.cpus.unwrap_or_else(|| Box::new(crate::settings::unknown::Cpus::system_default())),
|
||||||
|
gpu: self.gpu.unwrap_or_else(|| Box::new(crate::settings::unknown::Gpu::system_default())),
|
||||||
|
battery: self.battery.unwrap_or_else(|| Box::new(crate::settings::unknown::Battery))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
110
backend/src/settings/detect/limits_worker.rs
Normal file
110
backend/src/settings/detect/limits_worker.rs
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
use std::thread::{self, JoinHandle};
|
||||||
|
#[cfg(feature = "online")]
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use limits_core::json::Base;
|
||||||
|
|
||||||
|
#[cfg(feature = "online")]
|
||||||
|
pub fn spawn() -> JoinHandle<()> {
|
||||||
|
thread::spawn(move || {
|
||||||
|
log::info!("limits_worker starting...");
|
||||||
|
let sleep_dur = Duration::from_secs(60*60*24); // 1 day
|
||||||
|
let limits_path = super::utility::limits_path();
|
||||||
|
loop {
|
||||||
|
thread::sleep(sleep_dur);
|
||||||
|
if (limits_path.exists() && limits_path.is_file()) || !limits_path.exists() {
|
||||||
|
// try to load limits from file, fallback to built-in default
|
||||||
|
let base = match std::fs::File::open(&limits_path) {
|
||||||
|
Ok(f) => {
|
||||||
|
match serde_json::from_reader(f) {
|
||||||
|
Ok(b) => b,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Cannot parse {}: {}", limits_path.display(), e);
|
||||||
|
Base::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Cannot open {}: {}", limits_path.display(), e);
|
||||||
|
Base::default()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(refresh) = &base.refresh {
|
||||||
|
// try to retrieve newer version
|
||||||
|
match ureq::get(refresh)
|
||||||
|
.call() {
|
||||||
|
Ok(response) => {
|
||||||
|
let json_res: std::io::Result<Base> = response.into_json();
|
||||||
|
match json_res {
|
||||||
|
Ok(new_base) => {
|
||||||
|
match std::fs::File::create(&limits_path) {
|
||||||
|
Ok(f) => {
|
||||||
|
match serde_json::to_writer_pretty(f, &new_base) {
|
||||||
|
Ok(_) => log::info!("Successfully updated limits from `{}`, cached at {}", refresh, limits_path.display()),
|
||||||
|
Err(e) => log::error!("Failed to save limits json to file `{}`: {}", limits_path.display(), e),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => log::error!("Cannot create {}: {}", limits_path.display(), e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => log::error!("Cannot parse response from `{}`: {}", refresh, e),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => log::warn!("Cannot download limits from `{}`: {}", refresh, e),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::info!("limits_worker refresh is empty, terminating...");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if !limits_path.is_file() {
|
||||||
|
log::error!("Path for storing limits is not a file!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log::warn!("limits_worker completed!");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "online"))]
|
||||||
|
pub fn spawn() -> JoinHandle<()> {
|
||||||
|
thread::spawn(move || {
|
||||||
|
log::info!("limits_worker disabled...");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_limits_blocking() -> Base {
|
||||||
|
let limits_path = super::utility::limits_path();
|
||||||
|
if limits_path.is_file() {
|
||||||
|
match std::fs::File::open(&limits_path) {
|
||||||
|
Ok(f) => {
|
||||||
|
match serde_json::from_reader(f) {
|
||||||
|
Ok(b) => b,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Cannot parse {}: {}", limits_path.display(), e);
|
||||||
|
Base::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
log::error!("Cannot open {}: {}", limits_path.display(), e);
|
||||||
|
Base::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#[cfg(feature = "online")]
|
||||||
|
{
|
||||||
|
let refresh = Base::default().refresh.unwrap();
|
||||||
|
match ureq::get(&refresh) // try to retrieve newer version
|
||||||
|
.call() {
|
||||||
|
Ok(response) => {
|
||||||
|
let json_res: std::io::Result<Base> = response.into_json();
|
||||||
|
match json_res {
|
||||||
|
Ok(new_base) => return new_base,
|
||||||
|
Err(e) => log::error!("Cannot parse response from `{}`: {}", refresh, e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => log::warn!("Cannot download limits from `{}`: {}", refresh, e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Base::default()
|
||||||
|
}
|
||||||
|
}
|
5
backend/src/settings/detect/mod.rs
Normal file
5
backend/src/settings/detect/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
mod auto_detect;
|
||||||
|
pub mod limits_worker;
|
||||||
|
mod utility;
|
||||||
|
|
||||||
|
pub use auto_detect::{auto_detect_provider, auto_detect0};
|
3
backend/src/settings/detect/utility.rs
Normal file
3
backend/src/settings/detect/utility.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
pub fn limits_path() -> std::path::PathBuf {
|
||||||
|
crate::utility::settings_dir().join(crate::consts::LIMITS_FILE)
|
||||||
|
}
|
|
@ -1,44 +1,5 @@
|
||||||
use crate::persist::{DriverJson, SettingsJson};
|
use crate::persist::{DriverJson, SettingsJson};
|
||||||
use super::{TGeneral, TCpus, TGpu, TBattery, SettingError, General};
|
use super::{TGeneral, TCpus, TGpu, TBattery, SettingError, General, auto_detect0};
|
||||||
|
|
||||||
/// Device detection logic
|
|
||||||
fn auto_detect() -> DriverJson {
|
|
||||||
let lscpu: String = match usdpl_back::api::files::read_single("/proc/cpuinfo") {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(_) => return DriverJson::Unknown,
|
|
||||||
};
|
|
||||||
log::debug!("Read from /proc/cpuinfo:\n{}", lscpu);
|
|
||||||
let os_info: String = match usdpl_back::api::files::read_single("/etc/os-release") {
|
|
||||||
Ok(s) => s,
|
|
||||||
Err(_) => return DriverJson::Unknown,
|
|
||||||
};
|
|
||||||
log::debug!("Read from /etc/os-release:\n{}", os_info);
|
|
||||||
if let Some(_) = lscpu.find("model name\t: AMD Custom APU 0405\n") {
|
|
||||||
// definitely a Steam Deck, check if it's overclocked
|
|
||||||
// TODO: this auto-detect doesn't work
|
|
||||||
// look for a file instead?
|
|
||||||
let max_freq: u64 = match usdpl_back::api::files::read_single("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq") {
|
|
||||||
Ok(u) => u,
|
|
||||||
Err(_) => return DriverJson::SteamDeck,
|
|
||||||
};
|
|
||||||
if max_freq == 2800000 { // default clock speed
|
|
||||||
DriverJson::SteamDeck
|
|
||||||
} else {
|
|
||||||
DriverJson::SteamDeckAdvance
|
|
||||||
}
|
|
||||||
} else if let Some(_) = lscpu.find("model name\t: AMD Ryzen") {
|
|
||||||
DriverJson::Generic
|
|
||||||
} else {
|
|
||||||
DriverJson::Unknown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn auto_detect_loud() -> DriverJson {
|
|
||||||
let provider = auto_detect();
|
|
||||||
log::info!("Detected device automatically, compatible driver: {:?}", provider);
|
|
||||||
provider
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Driver {
|
pub struct Driver {
|
||||||
pub general: Box<dyn TGeneral>,
|
pub general: Box<dyn TGeneral>,
|
||||||
|
@ -66,110 +27,58 @@ impl Driver {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn version0(settings: SettingsJson, json_path: std::path::PathBuf) -> Result<Self, SettingError> {
|
fn version0(settings: SettingsJson, json_path: std::path::PathBuf) -> Result<Self, SettingError> {
|
||||||
let provider = settings.provider.unwrap_or_else(auto_detect);
|
if let Some(provider) = &settings.provider {
|
||||||
match provider {
|
match provider {
|
||||||
DriverJson::SteamDeck => Ok(Self {
|
DriverJson::SteamDeck => Ok(Self {
|
||||||
general: Box::new(General {
|
general: Box::new(General {
|
||||||
persistent: settings.persistent,
|
persistent: settings.persistent,
|
||||||
path: json_path,
|
path: json_path,
|
||||||
name: settings.name,
|
name: settings.name,
|
||||||
driver: DriverJson::SteamDeck,
|
driver: DriverJson::SteamDeck,
|
||||||
|
}),
|
||||||
|
cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, settings.version)),
|
||||||
|
gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)),
|
||||||
|
battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)),
|
||||||
}),
|
}),
|
||||||
cpus: Box::new(super::steam_deck::Cpus::from_json(settings.cpus, settings.version)),
|
DriverJson::SteamDeckAdvance => Ok(Self {
|
||||||
gpu: Box::new(super::steam_deck::Gpu::from_json(settings.gpu, settings.version)),
|
general: Box::new(General {
|
||||||
battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)),
|
persistent: settings.persistent,
|
||||||
}),
|
path: json_path,
|
||||||
DriverJson::SteamDeckAdvance => Ok(Self {
|
name: settings.name,
|
||||||
general: Box::new(General {
|
driver: DriverJson::SteamDeckAdvance,
|
||||||
persistent: settings.persistent,
|
}),
|
||||||
path: json_path,
|
cpus: Box::new(super::steam_deck_adv::Cpus::from_json(settings.cpus, settings.version)),
|
||||||
name: settings.name,
|
gpu: Box::new(super::steam_deck_adv::Gpu::from_json(settings.gpu, settings.version)),
|
||||||
driver: DriverJson::SteamDeckAdvance,
|
battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)),
|
||||||
}),
|
}),
|
||||||
cpus: Box::new(super::steam_deck_adv::Cpus::from_json(settings.cpus, settings.version)),
|
DriverJson::Generic => Ok(Self {
|
||||||
gpu: Box::new(super::steam_deck_adv::Gpu::from_json(settings.gpu, settings.version)),
|
general: Box::new(General {
|
||||||
battery: Box::new(super::steam_deck::Battery::from_json(settings.battery, settings.version)),
|
persistent: settings.persistent,
|
||||||
}),
|
path: json_path,
|
||||||
DriverJson::Generic => Ok(Self {
|
name: settings.name,
|
||||||
general: Box::new(General {
|
driver: DriverJson::Unknown,
|
||||||
persistent: settings.persistent,
|
}),
|
||||||
path: json_path,
|
cpus: Box::new(super::generic::Cpus::from_json(settings.cpus, settings.version)),
|
||||||
name: settings.name,
|
gpu: Box::new(super::generic::Gpu::from_json(settings.gpu, settings.version)),
|
||||||
driver: DriverJson::Unknown,
|
battery: Box::new(super::generic::Battery),
|
||||||
}),
|
}),
|
||||||
cpus: Box::new(super::generic::Cpus::from_json(settings.cpus, settings.version)),
|
DriverJson::Unknown => Ok(super::detect::auto_detect0(Some(settings), json_path)),
|
||||||
gpu: Box::new(super::generic::Gpu::from_json(settings.gpu, settings.version)),
|
DriverJson::AutoDetect => Ok(super::detect::auto_detect0(Some(settings), json_path)),
|
||||||
battery: Box::new(super::generic::Battery),
|
}
|
||||||
}),
|
} else {
|
||||||
DriverJson::Unknown => Ok(Self {
|
Ok(super::detect::auto_detect0(Some(settings), json_path))
|
||||||
general: Box::new(General {
|
|
||||||
persistent: settings.persistent,
|
|
||||||
path: json_path,
|
|
||||||
name: settings.name,
|
|
||||||
driver: DriverJson::Unknown,
|
|
||||||
}),
|
|
||||||
cpus: Box::new(super::unknown::Cpus::from_json(settings.cpus, settings.version)),
|
|
||||||
gpu: Box::new(super::unknown::Gpu::from_json(settings.gpu, settings.version)),
|
|
||||||
battery: Box::new(super::unknown::Battery),
|
|
||||||
}),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn system_default(json_path: std::path::PathBuf) -> Self {
|
pub fn system_default(json_path: std::path::PathBuf) -> Self {
|
||||||
let provider = auto_detect();
|
auto_detect0(None, json_path)
|
||||||
match provider {
|
|
||||||
DriverJson::SteamDeck => Self {
|
|
||||||
general: Box::new(General {
|
|
||||||
persistent: false,
|
|
||||||
path: json_path,
|
|
||||||
name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
|
||||||
driver: DriverJson::SteamDeck,
|
|
||||||
}),
|
|
||||||
cpus: Box::new(super::steam_deck::Cpus::system_default()),
|
|
||||||
gpu: Box::new(super::steam_deck::Gpu::system_default()),
|
|
||||||
battery: Box::new(super::steam_deck::Battery::system_default()),
|
|
||||||
},
|
|
||||||
DriverJson::SteamDeckAdvance => Self {
|
|
||||||
general: Box::new(General {
|
|
||||||
persistent: false,
|
|
||||||
path: json_path,
|
|
||||||
name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
|
||||||
driver: DriverJson::SteamDeck,
|
|
||||||
}),
|
|
||||||
cpus: Box::new(super::steam_deck_adv::Cpus::system_default()),
|
|
||||||
gpu: Box::new(super::steam_deck_adv::Gpu::system_default()),
|
|
||||||
battery: Box::new(super::steam_deck::Battery::system_default()),
|
|
||||||
},
|
|
||||||
DriverJson::Generic => Self {
|
|
||||||
general: Box::new(General {
|
|
||||||
persistent: false,
|
|
||||||
path: json_path,
|
|
||||||
name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
|
||||||
driver: DriverJson::Unknown,
|
|
||||||
}),
|
|
||||||
cpus: Box::new(super::generic::Cpus::system_default()),
|
|
||||||
gpu: Box::new(super::generic::Gpu::system_default()),
|
|
||||||
battery: Box::new(super::generic::Battery),
|
|
||||||
},
|
|
||||||
DriverJson::Unknown => Self {
|
|
||||||
general: Box::new(General {
|
|
||||||
persistent: false,
|
|
||||||
path: json_path,
|
|
||||||
name: crate::consts::DEFAULT_SETTINGS_NAME.to_owned(),
|
|
||||||
driver: DriverJson::Unknown,
|
|
||||||
}),
|
|
||||||
cpus: Box::new(super::unknown::Cpus::system_default()),
|
|
||||||
gpu: Box::new(super::unknown::Gpu::system_default()),
|
|
||||||
battery: Box::new(super::unknown::Battery),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sshhhh, this function isn't here ;)
|
// sshhhh, this function isn't here ;)
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn maybe_do_button() {
|
pub fn maybe_do_button() {
|
||||||
match auto_detect() {
|
match super::auto_detect_provider() {
|
||||||
DriverJson::SteamDeck | DriverJson::SteamDeckAdvance => {
|
DriverJson::SteamDeck | DriverJson::SteamDeckAdvance => {
|
||||||
let period = std::time::Duration::from_millis(500);
|
let period = std::time::Duration::from_millis(500);
|
||||||
for _ in 0..10 {
|
for _ in 0..10 {
|
||||||
|
@ -185,5 +94,6 @@ pub fn maybe_do_button() {
|
||||||
},
|
},
|
||||||
DriverJson::Generic => log::warn!("You need to come up with something fun on generic"),
|
DriverJson::Generic => log::warn!("You need to come up with something fun on generic"),
|
||||||
DriverJson::Unknown => log::warn!("Can't do button activities on unknown platform"),
|
DriverJson::Unknown => log::warn!("Can't do button activities on unknown platform"),
|
||||||
|
DriverJson::AutoDetect => log::warn!("WTF, why is auto_detect detecting AutoDetect???")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,16 @@ impl Battery {
|
||||||
Ok(val) => Ok(val / 1000.0),
|
Ok(val) => Ok(val / 1000.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_limits(_limits: limits_core::json::GenericBatteryLimit) -> Self {
|
||||||
|
// TODO
|
||||||
|
Self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_json_and_limits(_other: BatteryJson, _version: u64, _limits: limits_core::json::GenericBatteryLimit) -> Self {
|
||||||
|
// TODO
|
||||||
|
Self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OnSet for Battery {
|
impl OnSet for Battery {
|
||||||
|
|
|
@ -128,6 +128,43 @@ impl Cpus {
|
||||||
smt_capable: can_smt,
|
smt_capable: can_smt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_limits(_limits: limits_core::json::GenericCpuLimit) -> Self {
|
||||||
|
// TODO
|
||||||
|
Self {
|
||||||
|
cpus: vec![],
|
||||||
|
smt: false,
|
||||||
|
smt_capable: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_json_and_limits(mut other: Vec<CpuJson>, version: u64, _limits: limits_core::json::GenericCpuLimit) -> Self {
|
||||||
|
let (_, can_smt) = Self::system_smt_capabilities();
|
||||||
|
let mut result = Vec::with_capacity(other.len());
|
||||||
|
let max_cpus = Self::cpu_count();
|
||||||
|
for (i, cpu) in other.drain(..).enumerate() {
|
||||||
|
// prevent having more CPUs than available
|
||||||
|
if let Some(max_cpus) = max_cpus {
|
||||||
|
if i == max_cpus {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push(Cpu::from_json(cpu, version, i));
|
||||||
|
}
|
||||||
|
if let Some(max_cpus) = max_cpus {
|
||||||
|
if result.len() != max_cpus {
|
||||||
|
let mut sys_cpus = Cpus::system_default();
|
||||||
|
for i in result.len()..sys_cpus.cpus.len() {
|
||||||
|
result.push(sys_cpus.cpus.remove(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Self {
|
||||||
|
cpus: result,
|
||||||
|
smt: true,
|
||||||
|
smt_capable: can_smt,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TCpus for Cpus {
|
impl TCpus for Cpus {
|
||||||
|
|
|
@ -18,7 +18,20 @@ impl Gpu {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn system_default() -> Self {
|
/*pub fn system_default() -> Self {
|
||||||
|
Self {
|
||||||
|
slow_memory: false,
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
pub fn from_limits(_limits: limits_core::json::GenericGpuLimit) -> Self {
|
||||||
|
// TODO
|
||||||
|
Self {
|
||||||
|
slow_memory: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_json_and_limits(_other: GpuJson, _version: u64, _limits: limits_core::json::GenericGpuLimit) -> Self {
|
||||||
Self {
|
Self {
|
||||||
slow_memory: false,
|
slow_memory: false,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
mod detect;
|
||||||
pub mod driver;
|
pub mod driver;
|
||||||
mod error;
|
mod error;
|
||||||
mod general;
|
mod general;
|
||||||
|
@ -9,6 +10,7 @@ pub mod steam_deck;
|
||||||
pub mod steam_deck_adv;
|
pub mod steam_deck_adv;
|
||||||
pub mod unknown;
|
pub mod unknown;
|
||||||
|
|
||||||
|
pub use detect::{auto_detect0, auto_detect_provider, limits_worker::spawn as limits_worker_spawn};
|
||||||
pub use driver::Driver;
|
pub use driver::Driver;
|
||||||
pub use general::{SettingVariant, Settings, General};
|
pub use general::{SettingVariant, Settings, General};
|
||||||
pub use min_max::MinMax;
|
pub use min_max::MinMax;
|
||||||
|
|
Loading…
Reference in a new issue