diff --git a/backend/Cargo.lock b/backend/Cargo.lock index bea6ffb..408422c 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -820,7 +820,6 @@ name = "limits_core" version = "3.0.0" dependencies = [ "serde", - "serde_json", ] [[package]] @@ -1069,6 +1068,7 @@ dependencies = [ "log", "regex", "ron", + "sd_led", "serde", "serde_json", "simplelog", @@ -1216,6 +1216,13 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" +[[package]] +name = "sd_led" +version = "0.1.0" +dependencies = [ + "log", +] + [[package]] name = "serde" version = "1.0.183" diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 7fd5273..7b00fd3 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -30,6 +30,7 @@ simplelog = "0.12" limits_core = { version = "3", path = "./limits_core" } regex = "1" libryzenadj = { version = "0.12" } +sd_led = { version = "*", path = "./sd_led" } # ureq's tls feature does not like musl targets ureq = { version = "2", features = ["json", "gzip", "brotli", "charset"], default-features = false, optional = true } @@ -39,6 +40,7 @@ decky = ["usdpl-back/decky"] crankshaft = ["usdpl-back/crankshaft"] encrypt = ["usdpl-back/encrypt"] online = ["ureq"] +experimental = [] dev_stuff = [] [profile.release] diff --git a/backend/limits_core/Cargo.lock b/backend/limits_core/Cargo.lock index 1fa968e..169eb4d 100644 --- a/backend/limits_core/Cargo.lock +++ b/backend/limits_core/Cargo.lock @@ -2,18 +2,11 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "itoa" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" - [[package]] name = "limits_core" version = "3.0.0" dependencies = [ "serde", - "serde_json", ] [[package]] @@ -34,12 +27,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "ryu" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" - [[package]] name = "serde" version = "1.0.166" @@ -60,17 +47,6 @@ dependencies = [ "syn", ] -[[package]] -name = "serde_json" -version = "1.0.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" -dependencies = [ - "itoa", - "ryu", - "serde", -] - [[package]] name = "syn" version = "2.0.23" diff --git a/backend/limits_core/Cargo.toml b/backend/limits_core/Cargo.toml index 8f6db2c..bc36c76 100644 --- a/backend/limits_core/Cargo.toml +++ b/backend/limits_core/Cargo.toml @@ -7,4 +7,3 @@ edition = "2021" [dependencies] serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" diff --git a/backend/limits_srv/Cargo.lock b/backend/limits_srv/Cargo.lock index 9c3cf2d..ca8a790 100644 --- a/backend/limits_srv/Cargo.lock +++ b/backend/limits_srv/Cargo.lock @@ -436,7 +436,6 @@ name = "limits_core" version = "3.0.0" dependencies = [ "serde", - "serde_json", ] [[package]] diff --git a/backend/sd_led/Cargo.lock b/backend/sd_led/Cargo.lock new file mode 100644 index 0000000..0a12fba --- /dev/null +++ b/backend/sd_led/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + +[[package]] +name = "sd_led" +version = "0.1.0" +dependencies = [ + "log", +] diff --git a/backend/sd_led/Cargo.toml b/backend/sd_led/Cargo.toml new file mode 100644 index 0000000..0ee424a --- /dev/null +++ b/backend/sd_led/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "sd_led" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# logging +log = "0.4" diff --git a/backend/sd_led/src/lib.rs b/backend/sd_led/src/lib.rs new file mode 100644 index 0000000..aae4209 --- /dev/null +++ b/backend/sd_led/src/lib.rs @@ -0,0 +1,193 @@ +//! Rough Rust port of some BatCtrl functionality +//! Original: /usr/share/jupiter_controller_fw_updater/RA_bootloader_updater/linux_host_tools/BatCtrl +//! I do not have access to the source code, so this is my own interpretation of what it does. +//! +//! But also Quanta is based in a place with some questionable copyright practices, so... +pub mod raw_io; + +use std::io::Error; + +pub fn set_led(red_unused: bool, green_aka_white: bool, blue_unused: bool) -> Result { + let payload: u8 = 0x80 + | (red_unused as u8 & 1) + | ((green_aka_white as u8 & 1) << 1) + | ((blue_unused as u8 & 1) << 2); + //log::info!("Payload: {:b}", payload); + raw_io::write2(Setting::LEDStatus as _, payload) +} + +pub fn set(setting: Setting, mode: u8) -> Result { + raw_io::write2(setting as u8, mode) +} + +#[derive(Copy, Clone)] +#[repr(u8)] +pub enum Setting { + CycleCount = 0x32, + ControlBoard = 0x6C, + Charge = 0xA6, + ChargeMode = 0x76, + LEDStatus = 199, + LEDBreathing = 0x63, + FanSpeed = 0x2c, // lower 3 bits seem to not do everything, every other bit increases speed -- 5 total steps, 0xf4 seems to do something similar too + // 0x40 write 0x08 makes LED red + green turn on + // 0x58 write 0x80 shuts off battery power (bms?) + // 0x63 makes blue (0x02) or white (0x01) LED breathing effect + // 0x7a write 0x01, 0x02, or 0x03 turns off display +} + +#[derive(Copy, Clone, Debug)] +#[repr(u8)] +pub enum ControlBoard { + Enable = 0xAA, + Disable = 0xAB, +} + +#[derive(Copy, Clone, Debug)] +#[repr(u8)] +pub enum ChargeMode { + Normal = 0, + Discharge = 0x42, + Idle = 0x45, +} + +#[derive(Copy, Clone)] +#[repr(u8)] +pub enum Charge { + Enable = 0, + Disable = 4, +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + #[allow(dead_code)] + fn led_all_experiment_test() -> Result<(), Error> { + let original = raw_io::write_read(Setting::LEDStatus as _)?; + let sleep_dur = std::time::Duration::from_millis(1000); + for b in 0..0x7F { + let actual = 0x80 | b; + raw_io::write2(Setting::LEDStatus as _, actual)?; + println!("Wrote {actual:#b} to LED byte"); + std::thread::sleep(sleep_dur); + } + raw_io::write2(Setting::LEDStatus as _, original)?; + Ok(()) + } + + #[test] + #[allow(dead_code)] + fn led_singles_experiment_test() -> Result<(), Error> { + let original = raw_io::write_read(Setting::LEDStatus as _)?; + let sleep_dur = std::time::Duration::from_millis(1000); + let mut value = 1; + for _ in 0..std::mem::size_of::()*8 { + let actual = 0x80 | value; + raw_io::write2(Setting::LEDStatus as _, actual)?; + println!("Wrote {actual:#b} to LED byte"); + value = value << 1; + std::thread::sleep(sleep_dur); + } + raw_io::write2(Setting::LEDStatus as _, original)?; + Ok(()) + } + + #[test] + #[allow(dead_code)] + fn led_specify_experiment_test() -> Result<(), Error> { + let mut buffer = String::new(); + println!("LED number(s) to display?"); + std::io::stdin().read_line(&mut buffer)?; + + let mut resultant = 0; + let original = raw_io::write_read(Setting::LEDStatus as _)?; + for word in buffer.split(' ') { + let trimmed_word = word.trim(); + if !trimmed_word.is_empty() { + let value: u8 = trimmed_word.parse().expect("Invalid u8 number"); + let actual = 0x80 | value; + raw_io::wait_ready_for_write()?; + raw_io::write2(Setting::LEDStatus as _, actual)?; + println!("Wrote {actual:#b} to LED byte"); + resultant |= actual; + } + } + println!("Effectively wrote {resultant:#b} to LED byte"); + + println!("Press enter to return to normal"); + std::io::stdin().read_line(&mut buffer)?; + raw_io::write2(Setting::LEDStatus as _, original)?; + Ok(()) + } + + #[test] + #[allow(dead_code)] + fn breath_specify_experiment_test() -> Result<(), Error> { + let mut buffer = String::new(); + println!("LED number(s) to display?"); + std::io::stdin().read_line(&mut buffer)?; + + for word in buffer.split(' ') { + let trimmed_word = word.trim(); + if !trimmed_word.is_empty() { + let value: u8 = trimmed_word.parse().expect("Invalid u8 number"); + let actual = 0x20 | value; + raw_io::wait_ready_for_write()?; + raw_io::write2(0x63, actual)?; + println!("Wrote {actual:#b} to LED breathing byte"); + } + } + + println!("Press enter to return to normal"); + std::io::stdin().read_line(&mut buffer)?; + raw_io::write2(0x63, 0)?; + Ok(()) + } + + #[test] + #[allow(dead_code)] + fn unmapped_ports_experiment_test() -> Result<(), Error> { + let sleep_dur = std::time::Duration::from_millis(10000); + let value = 0xaa; + for addr in 0x63..0x64 { + //raw_io::wait_ready_for_read()?; + //let read = raw_io::write_read(addr)?; + raw_io::wait_ready_for_write()?; + raw_io::write2(addr, value)?; + println!("wrote {value:#b} for {addr:#x} port"); + std::thread::sleep(sleep_dur); + } + //raw_io::write2(Setting::LEDStatus as _, 0)?; + Ok(()) + } + + #[test] + #[allow(dead_code)] + fn write_specify_experiment_test() -> Result<(), Error> { + let mut buffer = String::new(); + println!("Register?"); + std::io::stdin().read_line(&mut buffer)?; + let register: u8 = buffer.trim().parse().expect("Invalid u8 number"); + buffer.clear(); + + println!("Value(s)?"); + std::io::stdin().read_line(&mut buffer)?; + + for word in buffer.split(' ') { + let trimmed_word = word.trim(); + if !trimmed_word.is_empty() { + let value: u8 = trimmed_word.parse().expect("Invalid u8 number"); + raw_io::wait_ready_for_write()?; + raw_io::write2(register, value)?; + println!("Wrote {value:#09b} to {register:#02x} register"); + } + } + + println!("Press enter to clear register"); + std::io::stdin().read_line(&mut buffer)?; + raw_io::write2(register, 0)?; + Ok(()) + } +} diff --git a/backend/sd_led/src/raw_io.rs b/backend/sd_led/src/raw_io.rs new file mode 100644 index 0000000..07d6568 --- /dev/null +++ b/backend/sd_led/src/raw_io.rs @@ -0,0 +1,51 @@ +use std::fs::OpenOptions; +use std::io::{Error, Read, Seek, SeekFrom, Write}; + +#[inline] +pub fn write2(p0: u8, p1: u8) -> Result { + write_to(0x6c, 0x81)?; + wait_ready_for_write()?; + let count0 = write_to(0x68, p0)?; + wait_ready_for_write()?; + let count1 = write_to(0x68, p1)?; + Ok(count0 + count1) +} + +#[inline] +pub fn write_read(p0: u8) -> Result { + write_to(0x6c, 0x81)?; + wait_ready_for_write()?; + write_to(0x68, p0)?; + wait_ready_for_read()?; + read_from(0x68) +} + +pub fn write_to(location: u64, value: u8) -> Result { + let mut file = OpenOptions::new().write(true).open("/dev/port")?; + file.seek(SeekFrom::Start(location))?; + file.write(&[value]) +} + +pub fn read_from(location: u64) -> Result { + let mut file = OpenOptions::new().read(true).open("/dev/port")?; + file.seek(SeekFrom::Start(location))?; + let mut buffer = [0]; + file.read(&mut buffer)?; + Ok(buffer[0]) +} + +pub fn wait_ready_for_write() -> Result<(), Error> { + let mut count = 0; + while count < 0x1ffff && (read_from(0x6c)? & 2) != 0 { + count += 1; + } + Ok(()) +} + +pub fn wait_ready_for_read() -> Result<(), Error> { + let mut count = 0; + while count < 0x1ffff && (read_from(0x6c)? & 1) == 0 { + count += 1; + } + Ok(()) +} diff --git a/backend/src/persist/gpu.rs b/backend/src/persist/gpu.rs index 7755847..a91f9de 100644 --- a/backend/src/persist/gpu.rs +++ b/backend/src/persist/gpu.rs @@ -8,6 +8,8 @@ use serde::{Deserialize, Serialize}; pub struct GpuJson { pub fast_ppt: Option, pub slow_ppt: Option, + pub tdp: Option, + pub tdp_boost: Option, pub clock_limits: Option>, pub slow_memory: bool, #[serde(skip_serializing_if = "Option::is_none")] @@ -19,6 +21,8 @@ impl Default for GpuJson { Self { fast_ppt: None, slow_ppt: None, + tdp: None, + tdp_boost: None, clock_limits: None, slow_memory: false, root: None, diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs index e538147..27c4322 100644 --- a/backend/src/settings/generic/gpu.rs +++ b/backend/src/settings/generic/gpu.rs @@ -14,6 +14,8 @@ pub struct Gpu { pub slow_memory: bool, pub fast_ppt: Option, pub slow_ppt: Option, + pub tdp: Option, + pub tdp_boost: Option, pub clock_limits: Option>, pub limits: GenericGpuLimit, sysfs: BasicEntityPath, @@ -70,6 +72,16 @@ impl ProviderBuilder for Gpu { } else { None }, + tdp: if limits.tdp.is_some() { + persistent.tdp + } else { + None + }, + tdp_boost: if limits.tdp_boost.is_some() { + persistent.tdp_boost + } else { + None + }, clock_limits: clock_lims, limits, sysfs: Self::find_card_sysfs(persistent.root) @@ -81,6 +93,8 @@ impl ProviderBuilder for Gpu { slow_memory: false, fast_ppt: None, slow_ppt: None, + tdp: None, + tdp_boost: None, clock_limits: None, limits, sysfs: Self::find_card_sysfs(None::<&'static str>), @@ -94,6 +108,8 @@ impl Into for Gpu { GpuJson { fast_ppt: self.fast_ppt, slow_ppt: self.slow_ppt, + tdp: self.tdp, + tdp_boost: self.tdp_boost, clock_limits: self.clock_limits.map(|x| x.into()), slow_memory: false, root: self.sysfs.root().and_then(|p| p.as_ref().to_str().map(|s| s.to_owned())) diff --git a/backend/src/settings/generic_amd/gpu.rs b/backend/src/settings/generic_amd/gpu.rs index 6e8f833..baf1508 100644 --- a/backend/src/settings/generic_amd/gpu.rs +++ b/backend/src/settings/generic_amd/gpu.rs @@ -17,6 +17,7 @@ fn msg_or_err(output: &mut String, m fn log_capabilities(ryzenadj: &RyzenAdj) { log::info!("RyzenAdj v{}.{}.{}", libryzenadj::libryzenadj_sys::RYZENADJ_REVISION_VER, libryzenadj::libryzenadj_sys::RYZENADJ_MAJOR_VER, libryzenadj::libryzenadj_sys::RYZENADJ_MINIOR_VER); + #[cfg(feature = "experimental")] if let Some(x) = ryzenadj.get_init_table_err() { log::warn!("RyzenAdj table init error: {}", x); } diff --git a/backend/src/settings/steam_deck/battery.rs b/backend/src/settings/steam_deck/battery.rs index 87f2d87..db152be 100644 --- a/backend/src/settings/steam_deck/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -6,7 +6,7 @@ use sysfuss::capability::attributes; use limits_core::json_v2::GenericBatteryLimit; -use super::util::ChargeMode; +use sd_led::ChargeMode; use crate::api::RangeLimit; use crate::persist::{BatteryEventJson, BatteryJson}; use crate::settings::{TBattery, ProviderBuilder}; @@ -131,7 +131,7 @@ impl EventInstruction { fn set_charge_mode(&self) -> Result<(), SettingError> { if let Some(charge_mode) = self.charge_mode { - super::util::set(super::util::Setting::ChargeMode, charge_mode as _) + sd_led::set(sd_led::Setting::ChargeMode, charge_mode as _) .map_err(|e| SettingError { msg: format!("Failed to set charge mode: {}", e), setting: crate::settings::SettingVariant::Battery, @@ -329,7 +329,7 @@ impl Battery { fn set_charge_mode(&mut self) -> Result<(), SettingError> { if let Some(charge_mode) = self.charge_mode { self.state.charge_mode_set = true; - super::util::set(super::util::Setting::ChargeMode, charge_mode as _) + sd_led::set(sd_led::Setting::ChargeMode, charge_mode as _) .map_err(|e| SettingError { msg: format!("Failed to set charge mode: {}", e), setting: crate::settings::SettingVariant::Battery, @@ -337,7 +337,7 @@ impl Battery { .map(|_| ()) } else if self.state.charge_mode_set { self.state.charge_mode_set = false; - super::util::set(super::util::Setting::ChargeMode, ChargeMode::Normal as _) + sd_led::set(sd_led::Setting::ChargeMode, ChargeMode::Normal as _) .map_err(|e| SettingError { msg: format!("Failed to set charge mode: {}", e), setting: crate::settings::SettingVariant::Battery, diff --git a/backend/src/settings/steam_deck/gpu.rs b/backend/src/settings/steam_deck/gpu.rs index 96316f0..7b06454 100644 --- a/backend/src/settings/steam_deck/gpu.rs +++ b/backend/src/settings/steam_deck/gpu.rs @@ -303,6 +303,8 @@ impl Into for Gpu { GpuJson { fast_ppt: self.fast_ppt, slow_ppt: self.slow_ppt, + tdp: None, + tdp_boost: None, clock_limits: self.clock_limits.map(|x| x.into()), slow_memory: self.slow_memory, root: self.sysfs_card.root().or(self.sysfs_hwmon.root()).and_then(|p| p.as_ref().to_str().map(|r| r.to_owned())) diff --git a/backend/src/settings/steam_deck/util.rs b/backend/src/settings/steam_deck/util.rs index 029e2f3..4362bb2 100644 --- a/backend/src/settings/steam_deck/util.rs +++ b/backend/src/settings/steam_deck/util.rs @@ -1,13 +1,5 @@ -//! Rough Rust port of some BatCtrl functionality -//! Original: /usr/share/jupiter_controller_fw_updater/RA_bootloader_updater/linux_host_tools/BatCtrl -//! I do not have access to the source code, so this is my own interpretation of what it does. -//! -//! But also Quanta is based in a place with some questionable copyright practices, so... #![allow(dead_code)] -use std::fs::OpenOptions; -use std::io::{Error, Read, Seek, SeekFrom, Write}; - 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"; @@ -25,63 +17,6 @@ pub fn card_also_has(card: &dyn sysfuss::SysEntity, extensions: &'static [&'stat .all(|ext| card.as_ref().join(ext).exists()) } -#[inline] -fn write2(p0: u8, p1: u8) -> Result { - write_to(0x6c, 0x81)?; - wait_ready_for_write()?; - let count0 = write_to(0x68, p0)?; - wait_ready_for_write()?; - let count1 = write_to(0x68, p1)?; - Ok(count0 + count1) -} - -fn write_read(p0: u8) -> Result { - write_to(0x6c, 0x81)?; - wait_ready_for_write()?; - write_to(0x68, p0)?; - wait_ready_for_read()?; - read_from(0x68) -} - -fn write_to(location: u64, value: u8) -> Result { - let mut file = OpenOptions::new().write(true).open("/dev/port")?; - file.seek(SeekFrom::Start(location))?; - file.write(&[value]) -} - -fn read_from(location: u64) -> Result { - let mut file = OpenOptions::new().read(true).open("/dev/port")?; - file.seek(SeekFrom::Start(location))?; - let mut buffer = [0]; - file.read(&mut buffer)?; - Ok(buffer[0]) -} - -fn wait_ready_for_write() -> Result<(), Error> { - let mut count = 0; - while count < 0x1ffff && (read_from(0x6c)? & 2) != 0 { - count += 1; - } - Ok(()) -} - -fn wait_ready_for_read() -> Result<(), Error> { - let mut count = 0; - while count < 0x1ffff && (read_from(0x6c)? & 1) == 0 { - count += 1; - } - Ok(()) -} - -pub fn set_led(red_unused: bool, green_aka_white: bool, blue_unused: bool) -> Result { - let payload: u8 = 0x80 - | (red_unused as u8 & 1) - | ((green_aka_white as u8 & 1) << 1) - | ((blue_unused as u8 & 1) << 2); - //log::info!("Payload: {:b}", payload); - write2(Setting::LEDStatus as _, payload) -} - const THINGS: &[u8] = &[ 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, @@ -92,55 +27,20 @@ const THINGS: &[u8] = &[ const TIME_UNIT: std::time::Duration = std::time::Duration::from_millis(200); pub fn flash_led() { - let old_led_state = write_read(Setting::LEDStatus as _) + let led_status = sd_led::Setting::LEDStatus; + let old_led_state = sd_led::raw_io::write_read(led_status as _) .map_err(|e| log::error!("Failed to read LED status: {}", e)); for &code in THINGS { let on = code != 0; - if let Err(e) = set_led(on, on, false) { + if let Err(e) = sd_led::set_led(on, on, false) { log::error!("Thing err: {}", e); } std::thread::sleep(TIME_UNIT); } if let Ok(old_led_state) = old_led_state { log::debug!("Restoring LED state to {:#02b}", old_led_state); - write2(Setting::LEDStatus as _, old_led_state) + sd_led::raw_io::write2(led_status as _, old_led_state) .map_err(|e| log::error!("Failed to restore LED status: {}", e)) .unwrap(); } } - -pub fn set(setting: Setting, mode: u8) -> Result { - write2(setting as u8, mode) -} - -#[derive(Copy, Clone)] -#[repr(u8)] -pub enum Setting { - CycleCount = 0x32, - ControlBoard = 0x6C, - Charge = 0xA6, - ChargeMode = 0x76, - LEDStatus = 199, -} - -#[derive(Copy, Clone, Debug)] -#[repr(u8)] -pub enum ControlBoard { - Enable = 0xAA, - Disable = 0xAB, -} - -#[derive(Copy, Clone, Debug)] -#[repr(u8)] -pub enum ChargeMode { - Normal = 0, - Discharge = 0x42, - Idle = 0x45, -} - -#[derive(Copy, Clone)] -#[repr(u8)] -pub enum Charge { - Enable = 0, - Disable = 4, -} diff --git a/backend/src/settings/unknown/gpu.rs b/backend/src/settings/unknown/gpu.rs index 4e911d4..f7b5b36 100644 --- a/backend/src/settings/unknown/gpu.rs +++ b/backend/src/settings/unknown/gpu.rs @@ -34,6 +34,8 @@ impl Into for Gpu { GpuJson { fast_ppt: None, slow_ppt: None, + tdp: None, + tdp_boost: None, clock_limits: None, slow_memory: false, root: None, diff --git a/src/index.tsx b/src/index.tsx index 2412a10..1ba2b15 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -163,12 +163,20 @@ const reload = function() { backend.resolve(backend.getMessages(null), (messages: backend.Message[]) => { set_value(MESSAGE_LIST, messages) }); }; -// init USDPL WASM and connection to back-end -(async function(){ - await backend.initBackend(); - usdplReady = true; - reload(); // technically this is only a load +const clearHooks = function() { + clearInterval(periodicHook!); + periodicHook = null; + lifetimeHook?.unregister(); + startHook?.unregister(); + endHook?.unregister(); + backend.log(backend.LogLevel.Debug, "Unregistered PowerTools callbacks, so long and thanks for all the fish."); +}; + +const registerCallbacks = function(autoclear: boolean) { + if (autoclear) { + clearHooks(); + } // register Steam callbacks //@ts-ignore lifetimeHook = SteamClient.GameSessions.RegisterForAppLifetimeNotifications((update) => { @@ -203,6 +211,15 @@ const reload = function() { }); backend.log(backend.LogLevel.Debug, "Registered PowerTools callbacks, hello!"); +}; + +// init USDPL WASM and connection to back-end +(async function(){ + await backend.initBackend(); + usdplReady = true; + reload(); // technically this is only a load + + registerCallbacks(true); })(); const periodicals = function() { @@ -334,19 +351,15 @@ export default definePlugin((serverApi: ServerAPI) => { if (now.getDate() == 1 && now.getMonth() == 3) { ico = ; } + registerCallbacks(false); return { title:
PowerTools
, content: , icon: ico, onDismount() { backend.log(backend.LogLevel.Debug, "PowerTools shutting down"); - clearInterval(periodicHook!); - periodicHook = null; - lifetimeHook?.unregister(); - startHook?.unregister(); - endHook?.unregister(); + clearHooks(); //serverApi.routerHook.removeRoute("/decky-plugin-test"); - backend.log(backend.LogLevel.Debug, "Unregistered PowerTools callbacks, so long and thanks for all the fish."); }, }; });