diff --git a/README.md b/README.md index a1398a3..f4d47b9 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # PowerTools - + [![Decky store](https://img.shields.io/badge/dynamic/json?color=blue&label=release&query=%24%5B%3F%28%40.name%3D%3D%27PowerTools%27%29%5D.versions%5B0%5D.name&url=https%3A%2F%2Fplugins.deckbrew.xyz%2Fplugins&style=flat-square)](https://plugins.deckbrew.xyz/) [![Custom store](https://img.shields.io/badge/dynamic/json?color=blue&label=preview&query=%24%5B%3F%28%40.name%3D%3D%27PowerTools%27%29%5D.versions%5B0%5D.name&url=https%3A%2F%2Fnot-decky-alpha.ngni.us%2Fplugins&style=flat-square)](https://github.com/NGnius/PowerTools/wiki) +[![GitHub package.json version](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fgit.ngni.us%2FNG-SD-Plugins%2FPowerTools%2Fraw%2Fbranch%2Fmain%2Fpackage.json&query=%24.version&style=flat-square&label=local&cacheSeconds=600)](https://git.ngni.us/NG-SD-Plugins/PowerTools/src/branch/main/package.json) [![Liberapay](https://img.shields.io/liberapay/patrons/NGnius?style=flat-square)](https://liberapay.com/NGnius) -[![GitHub](https://img.shields.io/github/license/NGnius/PowerTools?style=flat-square)](https://github.com/NGnius/PowerTools/blob/main/LICENSE) -[![GitHub package.json version](https://img.shields.io/github/package-json/v/NGnius/PowerTools?style=flat-square)](https://github.com/NGnius/PowerTools/blob/main/package.json) -[![GitHub package.json dependency version (prod)](https://img.shields.io/github/package-json/dependency-version/NGnius/PowerTools/decky-frontend-lib?style=flat-square)](https://github.com/NGnius/PowerTools/blob/main/pnpm-lock.yaml) +[![GitHub](https://img.shields.io/badge/GPL--3.0-orange?style=flat-square&label=license&cacheSeconds=600)](https://github.com/NGnius/PowerTools/blob/main/LICENSE) +[![GitHub package.json dependency version (local)](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fgit.ngni.us%2FNG-SD-Plugins%2FPowerTools%2Fraw%2Fbranch%2Fmain%2Fpackage.json&query=%24..%5B'decky-frontend-lib'%5D&style=flat-square&label=decky-frontend-lib&cacheSeconds=600)](https://github.com/NGnius/PowerTools/blob/main/pnpm-lock.yaml) ![plugin_demo](./assets/ui.png) @@ -24,17 +24,19 @@ You will need that installed for this plugin to work. - Display supplementary battery info - Keep settings between restarts (stored in `~/.config/powertools/.json`) +This plugin is tested on Steam Deck, but is designed to work on other Linux devices as well. Unfortunately I am currently unable to test on other devices. + ## Install -Please use Decky's [built-in store](https://beta.deckbrew.xyz/) to install official releases. -If you're an advanced user, and/or would like to use an in-development version, feel free to build PowerTools yourself. +Please use Decky's [built-in store](https://plugins.deckbrew.xyz/) to install official releases. +If you want to test unstable versions, use [my custom store](https://not-decky-alpha.ngni.us/plugins). If you would like to use an in-development version, feel free to build PowerTools yourself. ## Build -0. Requirements: a functioning Rust toolchain for x86_64-unknown-linux-musl, npm, and some tech literacy +0. Requirements: a functioning Rust toolchain for x86_64-unknown-linux-gnu (or -musl), pnpm, and some tech literacy 1. In a terminal, navigate to the backend directory of this project and run `./build.sh` -2. In the root of this project, run `npm run build` -3. Transfer the project (especially dist/ and bin/) to a folder in your Steam Deck's homebrew plugins directory +2. In the root of this project, run `pnpm run build` +3. Transfer the project (especially dist/ and bin/) to a folder in your Steam Deck's `~/homebrew/plugins` directory ## License diff --git a/assets/icon.svg b/assets/icon.svg index 93a7902..6758ab3 100644 --- a/assets/icon.svg +++ b/assets/icon.svg @@ -7,9 +7,9 @@ viewBox="0 0 483.77954 483.77954" version="1.1" id="svg5" - inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)" + inkscape:version="1.2.2 (b0a8486541, 2022-12-01)" sodipodi:docname="icon.svg" - inkscape:export-filename="/home/ngnius/Documents/git-repos/PowerTools/extras/icon.png" + inkscape:export-filename="logo.png" inkscape:export-xdpi="203.2" inkscape:export-ydpi="203.2" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" @@ -30,16 +30,18 @@ width="241.88977px" inkscape:snap-object-midpoints="false" inkscape:zoom="1.4142136" - inkscape:cx="250.66935" - inkscape:cy="188.0904" - inkscape:window-width="1280" - inkscape:window-height="1007" - inkscape:window-x="1280" + inkscape:cx="199.05056" + inkscape:cy="246.07316" + inkscape:window-width="2560" + inkscape:window-height="998" + inkscape:window-x="0" inkscape:window-y="0" - inkscape:window-maximized="0" + inkscape:window-maximized="1" inkscape:current-layer="layer1" inkscape:snap-intersection-paths="true" - inkscape:snap-midpoints="true" /> + inkscape:snap-midpoints="true" + inkscape:showpageshadow="2" + inkscape:deskcolor="#d1d1d1" /> + + cx="59.355446" + cy="88.752792" + r="25" /> + - + y="339" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/logo.png b/assets/logo.png index 94c719c..25a89b4 100644 Binary files a/assets/logo.png and b/assets/logo.png differ diff --git a/assets/sticker.svg b/assets/sticker.svg new file mode 100644 index 0000000..b9cf569 --- /dev/null +++ b/assets/sticker.svg @@ -0,0 +1,384 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Power + Tools + + diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 9036a82..fe94411 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -46,9 +55,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" dependencies = [ "memchr", ] @@ -68,6 +77,12 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -85,18 +100,18 @@ checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.29", ] [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.29", ] [[package]] @@ -105,6 +120,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.1" @@ -113,9 +143,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "414dcefbc63d77c526a76b3afcf6fbb9b5e2791c19c3aa2297733208750c6e53" [[package]] name = "bindgen" @@ -166,9 +196,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytecount" @@ -190,9 +220,12 @@ checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cexpr" @@ -211,13 +244,13 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "time 0.1.45", "wasm-bindgen", @@ -253,27 +286,17 @@ dependencies = [ "cc", ] -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -307,54 +330,16 @@ dependencies = [ ] [[package]] -name = "cxx" -version = "1.0.94" +name = "deranged" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.13", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.13", -] +checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", @@ -362,9 +347,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "encoding" @@ -432,13 +417,19 @@ checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.2.8" @@ -462,9 +453,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.25" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "c6c98ee8095e9d1dcbf2fcc6d95acccb90d1c81db1e44725c6a984b1dbdfb010" dependencies = [ "crc32fast", "miniz_oxide", @@ -478,9 +469,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -539,9 +530,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -558,6 +549,12 @@ dependencies = [ "encoding", ] +[[package]] +name = "gimli" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" + [[package]] name = "glob" version = "0.3.1" @@ -566,9 +563,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "h2" -version = "0.3.16" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ "bytes", "fnv", @@ -576,7 +573,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 1.9.3", "slab", "tokio", "tokio-util", @@ -589,6 +586,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" + [[package]] name = "headers" version = "0.3.8" @@ -616,12 +619,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" [[package]] name = "hex" @@ -659,15 +659,15 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.25" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -680,7 +680,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -689,9 +689,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.54" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c17cc76786e99f8d2f055c11159e7f0091c42474dcc3189fbab96072e873e6d" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -703,19 +703,18 @@ dependencies = [ [[package]] name = "iana-time-zone-haiku" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "cxx", - "cxx-build", + "cc", ] [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -728,20 +727,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +dependencies = [ + "equivalent", + "hashbrown 0.14.0", ] [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -760,9 +769,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.140" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libloading" @@ -799,35 +808,23 @@ dependencies = [ [[package]] name = "limits_core" -version = "1.0.0" +version = "2.0.1" dependencies = [ "serde", "serde_json", ] -[[package]] -name = "link-cplusplus" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" -dependencies = [ - "cc", -] - [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "76fc44e2588d5b436dbc3c6cf62aef290f90dab6235744a93dfe1cc18f451e2c" [[package]] name = "mime" @@ -853,37 +850,40 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys", ] [[package]] -name = "multiparty" -version = "0.1.0" +name = "multer" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed1ec6589a6d4a1e0b33b4c0a3f6ee96dfba88ebdb3da51403fd7cf0a24a4b04" +checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" dependencies = [ "bytes", - "futures-core", + "encoding_rs", + "futures-util", + "http", "httparse", + "log", "memchr", - "pin-project-lite", - "try-lock", + "mime", + "spin", + "version_check", ] [[package]] @@ -898,39 +898,29 @@ dependencies = [ [[package]] name = "nom_locate" -version = "4.1.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e299bf5ea7b212e811e71174c5d1a5d065c4c0ad0c8691ecb1f97e3e66025e" +checksum = "1e3c83c053b0713da60c5b8de47fe8e494fe3ece5267b2f23090a07a053ba8f3" dependencies = [ "bytecount", "memchr", "nom", ] -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", @@ -973,10 +963,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b2b2cbbfd8defa51ff24450a61d73b3ff3e158484ddd274a883e886e6fbaa78" [[package]] -name = "once_cell" -version = "1.17.1" +name = "object" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "opaque-debug" @@ -1003,35 +1002,35 @@ checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.29", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -1053,7 +1052,7 @@ dependencies = [ [[package]] name = "powertools" -version = "1.3.1" +version = "1.4.0" dependencies = [ "async-trait", "libryzenadj", @@ -1063,6 +1062,7 @@ dependencies = [ "serde", "serde_json", "simplelog", + "sysfuss", "tokio", "ureq", "usdpl-back", @@ -1086,18 +1086,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.55" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d0dd4be24fcdcfeaa12a432d588dc59bbad6cad3510c67e74a2b6b2fc950564" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] @@ -1134,9 +1134,21 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.3" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" dependencies = [ "aho-corasick", "memchr", @@ -1145,9 +1157,15 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.29" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc-hash" @@ -1157,18 +1175,18 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.0", + "base64 0.21.3", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "scoped-tls" @@ -1176,37 +1194,31 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" -[[package]] -name = "scratch" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" - [[package]] name = "serde" -version = "1.0.159" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.159" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.29", ] [[package]] name = "serde_json" -version = "1.0.95" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" dependencies = [ "itoa", "ryu", @@ -1250,14 +1262,14 @@ checksum = "acee08041c5de3d5048c8b3f6f13fafb3026b24ba43c6a695a0c76179b844369" dependencies = [ "log", "termcolor", - "time 0.3.20", + "time 0.3.28", ] [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] @@ -1272,6 +1284,22 @@ dependencies = [ "winapi", ] +[[package]] +name = "socket2" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2538b18701741680e0322a2302176d3253a35388e2e62f172f64f4f16605f877" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "subtle" version = "2.4.1" @@ -1291,15 +1319,19 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.13" +version = "2.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "sysfuss" +version = "0.2.0" + [[package]] name = "termcolor" version = "1.1.3" @@ -1311,22 +1343,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.13", + "syn 2.0.29", ] [[package]] @@ -1342,10 +1374,11 @@ dependencies = [ [[package]] name = "time" -version = "0.3.20" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" dependencies = [ + "deranged", "itoa", "libc", "num_threads", @@ -1356,15 +1389,15 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" [[package]] name = "time-macros" -version = "0.2.8" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" dependencies = [ "time-core", ] @@ -1386,25 +1419,25 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.27.0" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", "mio", "num_cpus", "pin-project-lite", - "socket2", + "socket2 0.5.3", "windows-sys", ] [[package]] name = "tokio-stream" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", "pin-project-lite", @@ -1425,9 +1458,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" dependencies = [ "bytes", "futures-core", @@ -1439,17 +1472,17 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" [[package]] name = "toml_edit" -version = "0.19.8" +version = "0.19.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13" +checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" dependencies = [ - "indexmap", + "indexmap 2.0.0", "toml_datetime", "winnow", ] @@ -1474,9 +1507,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", ] @@ -1514,9 +1547,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicase" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" dependencies = [ "version_check", ] @@ -1529,9 +1562,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-normalization" @@ -1542,12 +1575,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - [[package]] name = "universal-hash" version = "0.4.1" @@ -1560,11 +1587,11 @@ dependencies = [ [[package]] name = "ureq" -version = "2.6.2" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338b31dd1314f68f3aabf3ed57ab922df95ffcd902476ca7ba3c4ce7b908c46d" +checksum = "0b11c96ac7ee530603dcdf68ed1557050f374ce55a5a07193ebf8cbc9f8927e9" dependencies = [ - "base64 0.13.1", + "base64 0.21.3", "brotli-decompressor", "encoding_rs", "flate2", @@ -1577,9 +1604,9 @@ dependencies = [ [[package]] name = "url" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna", @@ -1628,19 +1655,18 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] [[package]] name = "warp" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27e1a710288f0f91a98dd8a74f05b76a10768db245ce183edf64dc1afdc3016c" +checksum = "ba431ef570df1287f7f8b07e376491ad54f84d26ac473489427231e1718e1f69" dependencies = [ "bytes", "futures-channel", @@ -1651,7 +1677,7 @@ dependencies = [ "log", "mime", "mime_guess", - "multiparty", + "multer", "percent-encoding", "pin-project", "rustls-pemfile", @@ -1681,9 +1707,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1691,24 +1717,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.29", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1716,22 +1742,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.29", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "which" @@ -1777,27 +1803,27 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.46.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ "windows-targets", ] [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -1810,51 +1836,51 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winnow" -version = "0.4.1" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28" +checksum = "7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc" dependencies = [ "memchr", ] diff --git a/backend/Cargo.toml b/backend/Cargo.toml index 07b2ca0..6c86f35 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "powertools" -version = "1.3.1" +version = "1.4.0" edition = "2021" authors = ["NGnius (Graham) "] description = "Backend (superuser) functionality for PowerTools" @@ -15,6 +15,7 @@ readme = "../README.md" usdpl-back = { version = "0.10.1", features = ["blocking"] }#, path = "../../usdpl-rs/usdpl-back"} serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +sysfuss = { version = "0.2", path = "../../sysfs-nav", features = ["derive"] } # async tokio = { version = "*", features = ["time"] } @@ -25,11 +26,11 @@ log = "0.4" simplelog = "0.12" # limits & driver functionality -limits_core = { version = "1.0.0", path = "./limits_core" } +limits_core = { version = "2", path = "./limits_core" } regex = "1" libryzenadj = { version = "0.12" } # ureq's tls feature does not like musl targets -ureq = { version = "2.5", features = ["json", "gzip", "brotli", "charset"], default-features = false, optional = true } +ureq = { version = "2", features = ["json", "gzip", "brotli", "charset"], default-features = false, optional = true } [features] default = ["online", "decky"] diff --git a/backend/build.sh b/backend/build.sh index d99c6e4..7e408f6 100755 --- a/backend/build.sh +++ b/backend/build.sh @@ -6,7 +6,7 @@ cargo build mkdir -p ../bin -#cp ./target/x86_64-unknown-linux-musl/release/powertools ../bin/backend -#cp ./target/x86_64-unknown-linux-musl/debug/powertools ../bin/backend -#cp ./target/debug/powertools ../bin/backend -cp ./target/debug/powertools ../bin/backend +#cp --preserve=mode ./target/x86_64-unknown-linux-musl/release/powertools ../bin/backend +#cp --preserve=mode ./target/x86_64-unknown-linux-musl/debug/powertools ../bin/backend +#cp --preserve=mode ./target/debug/powertools ../bin/backend +cp --preserve=mode ./target/debug/powertools ../bin/backend diff --git a/backend/limits_core/Cargo.lock b/backend/limits_core/Cargo.lock index 1fe94f4..a3d5955 100644 --- a/backend/limits_core/Cargo.lock +++ b/backend/limits_core/Cargo.lock @@ -4,13 +4,13 @@ version = 3 [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" [[package]] name = "limits_core" -version = "1.0.0" +version = "2.0.1" dependencies = [ "serde", "serde_json", @@ -18,42 +18,42 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.54" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" [[package]] name = "serde" -version = "1.0.159" +version = "1.0.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.159" +version = "1.0.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" dependencies = [ "proc-macro2", "quote", @@ -62,9 +62,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.95" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ "itoa", "ryu", @@ -73,9 +73,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.12" +version = "2.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927" +checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" dependencies = [ "proc-macro2", "quote", @@ -84,6 +84,6 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" diff --git a/backend/limits_core/Cargo.toml b/backend/limits_core/Cargo.toml index 2bb9e77..7d2f721 100644 --- a/backend/limits_core/Cargo.toml +++ b/backend/limits_core/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "limits_core" -version = "1.0.0" +version = "2.0.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/backend/limits_core/src/json/base.rs b/backend/limits_core/src/json/base.rs index d6e013c..cbb77fc 100644 --- a/backend/limits_core/src/json/base.rs +++ b/backend/limits_core/src/json/base.rs @@ -57,16 +57,16 @@ impl Default for Base { }, limits: vec![ super::Limits::Cpu(super::CpuLimit::GenericAMD(super::GenericCpuLimit { - clock_min: Some(super::RangeLimit { min: 1000, max: 3700 }), - clock_max: Some(super::RangeLimit { min: 1000, max: 3700 }), + clock_min: Some(super::RangeLimit { min: Some(1000), max: Some(3700) }), + clock_max: Some(super::RangeLimit { min: Some(1000), max: Some(3700) }), clock_step: 100, })), super::Limits::Gpu(super::GpuLimit::GenericAMD(super::GenericGpuLimit { - fast_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), - slow_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), + fast_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), + slow_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), ppt_step: Some(1_000_000), - clock_min: Some(super::RangeLimit { min: 400, max: 1100 }), - clock_max: Some(super::RangeLimit { min: 400, max: 1100 }), + clock_min: Some(super::RangeLimit { min: Some(400), max: Some(1100) }), + clock_max: Some(super::RangeLimit { min: Some(400), max: Some(1100) }), clock_step: Some(100), ..Default::default() })), @@ -84,16 +84,16 @@ impl Default for Base { }, limits: vec![ super::Limits::Cpu(super::CpuLimit::GenericAMD(super::GenericCpuLimit { - clock_min: Some(super::RangeLimit { min: 1000, max: 4000 }), - clock_max: Some(super::RangeLimit { min: 1000, max: 4000 }), + clock_min: Some(super::RangeLimit { min: Some(1000), max: Some(4000) }), + clock_max: Some(super::RangeLimit { min: Some(1000), max: Some(4000) }), clock_step: 100, })), super::Limits::Gpu(super::GpuLimit::GenericAMD(super::GenericGpuLimit { - fast_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), - slow_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), + fast_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), + slow_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), ppt_step: Some(1_000_000), - clock_min: Some(super::RangeLimit { min: 400, max: 1600 }), - clock_max: Some(super::RangeLimit { min: 400, max: 1600 }), + clock_min: Some(super::RangeLimit { min: Some(400), max: Some(1600) }), + clock_max: Some(super::RangeLimit { min: Some(400), max: Some(1600) }), clock_step: Some(100), ..Default::default() })), @@ -111,16 +111,16 @@ impl Default for Base { }, limits: vec![ super::Limits::Cpu(super::CpuLimit::GenericAMD(super::GenericCpuLimit { - clock_min: Some(super::RangeLimit { min: 1000, max: 4500 }), - clock_max: Some(super::RangeLimit { min: 1000, max: 4500 }), + clock_min: Some(super::RangeLimit { min: Some(1000), max: Some(4500) }), + clock_max: Some(super::RangeLimit { min: Some(1000), max: Some(4500) }), clock_step: 100, })), super::Limits::Gpu(super::GpuLimit::GenericAMD(super::GenericGpuLimit { - fast_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), - slow_ppt: Some(super::RangeLimit { min: 1_000_000, max: 25_000_000 }), + fast_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), + slow_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(25_000_000) }), ppt_step: Some(1_000_000), - clock_min: Some(super::RangeLimit { min: 400, max: 2000 }), - clock_max: Some(super::RangeLimit { min: 400, max: 2000 }), + clock_min: Some(super::RangeLimit { min: Some(400), max: Some(2000) }), + clock_max: Some(super::RangeLimit { min: Some(400), max: Some(2000) }), clock_step: Some(100), ..Default::default() })), @@ -138,16 +138,16 @@ impl Default for Base { }, limits: vec![ super::Limits::Cpu(super::CpuLimit::Generic(super::GenericCpuLimit { - clock_min: Some(super::RangeLimit { min: 1000, max: 4700 }), - clock_max: Some(super::RangeLimit { min: 1000, max: 4700 }), + clock_min: Some(super::RangeLimit { min: Some(1000), max: Some(4700) }), + clock_max: Some(super::RangeLimit { min: Some(1000), max: Some(4700) }), clock_step: 100, })), super::Limits::Gpu(super::GpuLimit::Generic(super::GenericGpuLimit { - fast_ppt: Some(super::RangeLimit { min: 1_000_000, max: 28_000_000 }), - slow_ppt: Some(super::RangeLimit { min: 1_000_000, max: 28_000_000 }), + fast_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(28_000_000) }), + slow_ppt: Some(super::RangeLimit { min: Some(1_000_000), max: Some(28_000_000) }), ppt_step: Some(1_000_000), - clock_min: Some(super::RangeLimit { min: 400, max: 2200 }), - clock_max: Some(super::RangeLimit { min: 400, max: 2200 }), + clock_min: Some(super::RangeLimit { min: Some(400), max: Some(2200) }), + clock_max: Some(super::RangeLimit { min: Some(400), max: Some(2200) }), clock_step: Some(100), ..Default::default() })), @@ -170,7 +170,14 @@ impl Default for Base { ] } ], - messages: Vec::new(), + messages: vec![ + super::DeveloperMessage { + id: 1, + title: "Welcome".to_owned(), + body: "Thanks for installing PowerTools! For more information, please check the wiki. For bugs and requests, please create an issue on GitHub.".to_owned(), + url: Some("https://github.com/NGnius/PowerTools/wiki".to_owned()), + } + ], refresh: Some("http://limits.ngni.us:45000/powertools/v1".to_owned()) } } diff --git a/backend/limits_core/src/json/range.rs b/backend/limits_core/src/json/range.rs index 2ea3718..49135eb 100644 --- a/backend/limits_core/src/json/range.rs +++ b/backend/limits_core/src/json/range.rs @@ -3,6 +3,6 @@ use serde::{Deserialize, Serialize}; /// Base JSON limits information #[derive(Serialize, Deserialize, Debug, Clone)] pub struct RangeLimit { - pub min: T, - pub max: T, + pub min: Option, + pub max: Option, } diff --git a/backend/limits_srv/Cargo.lock b/backend/limits_srv/Cargo.lock index b0d4490..1b8b3ee 100644 --- a/backend/limits_srv/Cargo.lock +++ b/backend/limits_srv/Cargo.lock @@ -2,6 +2,27 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + [[package]] name = "android_system_properties" version = "0.1.5" @@ -17,6 +38,21 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.13.1" @@ -25,9 +61,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "bitflags" @@ -46,9 +82,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "byteorder" @@ -76,40 +112,30 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" +checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5" dependencies = [ + "android-tzdata", "iana-time-zone", "js-sys", - "num-integer", "num-traits", "time", "wasm-bindgen", "winapi", ] -[[package]] -name = "codespan-reporting" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" -dependencies = [ - "termcolor", - "unicode-width", -] - [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c" dependencies = [ "libc", ] @@ -124,60 +150,25 @@ dependencies = [ "typenum", ] -[[package]] -name = "cxx" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93" -dependencies = [ - "cc", - "cxxbridge-flags", - "cxxbridge-macro", - "link-cplusplus", -] - -[[package]] -name = "cxx-build" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b" -dependencies = [ - "cc", - "codespan-reporting", - "once_cell", - "proc-macro2", - "quote", - "scratch", - "syn 2.0.12", -] - -[[package]] -name = "cxxbridge-flags" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb" - -[[package]] -name = "cxxbridge-macro" -version = "1.0.94" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.12", -] - [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", ] +[[package]] +name = "encoding_rs" +version = "0.8.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +dependencies = [ + "cfg-if", +] + [[package]] name = "fnv" version = "1.0.7" @@ -186,9 +177,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -247,9 +238,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -257,10 +248,16 @@ dependencies = [ ] [[package]] -name = "h2" -version = "0.3.16" +name = "gimli" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + +[[package]] +name = "h2" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" dependencies = [ "bytes", "fnv", @@ -308,12 +305,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" [[package]] name = "http" @@ -351,9 +345,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.25" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -375,9 +369,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.54" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c17cc76786e99f8d2f055c11159e7f0091c42474dcc3189fbab96072e873e6d" +checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -389,19 +383,18 @@ dependencies = [ [[package]] name = "iana-time-zone-haiku" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "cxx", - "cxx-build", + "cc", ] [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -419,28 +412,28 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.140" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "limits_core" -version = "1.0.0" +version = "2.0.1" dependencies = [ "serde", "serde_json", @@ -448,7 +441,7 @@ dependencies = [ [[package]] name = "limits_srv" -version = "1.0.0" +version = "2.0.1" dependencies = [ "chrono", "limits_core", @@ -458,23 +451,11 @@ dependencies = [ "warp", ] -[[package]] -name = "link-cplusplus" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5" -dependencies = [ - "cc", -] - [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "memchr" @@ -499,39 +480,41 @@ dependencies = [ ] [[package]] -name = "mio" -version = "0.8.6" +name = "miniz_oxide" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys", ] [[package]] -name = "multiparty" -version = "0.1.0" +name = "multer" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed1ec6589a6d4a1e0b33b4c0a3f6ee96dfba88ebdb3da51403fd7cf0a24a4b04" +checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" dependencies = [ "bytes", - "futures-core", + "encoding_rs", + "futures-util", + "http", "httparse", + "log", "memchr", - "pin-project-lite", - "try-lock", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", + "mime", + "spin", + "version_check", ] [[package]] @@ -545,51 +528,60 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ "hermit-abi", "libc", ] [[package]] -name = "once_cell" -version = "1.17.1" +name = "object" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pin-project" -version = "1.0.12" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +checksum = "030ad2bc4db10a8944cb0d837f158bdfec4d4a4873ab701a95046770d11f8842" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.12" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "4c40d25201921e5ff0c862a505c6557ea88568a4e3ace775ab55e93f2f4f9d57" [[package]] name = "pin-utils" @@ -605,18 +597,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro2" -version = "1.0.54" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] @@ -652,19 +644,25 @@ dependencies = [ ] [[package]] -name = "rustls-pemfile" -version = "1.0.2" +name = "rustc-demangle" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustls-pemfile" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ - "base64 0.21.0", + "base64 0.21.2", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" [[package]] name = "scoped-tls" @@ -672,37 +670,31 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" -[[package]] -name = "scratch" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1" - [[package]] name = "serde" -version = "1.0.159" +version = "1.0.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.159" +version = "1.0.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn", ] [[package]] name = "serde_json" -version = "1.0.95" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ "itoa", "ryu", @@ -752,36 +744,22 @@ dependencies = [ ] [[package]] -name = "syn" -version = "1.0.109" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "syn" +version = "2.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "syn" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79d9531f94112cfc3e4c8f5f02cb2b58f72c97b7efd85f70203cc6d8efda5927" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "1.0.40" @@ -799,7 +777,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn", ] [[package]] @@ -830,11 +808,12 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.27.0" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", @@ -847,20 +826,20 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.0.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a573bdc87985e9d6ddeed1b3d864e8a302c847e40d647746df2f1de209d1ce" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.12", + "syn", ] [[package]] name = "tokio-stream" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", "pin-project-lite", @@ -881,9 +860,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" dependencies = [ "bytes", "futures-core", @@ -913,9 +892,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", ] @@ -968,9 +947,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" [[package]] name = "unicode-normalization" @@ -981,17 +960,11 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - [[package]] name = "url" -version = "2.3.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" dependencies = [ "form_urlencoded", "idna", @@ -1012,19 +985,18 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] [[package]] name = "warp" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27e1a710288f0f91a98dd8a74f05b76a10768db245ce183edf64dc1afdc3016c" +checksum = "ba431ef570df1287f7f8b07e376491ad54f84d26ac473489427231e1718e1f69" dependencies = [ "bytes", "futures-channel", @@ -1035,7 +1007,7 @@ dependencies = [ "log", "mime", "mime_guess", - "multiparty", + "multer", "percent-encoding", "pin-project", "rustls-pemfile", @@ -1065,9 +1037,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1075,24 +1047,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1100,22 +1072,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "winapi" @@ -1133,15 +1105,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1150,27 +1113,27 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.46.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ "windows-targets", ] [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -1183,42 +1146,42 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/backend/limits_srv/Cargo.toml b/backend/limits_srv/Cargo.toml index 67305c8..2d529a8 100644 --- a/backend/limits_srv/Cargo.toml +++ b/backend/limits_srv/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "limits_srv" -version = "1.0.0" +version = "2.0.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -limits_core = { version = "1.0.0", path = "../limits_core" } +limits_core = { version = "2.0.1", path = "../limits_core" } chrono = { version = "0.4" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" diff --git a/backend/limits_srv/pt_limits.json b/backend/limits_srv/pt_limits.json index c7797f6..2b34975 100644 --- a/backend/limits_srv/pt_limits.json +++ b/backend/limits_srv/pt_limits.json @@ -289,6 +289,13 @@ ] } ], - "messages": [], + "messages": [ + { + "id": 1, + "title": "Welcome", + "body": "Thanks for installing PowerTools! For more information, please check the wiki. For bugs and requests, please create an issue on GitHub.", + "url": "https://github.com/NGnius/PowerTools/wiki" + } + ], "refresh": "http://limits.ngni.us:45000/powertools/v1" } \ No newline at end of file diff --git a/backend/src/api/api_types.rs b/backend/src/api/api_types.rs index aa904b5..8d72107 100644 --- a/backend/src/api/api_types.rs +++ b/backend/src/api/api_types.rs @@ -1,18 +1,14 @@ use serde::{Deserialize, Serialize}; -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Clone, Debug)] pub struct RangeLimit { pub min: T, pub max: T, } -impl From> for RangeLimit { - #[inline] - fn from(other: limits_core::json::RangeLimit) -> Self { - RangeLimit { - min: other.min, - max: other.max, - } +impl RangeLimit { + pub fn new(min: T, max: T) -> Self { + Self { min, max } } } diff --git a/backend/src/api/battery.rs b/backend/src/api/battery.rs index b134ff3..2446e75 100644 --- a/backend/src/api/battery.rs +++ b/backend/src/api/battery.rs @@ -30,11 +30,6 @@ pub fn current_now(sender: Sender) -> impl AsyncCallable { } } -/// Current current (ha!) web method -/*pub fn current_now(_: super::ApiParameterType) -> super::ApiParameterType { - super::utility::map_optional_result(crate::settings::driver::read_current_now()) -}*/ - /// Charge now web method pub fn charge_now(sender: Sender) -> impl AsyncCallable { let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety @@ -110,6 +105,31 @@ pub fn charge_design(sender: Sender) -> impl AsyncCallable { } } +/// Charge wattage web method +pub fn charge_power(sender: Sender) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + let sender2 = sender.clone(); + move || { + let (tx, rx) = mpsc::channel(); + let callback = + move |val: Option| tx.send(val).expect("power_now callback send failed"); + sender2 + .lock() + .unwrap() + .send(ApiMessage::Battery(BatteryMessage::ReadChargePower( + Box::new(callback), + ))) + .expect("power_now send failed"); + rx.recv().expect("power_now callback recv failed") + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |result| super::utility::map_optional_result(Ok(result)), + } +} + /// Generate set battery charge rate web method pub fn set_charge_rate( sender: Sender, diff --git a/backend/src/api/cpu.rs b/backend/src/api/cpu.rs index c737aac..bd19eab 100644 --- a/backend/src/api/cpu.rs +++ b/backend/src/api/cpu.rs @@ -6,6 +6,7 @@ use usdpl_back::AsyncCallable; use crate::settings::{MinMax, SettingError, SettingVariant}; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; use super::handler::{ApiMessage, CpuMessage}; +use super::utility::map_optional; /// Available CPUs web method pub fn max_cpus(_: super::ApiParameterType) -> super::ApiParameterType { @@ -205,8 +206,8 @@ pub fn set_clock_limits( setter( index as usize, MinMax { - min: safe_min as u64, - max: safe_max as u64, + min: Some(safe_min as u64), + max: Some(safe_max as u64), }, ); vec![safe_min.into(), safe_max.into()] @@ -220,6 +221,7 @@ pub fn set_clock_limits( vec!["set_clock_limits missing parameter 0".into()] } } + // TODO allow param 0 and/or 1 to be Primitive::Empty } pub fn get_clock_limits( @@ -245,7 +247,7 @@ pub fn get_clock_limits( move |params_in: super::ApiParameterType| { if let Some(&Primitive::F64(index)) = params_in.get(0) { if let Some(min_max) = getter(index as usize) { - vec![min_max.min.into(), min_max.max.into()] + vec![map_optional(min_max.min), map_optional(min_max.max)] } else { vec![Primitive::Empty, Primitive::Empty] } diff --git a/backend/src/api/general.rs b/backend/src/api/general.rs index fd032d8..9cda1c2 100644 --- a/backend/src/api/general.rs +++ b/backend/src/api/general.rs @@ -321,3 +321,57 @@ pub fn force_apply( vec![true.into()] } } + +/// Generate get periodicals aggregate method +pub fn get_periodicals(sender: Sender) -> impl AsyncCallable { + let sender = Arc::new(Mutex::new(sender)); // Sender is not Sync; this is required for safety + let getter = move || { + 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_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 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()), + ] + } + }; + super::async_utils::AsyncIshGetter { + set_get: getter, + trans_getter: |result| result, + } +} + +fn build_comms<'a, T: Send + 'a>(msg: &'static str) -> (mpsc::Receiver, Box) { + let (tx, rx) = mpsc::channel(); + let callback = move |t: T| tx.send(t).expect(msg); + (rx, Box::new(callback)) +} + +fn wait_for_response(sender: &Sender, rx: mpsc::Receiver, api_msg: ApiMessage, op: &str) -> T { + sender.send(api_msg).expect(&format!("{} send failed", op)); + rx.recv().expect(&format!("{} callback recv failed", op)) +} diff --git a/backend/src/api/gpu.rs b/backend/src/api/gpu.rs index 3829d30..320a331 100644 --- a/backend/src/api/gpu.rs +++ b/backend/src/api/gpu.rs @@ -3,6 +3,7 @@ use std::sync::{Arc, Mutex}; use usdpl_back::core::serdes::Primitive; use usdpl_back::AsyncCallable; +use super::utility::map_optional; use crate::settings::MinMax; //use crate::utility::{unwrap_lock, unwrap_maybe_fatal}; use super::handler::{ApiMessage, GpuMessage}; @@ -94,8 +95,8 @@ pub fn set_clock_limits( let safe_max = if max < min { min } else { max }; let safe_min = if min > max { max } else { min }; setter(MinMax { - min: safe_min as _, - max: safe_max as _, + min: Some(safe_min as _), + max: Some(safe_max as _), }); vec![(safe_min as u64).into(), (safe_max as u64).into()] } else { @@ -105,6 +106,7 @@ pub fn set_clock_limits( vec!["set_clock_limits missing parameter 0".into()] } } + // TODO allow param 0 and/or 1 to be Primitive::Empty } pub fn get_clock_limits(sender: Sender) -> impl AsyncCallable { @@ -131,7 +133,7 @@ pub fn get_clock_limits(sender: Sender) -> impl AsyncCallable { set_get: getter, trans_getter: |clocks: Option>| { clocks - .map(|x| vec![x.min.into(), x.max.into()]) + .map(|x| vec![map_optional(x.min), map_optional(x.max)]) .unwrap_or_else(|| vec![Primitive::Empty, Primitive::Empty]) }, } diff --git a/backend/src/api/handler.rs b/backend/src/api/handler.rs index 57f57f5..60316c9 100644 --- a/backend/src/api/handler.rs +++ b/backend/src/api/handler.rs @@ -39,6 +39,7 @@ pub enum BatteryMessage { ReadChargeNow(Callback>), ReadChargeDesign(Callback>), ReadCurrentNow(Callback>), + ReadChargePower(Callback>), SetChargeLimit(Option), GetChargeLimit(Callback>), } @@ -55,6 +56,7 @@ impl BatteryMessage { Self::ReadChargeNow(cb) => cb(settings.read_charge_now()), Self::ReadChargeDesign(cb) => cb(settings.read_charge_design()), Self::ReadCurrentNow(cb) => cb(settings.read_current_now()), + Self::ReadChargePower(cb) => cb(settings.read_charge_power()), Self::SetChargeLimit(limit) => settings.charge_limit(limit), Self::GetChargeLimit(cb) => cb(settings.get_charge_limit()), } @@ -268,7 +270,9 @@ impl ApiMessageHandler { while let Ok(msg) = self.intake.try_recv() { dirty |= self.process(settings, msg); } - if dirty /*|| dirty_echo */ { + if dirty + /*|| dirty_echo */ + { //dirty_echo = dirty; // echo only once // run on_set @@ -288,6 +292,16 @@ impl ApiMessageHandler { let settings_clone = settings.json(); let save_json: SettingsJson = settings_clone.into(); unwrap_maybe_fatal(save_json.save(&save_path), "Failed to save settings"); + if let Some(event) = &settings.general.on_event().on_save { + if !event.is_empty() { + unwrap_maybe_fatal( + std::process::Command::new("/bin/bash") + .args(&["-c", event]) + .spawn(), + "Failed to start on_save event command", + ); + } + } log::debug!("Saved settings to {}", save_path.display()); if let Err(e) = crate::utility::chown_settings_dir() { log::error!("Failed to change config dir permissions: {}", e); diff --git a/backend/src/api/message.rs b/backend/src/api/message.rs new file mode 100644 index 0000000..3ac093e --- /dev/null +++ b/backend/src/api/message.rs @@ -0,0 +1,141 @@ +use std::sync::{atomic::{AtomicU64, Ordering}, Arc}; + +use serde::{Deserialize, Serialize}; + +use usdpl_back::AsyncCallable; +use usdpl_back::core::serdes::Primitive; + +use limits_core::json::DeveloperMessage; + +use crate::MESSAGE_SEEN_ID_FILE; +use crate::utility::settings_dir; + +#[derive(Serialize, Deserialize)] +pub struct ApiMessage { + /// Message identifier + pub id: Option, + /// Message title + pub title: String, + /// Message content + pub body: String, + /// Link for further information + pub url: Option, +} + +impl std::convert::From for ApiMessage { + fn from(other: DeveloperMessage) -> Self { + Self { + id: Some(other.id), + title: other.title, + body: other.body, + url: other.url, + } + } +} + +fn get_dev_messages() -> Vec { + crate::settings::get_dev_messages().drain(..).map(|msg| ApiMessage::from(msg)).collect() +} + +pub struct MessageHandler { + seen: Arc, +} + +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 */ { + u64::from_le_bytes([ + last_seen_id_bytes[0], + last_seen_id_bytes[1], + last_seen_id_bytes[2], + last_seen_id_bytes[3], + last_seen_id_bytes[4], + last_seen_id_bytes[5], + last_seen_id_bytes[6], + last_seen_id_bytes[7], + ]) + } else { + u64::MAX + } + } else { + u64::MIN + }; + Self { + seen: Arc::new(AtomicU64::new(last_seen_id)), + } + } + + pub fn to_callables(self) -> (AsyncMessageGetter, AsyncMessageDismisser) { + ( + AsyncMessageGetter { + seen: self.seen.clone(), + }, + AsyncMessageDismisser { + seen: self.seen.clone(), + } + ) + } +} + +pub struct AsyncMessageGetter { + seen: Arc, +} + +impl AsyncMessageGetter { + fn remove_before_id(id: u64, messages: impl Iterator) -> impl Iterator { + messages.skip_while(move |msg| if let Some(msg_id) = msg.id { msg_id <= id } else { true }) + } +} + +#[async_trait::async_trait] +impl AsyncCallable for AsyncMessageGetter { + async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType { + let since = if let Some(param0) = params.get(0) { + if let Primitive::Empty = param0 { + self.seen.load(Ordering::Relaxed) + } else if let Primitive::U64(since) = param0 { + *since + } else { + return vec!["get message invalid parameter 0".into()]; + } + } else { + self.seen.load(Ordering::Relaxed) + }; + let mut messages = get_dev_messages(); + Self::remove_before_id(since, messages.drain(..)) + .filter_map(|msg| serde_json::to_string(&msg).ok().map(|x| Primitive::Json(x))) + .collect() + } +} + +pub struct AsyncMessageDismisser { + seen: Arc, +} + +#[async_trait::async_trait] +impl AsyncCallable for AsyncMessageDismisser { + async fn call(&self, params: super::ApiParameterType) -> super::ApiParameterType { + let id = if let Some(param0) = params.get(0) { + if let Primitive::Empty = param0 { + None + } else if let Primitive::F64(since) = param0 { + Some(*since as u64) + } else { + return vec!["dismiss message invalid parameter 0".into()]; + } + } else { + None + }; + if let Some(id) = id { + self.seen.store(id, Ordering::Relaxed); + let filename = settings_dir().join(MESSAGE_SEEN_ID_FILE); + if let Err(e) = std::fs::write(&filename, id.to_le_bytes()) { + log::error!("Failed to write seen id to {}: {}", filename.display(), e); + } + } else { + // TODO clear non-dev messages in cache + } + vec![true.into()] + } +} diff --git a/backend/src/api/mod.rs b/backend/src/api/mod.rs index 8c7a4aa..8dc8add 100644 --- a/backend/src/api/mod.rs +++ b/backend/src/api/mod.rs @@ -5,6 +5,7 @@ pub mod cpu; pub mod general; pub mod gpu; pub mod handler; +pub mod message; mod utility; pub(super) type ApiParameterType = Vec; diff --git a/backend/src/api/utility.rs b/backend/src/api/utility.rs index 7cec146..fda4404 100644 --- a/backend/src/api/utility.rs +++ b/backend/src/api/utility.rs @@ -19,10 +19,7 @@ pub fn map_optional_result>( result: Result, SettingError>, ) -> super::ApiParameterType { match result { - Ok(val) => match val { - Some(val) => vec![val.into()], - None => vec![Primitive::Empty], - }, + Ok(val) => vec![map_optional(val)], Err(e) => { log::debug!("Mapping error to primitive: {}", e); vec![e.msg.into()] @@ -30,6 +27,13 @@ pub fn map_optional_result>( } } +pub fn map_optional>(option: Option) -> Primitive { + match option { + Some(val) => val.into(), + None => Primitive::Empty, + } +} + /*#[inline] pub fn map_empty_result>( result: Result<(), SettingError>, diff --git a/backend/src/consts.rs b/backend/src/consts.rs index 842051a..e296cbe 100644 --- a/backend/src/consts.rs +++ b/backend/src/consts.rs @@ -7,3 +7,5 @@ pub const DEFAULT_SETTINGS_FILE: &str = "default_settings.json"; pub const DEFAULT_SETTINGS_NAME: &str = "Main"; pub const LIMITS_FILE: &str = "limits_cache.json"; + +pub const MESSAGE_SEEN_ID_FILE: &str = "seen_message.bin"; diff --git a/backend/src/main.rs b/backend/src/main.rs index e1ca128..6eb6d99 100644 --- a/backend/src/main.rs +++ b/backend/src/main.rs @@ -73,10 +73,6 @@ fn main() -> Result<(), ()> { } 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)) @@ -88,6 +84,11 @@ fn main() -> Result<(), ()> { ) }); + log::info!( + "Detected device automatically {:?}, using driver: {:?} (This can be overriden)", + crate::settings::auto_detect_provider(), loaded_settings.cpus.provider() + ); + log::debug!("Settings: {:?}", loaded_settings); let (api_handler, api_sender) = crate::api::handler::ApiMessageHandler::new(); @@ -96,6 +97,8 @@ fn main() -> Result<(), ()> { let _resume_handle = resume_worker::spawn(api_sender.clone()); let _power_handle = power_worker::spawn(api_sender.clone()); + let (message_getter, message_dismisser) = api::message::MessageHandler::new().to_callables(); + let instance = Instance::new(PORT) .register("V_INFO", |_: Vec| { #[cfg(debug_assertions)] @@ -126,6 +129,10 @@ fn main() -> Result<(), ()> { "BATTERY_charge_design", api::battery::charge_design(api_sender.clone()), ) + .register_async( + "BATTERY_charge_power", + api::battery::charge_power(api_sender.clone()), + ) .register( "BATTERY_set_charge_rate", api::battery::set_charge_rate(api_sender.clone()), @@ -279,7 +286,13 @@ fn main() -> Result<(), ()> { .register( "GENERAL_on_unplugged", api::battery::on_unplugged(api_sender.clone()), - ); + ) + .register_async( + "GENERAL_get_periodicals", + api::general::get_periodicals(api_sender.clone()) + ) + .register_async("MESSAGE_get", message_getter) + .register_async("MESSAGE_dismiss", message_dismisser); if let Err(e) = loaded_settings.on_set() { e.iter() diff --git a/backend/src/persist/battery.rs b/backend/src/persist/battery.rs index 1e8ed57..57d33bb 100644 --- a/backend/src/persist/battery.rs +++ b/backend/src/persist/battery.rs @@ -9,6 +9,8 @@ pub struct BatteryJson { pub charge_mode: Option, #[serde(default)] pub events: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub root: Option, } #[derive(Serialize, Deserialize, Clone)] @@ -24,6 +26,7 @@ impl Default for BatteryJson { charge_rate: None, charge_mode: None, events: Vec::new(), + root: None, } } } diff --git a/backend/src/persist/cpu.rs b/backend/src/persist/cpu.rs index 442206a..e515311 100644 --- a/backend/src/persist/cpu.rs +++ b/backend/src/persist/cpu.rs @@ -12,6 +12,8 @@ pub struct CpuJson { pub online: bool, pub clock_limits: Option>, pub governor: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub root: Option, } impl Default for CpuJson { @@ -20,6 +22,7 @@ impl Default for CpuJson { online: true, clock_limits: None, governor: "schedutil".to_owned(), + root: None, } } } diff --git a/backend/src/persist/general.rs b/backend/src/persist/general.rs index d012743..58497ec 100644 --- a/backend/src/persist/general.rs +++ b/backend/src/persist/general.rs @@ -5,6 +5,25 @@ use serde::{Deserialize, Serialize}; use super::JsonError; use super::{BatteryJson, CpuJson, DriverJson, GpuJson}; +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct OnEventJson { + pub on_save: Option, + pub on_load: Option, + pub on_set: Option, + pub on_resume: Option, +} + +impl Default for OnEventJson { + fn default() -> Self { + Self { + on_save: None, + on_load: None, + on_set: None, + on_resume: None, + } + } +} + #[derive(Serialize, Deserialize)] pub struct SettingsJson { pub version: u64, @@ -14,6 +33,7 @@ pub struct SettingsJson { pub gpu: GpuJson, pub battery: BatteryJson, pub provider: Option, + pub events: Option, } impl Default for SettingsJson { @@ -26,6 +46,7 @@ impl Default for SettingsJson { gpu: GpuJson::default(), battery: BatteryJson::default(), provider: None, + events: None, } } } @@ -58,6 +79,6 @@ impl SettingsJson { #[derive(Serialize, Deserialize, Clone)] pub struct MinMaxJson { - pub max: T, - pub min: T, + pub max: Option, + pub min: Option, } diff --git a/backend/src/persist/gpu.rs b/backend/src/persist/gpu.rs index 933f2c4..7755847 100644 --- a/backend/src/persist/gpu.rs +++ b/backend/src/persist/gpu.rs @@ -10,6 +10,8 @@ pub struct GpuJson { pub slow_ppt: Option, pub clock_limits: Option>, pub slow_memory: bool, + #[serde(skip_serializing_if = "Option::is_none")] + pub root: Option, } impl Default for GpuJson { @@ -19,6 +21,7 @@ impl Default for GpuJson { slow_ppt: None, clock_limits: None, slow_memory: false, + root: None, } } } diff --git a/backend/src/persist/mod.rs b/backend/src/persist/mod.rs index 75c3caf..17dfa35 100644 --- a/backend/src/persist/mod.rs +++ b/backend/src/persist/mod.rs @@ -8,7 +8,7 @@ mod gpu; pub use battery::{BatteryEventJson, BatteryJson}; pub use cpu::CpuJson; pub use driver::DriverJson; -pub use general::{MinMaxJson, SettingsJson}; +pub use general::{MinMaxJson, OnEventJson, SettingsJson}; pub use gpu::GpuJson; pub use error::JsonError; diff --git a/backend/src/resume_worker.rs b/backend/src/resume_worker.rs index dfa4d8f..1f49ad5 100644 --- a/backend/src/resume_worker.rs +++ b/backend/src/resume_worker.rs @@ -5,7 +5,7 @@ use std::time::{Duration, Instant}; use crate::api::handler::ApiMessage; //use crate::utility::unwrap_maybe_fatal; -const ALLOWED_ERROR: f64 = 100.0; // period of 10ms with 100x means sleep has to be >= 1s to be detected +const ALLOWED_ERROR: f64 = 20.0; // period of 50ms with 20x means sleep has to be >= 1s to be detected pub fn spawn(sender: Sender) -> JoinHandle<()> { thread::spawn(move || { diff --git a/backend/src/settings/detect/auto_detect.rs b/backend/src/settings/detect/auto_detect.rs index 567837b..e66394a 100644 --- a/backend/src/settings/detect/auto_detect.rs +++ b/backend/src/settings/detect/auto_detect.rs @@ -303,6 +303,7 @@ impl DriverBuilder { path: json_path, name: profile_name, driver: DriverJson::AutoDetect, + events: Default::default(), }), cpus: None, gpu: None, diff --git a/backend/src/settings/detect/mod.rs b/backend/src/settings/detect/mod.rs index a514eb9..bb46e2c 100644 --- a/backend/src/settings/detect/mod.rs +++ b/backend/src/settings/detect/mod.rs @@ -3,3 +3,4 @@ pub mod limits_worker; mod utility; pub use auto_detect::{auto_detect0, auto_detect_provider}; +pub use utility::get_dev_messages; diff --git a/backend/src/settings/detect/utility.rs b/backend/src/settings/detect/utility.rs index 16aec42..c278e66 100644 --- a/backend/src/settings/detect/utility.rs +++ b/backend/src/settings/detect/utility.rs @@ -1,3 +1,19 @@ +use limits_core::json::{DeveloperMessage, Base}; + pub fn limits_path() -> std::path::PathBuf { crate::utility::settings_dir().join(crate::consts::LIMITS_FILE) } + +// NOTE: eats errors +pub fn get_dev_messages() -> Vec { + let limits_path = limits_path(); + if let Ok(file) = std::fs::File::open(&limits_path) { + if let Ok(base) = serde_json::from_reader::<_, Base>(file) { + base.messages + } else { + vec![] + } + } else { + vec![] + } +} diff --git a/backend/src/settings/driver.rs b/backend/src/settings/driver.rs index 5f39258..4192f6f 100644 --- a/backend/src/settings/driver.rs +++ b/backend/src/settings/driver.rs @@ -21,6 +21,7 @@ impl Driver { path: json_path, name: settings.name, driver: DriverJson::SteamDeck, + events: settings.events.unwrap_or_default(), }), cpus: Box::new(super::steam_deck::Cpus::from_json( settings.cpus, @@ -51,6 +52,7 @@ impl Driver { path: json_path, name: settings.name, driver: DriverJson::SteamDeck, + events: settings.events.unwrap_or_default(), }), cpus: Box::new(super::steam_deck::Cpus::from_json( settings.cpus, @@ -72,6 +74,7 @@ impl Driver { path: json_path, name: settings.name, driver: DriverJson::SteamDeckAdvance, + events: settings.events.unwrap_or_default(), }), cpus: Box::new(super::steam_deck::Cpus::from_json( settings.cpus, diff --git a/backend/src/settings/general.rs b/backend/src/settings/general.rs index 5e39694..1f47bc2 100644 --- a/backend/src/settings/general.rs +++ b/backend/src/settings/general.rs @@ -34,16 +34,43 @@ pub struct General { pub path: PathBuf, pub name: String, pub driver: crate::persist::DriverJson, + pub events: crate::persist::OnEventJson, } impl OnSet for General { fn on_set(&mut self) -> Result<(), Vec> { + if let Some(event) = &self.events.on_set { + if !event.is_empty() { + std::process::Command::new("/bin/bash") + .args(&["-c", event]) + .spawn() + .map_err(|e| { + vec![SettingError { + msg: format!("on_set event command error: {}", e), + setting: SettingVariant::General, + }] + })?; + } + } Ok(()) } } impl OnResume for General { fn on_resume(&self) -> Result<(), Vec> { + if let Some(event) = &self.events.on_resume { + if !event.is_empty() { + std::process::Command::new("/bin/bash") + .args(&["-c", event]) + .spawn() + .map_err(|e| { + vec![SettingError { + msg: format!("on_resume event command error: {}", e), + setting: SettingVariant::General, + }] + })?; + } + } Ok(()) } } @@ -82,6 +109,10 @@ impl TGeneral for General { fn provider(&self) -> crate::persist::DriverJson { self.driver.clone() } + + fn on_event(&self) -> &crate::persist::OnEventJson { + &self.events + } } #[derive(Debug)] @@ -214,6 +245,17 @@ impl Settings { *self.general.persistent() = false; } self.general.path(filename); + if let Some(event) = &self.general.on_event().on_load { + if !event.is_empty() { + std::process::Command::new("/bin/bash") + .args(&["-c", event]) + .spawn() + .map_err(|e| SettingError { + msg: format!("on_save event command error: {}", e), + setting: SettingVariant::General, + })?; + } + } Ok(*self.general.persistent()) } @@ -257,6 +299,7 @@ impl Settings { gpu: self.gpu.json(), battery: self.battery.json(), provider: Some(self.general.provider()), + events: Some(self.general.on_event().clone()), } } } diff --git a/backend/src/settings/generic/battery.rs b/backend/src/settings/generic/battery.rs index 1a70c37..81464dd 100644 --- a/backend/src/settings/generic/battery.rs +++ b/backend/src/settings/generic/battery.rs @@ -1,6 +1,7 @@ use std::convert::Into; use limits_core::json::GenericBatteryLimit; +use sysfuss::SysEntity; use crate::persist::BatteryJson; use crate::settings::TBattery; @@ -10,6 +11,7 @@ use crate::settings::{OnResume, OnSet, SettingError}; pub struct Battery { #[allow(dead_code)] limits: GenericBatteryLimit, + sysfs: sysfuss::PowerSupplyPath, } impl Into for Battery { @@ -19,6 +21,7 @@ impl Into for Battery { charge_rate: None, charge_mode: None, events: Vec::default(), + root: self.sysfs.root().and_then(|p| p.as_ref().to_str().map(|s| s.to_owned())), } } } @@ -37,18 +40,41 @@ impl Battery { } } + fn find_psu_sysfs(root: Option>) -> sysfuss::PowerSupplyPath { + let root = crate::settings::util::root_or_default_sysfs(root); + match root.power_supply(crate::settings::util::always_satisfied) { + Ok(mut iter) => { + iter.next() + .unwrap_or_else(|| { + log::error!("Failed to find generic battery power_supply in sysfs (no results), using naive fallback"); + root.power_supply_by_name("BAT0") + }) + }, + Err(e) => { + log::error!("Failed to find generic battery power_supply in sysfs ({}), using naive fallback", e); + root.power_supply_by_name("BAT0") + } + } + } + pub fn from_limits(limits: limits_core::json::GenericBatteryLimit) -> Self { // TODO - Self { limits } + Self { + limits, + sysfs: Self::find_psu_sysfs(None::<&'static str>), + } } pub fn from_json_and_limits( - _other: BatteryJson, + other: BatteryJson, _version: u64, limits: limits_core::json::GenericBatteryLimit, ) -> Self { // TODO - Self { limits } + Self { + limits, + sysfs: Self::find_psu_sysfs(other.root) + } } } @@ -129,6 +155,10 @@ impl TBattery for Battery { None } + fn read_charge_power(&self) -> Option { + None + } + fn charge_limit(&mut self, _limit: Option) {} fn get_charge_limit(&self) -> Option { diff --git a/backend/src/settings/generic/cpu.rs b/backend/src/settings/generic/cpu.rs index 3e838ce..00f7dbe 100644 --- a/backend/src/settings/generic/cpu.rs +++ b/backend/src/settings/generic/cpu.rs @@ -3,6 +3,7 @@ use std::convert::{AsMut, AsRef, Into}; use limits_core::json::GenericCpuLimit; 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}; @@ -201,6 +202,7 @@ pub struct Cpu { limits: GenericCpuLimit, index: usize, state: crate::state::steam_deck::Cpu, + root: std::path::PathBuf, } /*impl Cpu { @@ -234,6 +236,7 @@ impl FromGenericCpuInfo for Cpu { limits, index: cpu_index, state: crate::state::steam_deck::Cpu::default(), + root: "/".into(), } } @@ -257,6 +260,7 @@ impl FromGenericCpuInfo for Cpu { limits, index: i, state: crate::state::steam_deck::Cpu::default(), + root: other.root.unwrap_or_else(|| "/".to_string()).into(), }, _ => Self { online: other.online, @@ -265,6 +269,7 @@ impl FromGenericCpuInfo for Cpu { limits, index: i, state: crate::state::steam_deck::Cpu::default(), + root: other.root.unwrap_or_else(|| "/".to_string()).into(), }, } } @@ -330,8 +335,16 @@ impl Cpu { fn limits(&self) -> crate::api::CpuLimits { crate::api::CpuLimits { - clock_min_limits: self.limits.clock_min.clone().map(|x| x.into()), - clock_max_limits: self.limits.clock_max.clone().map(|x| x.into()), + clock_min_limits: self + .limits + .clock_min + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(5_000))), + clock_max_limits: self + .limits + .clock_max + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(5_000))), clock_step: self.limits.clock_step, governors: self.governors(), } @@ -345,6 +358,7 @@ impl Into for Cpu { online: self.online, clock_limits: self.clock_limits.map(|x| x.into()), governor: self.governor, + root: self.root.to_str().map(|s| s.to_owned()), } } } diff --git a/backend/src/settings/generic/gpu.rs b/backend/src/settings/generic/gpu.rs index f8d1a5c..b8fcb6c 100644 --- a/backend/src/settings/generic/gpu.rs +++ b/backend/src/settings/generic/gpu.rs @@ -1,7 +1,9 @@ use std::convert::Into; use limits_core::json::GenericGpuLimit; +use sysfuss::{BasicEntityPath, SysEntity}; +use crate::api::RangeLimit; use crate::persist::GpuJson; use crate::settings::TGpu; use crate::settings::{min_max_from_json, MinMax}; @@ -14,6 +16,7 @@ pub struct Gpu { pub slow_ppt: Option, pub clock_limits: Option>, limits: GenericGpuLimit, + sysfs: BasicEntityPath, } impl Gpu { @@ -30,6 +33,23 @@ impl Gpu { } }*/ + fn find_card_sysfs(root: Option>) -> BasicEntityPath { + let root = crate::settings::util::root_or_default_sysfs(root); + match root.class("drm", crate::settings::util::always_satisfied) { + Ok(mut iter) => { + iter.next() + .unwrap_or_else(|| { + log::error!("Failed to find generic gpu drm in sysfs (no results), using naive fallback"); + BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0")) + }) + }, + Err(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")) + } + } + } + pub fn from_limits(limits: limits_core::json::GenericGpuLimit) -> Self { Self { slow_memory: false, @@ -37,6 +57,7 @@ impl Gpu { slow_ppt: None, clock_limits: None, limits, + sysfs: Self::find_card_sysfs(None::<&'static str>), } } @@ -64,6 +85,7 @@ impl Gpu { }, clock_limits: clock_lims, limits, + sysfs: Self::find_card_sysfs(other.root) } } } @@ -76,6 +98,7 @@ impl Into for Gpu { slow_ppt: self.slow_ppt, 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())) } } } @@ -97,14 +120,38 @@ impl crate::settings::OnPowerEvent for Gpu {} impl TGpu for Gpu { fn limits(&self) -> crate::api::GpuLimits { crate::api::GpuLimits { - fast_ppt_limits: self.limits.fast_ppt.clone().map(|x| x.into()), - slow_ppt_limits: self.limits.slow_ppt.clone().map(|x| x.into()), + fast_ppt_limits: self + .limits + .fast_ppt + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15_000_000))), + slow_ppt_limits: self + .limits + .slow_ppt + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15_000_000))), ppt_step: self.limits.ppt_step.unwrap_or(1_000_000), - tdp_limits: self.limits.tdp.clone().map(|x| x.into()), - tdp_boost_limits: self.limits.tdp_boost.clone().map(|x| x.into()), + tdp_limits: self + .limits + .tdp + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15_000_000))), + tdp_boost_limits: self + .limits + .tdp_boost + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(15_000_000))), tdp_step: self.limits.tdp_step.unwrap_or(42), - clock_min_limits: self.limits.clock_min.clone().map(|x| x.into()), - clock_max_limits: self.limits.clock_max.clone().map(|x| x.into()), + clock_min_limits: self + .limits + .clock_min + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(3_000))), + clock_max_limits: self + .limits + .clock_max + .clone() + .map(|x| RangeLimit::new(x.min.unwrap_or(0), x.max.unwrap_or(3_000))), clock_step: self.limits.clock_step.unwrap_or(100), memory_control_capable: false, } @@ -116,10 +163,20 @@ impl TGpu for Gpu { fn ppt(&mut self, fast: Option, slow: Option) { if let Some(fast_lims) = &self.limits.fast_ppt { - self.fast_ppt = fast.map(|x| x.clamp(fast_lims.min, fast_lims.max)); + self.fast_ppt = fast.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| x.clamp(slow_lims.min, slow_lims.max)); + self.slow_ppt = slow.map(|x| { + x.clamp( + slow_lims.min.unwrap_or(0), + slow_lims.max.unwrap_or(u64::MAX), + ) + }); } } diff --git a/backend/src/settings/generic_amd/gpu.rs b/backend/src/settings/generic_amd/gpu.rs index 841393b..9af3bc2 100644 --- a/backend/src/settings/generic_amd/gpu.rs +++ b/backend/src/settings/generic_amd/gpu.rs @@ -128,24 +128,22 @@ impl Gpu { } if let Some(clock_limits) = &self.generic.clock_limits { self.state.clock_limits_set = true; - lock.set_max_gfxclk_freq(clock_limits.max as _) - .map_err(|e| SettingError { - msg: format!( - "RyzenAdj set_max_gfxclk_freq({}) err: {}", - clock_limits.max, e - ), - setting: SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); - lock.set_min_gfxclk_freq(clock_limits.min as _) - .map_err(|e| SettingError { - msg: format!( - "RyzenAdj set_min_gfxclk_freq({}) err: {}", - clock_limits.min, e - ), - setting: SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); + if let Some(max) = clock_limits.max { + lock.set_max_gfxclk_freq(max as _) + .map_err(|e| SettingError { + msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", max, e), + setting: SettingVariant::Gpu, + }) + .unwrap_or_else(|e| errors.push(e)); + } + if let Some(min) = clock_limits.min { + lock.set_min_gfxclk_freq(min as _) + .map_err(|e| SettingError { + msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", min, e), + setting: SettingVariant::Gpu, + }) + .unwrap_or_else(|e| errors.push(e)); + } } else if self.state.clock_limits_set { self.state.clock_limits_set = false; let limits = self.generic.limits(); @@ -218,24 +216,22 @@ impl Gpu { .unwrap_or_else(|e| errors.push(e)); } if let Some(clock_limits) = &self.generic.clock_limits { - lock.set_max_gfxclk_freq(clock_limits.max as _) - .map_err(|e| SettingError { - msg: format!( - "RyzenAdj set_max_gfxclk_freq({}) err: {}", - clock_limits.max, e - ), - setting: SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); - lock.set_min_gfxclk_freq(clock_limits.min as _) - .map_err(|e| SettingError { - msg: format!( - "RyzenAdj set_min_gfxclk_freq({}) err: {}", - clock_limits.min, e - ), - setting: SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); + if let Some(max) = clock_limits.max { + lock.set_max_gfxclk_freq(max as _) + .map_err(|e| SettingError { + msg: format!("RyzenAdj set_max_gfxclk_freq({}) err: {}", max, e), + setting: SettingVariant::Gpu, + }) + .unwrap_or_else(|e| errors.push(e)); + } + if let Some(min) = clock_limits.min { + lock.set_min_gfxclk_freq(min as _) + .map_err(|e| SettingError { + msg: format!("RyzenAdj set_min_gfxclk_freq({}) err: {}", min, e), + setting: SettingVariant::Gpu, + }) + .unwrap_or_else(|e| errors.push(e)); + } } Ok(()) } diff --git a/backend/src/settings/min_max.rs b/backend/src/settings/min_max.rs index c1c9563..e307268 100644 --- a/backend/src/settings/min_max.rs +++ b/backend/src/settings/min_max.rs @@ -8,8 +8,8 @@ pub type MinMax = RangeLimit; pub fn min_max_from_json>(other: MinMaxJson, _version: u64) -> MinMax { MinMax { - max: other.max.into(), - min: other.min.into(), + max: other.max.map(|x| x.into()), + min: other.min.map(|x| x.into()), } } @@ -17,8 +17,8 @@ impl, Y> Into> for RangeLimit { #[inline] fn into(self) -> MinMaxJson { MinMaxJson { - max: self.max.into(), - min: self.min.into(), + max: self.max.map(|x| x.into()), + min: self.min.map(|x| x.into()), } } } diff --git a/backend/src/settings/mod.rs b/backend/src/settings/mod.rs index ca459e6..c3a0044 100644 --- a/backend/src/settings/mod.rs +++ b/backend/src/settings/mod.rs @@ -11,7 +11,7 @@ pub mod generic_amd; pub mod steam_deck; pub mod unknown; -pub use detect::{auto_detect0, auto_detect_provider, limits_worker::spawn as limits_worker_spawn}; +pub use detect::{auto_detect0, auto_detect_provider, limits_worker::spawn as limits_worker_spawn, get_dev_messages}; pub use driver::Driver; pub use general::{General, SettingVariant, Settings}; pub use min_max::{min_max_from_json, MinMax}; diff --git a/backend/src/settings/steam_deck/battery.rs b/backend/src/settings/steam_deck/battery.rs index 4a5305c..d03bfd6 100644 --- a/backend/src/settings/steam_deck/battery.rs +++ b/backend/src/settings/steam_deck/battery.rs @@ -1,4 +1,8 @@ use std::convert::Into; +use std::sync::Arc; + +use sysfuss::{PowerSupplyAttribute, PowerSupplyPath, HwMonAttribute, HwMonAttributeItem, HwMonAttributeType, HwMonPath, SysEntity, SysEntityAttributesExt, SysAttribute}; +use sysfuss::capability::attributes; use super::oc_limits::{BatteryLimits, OverclockLimits}; use super::util::ChargeMode; @@ -15,6 +19,8 @@ pub struct Battery { limits: BatteryLimits, state: crate::state::steam_deck::Battery, driver_mode: crate::persist::DriverJson, + sysfs_bat: PowerSupplyPath, + sysfs_hwmon: Arc, } #[derive(Debug, Clone)] @@ -32,6 +38,7 @@ struct EventInstruction { charge_rate: Option, charge_mode: Option, is_triggered: bool, + sysfs_hwmon: Arc, } impl OnPowerEvent for EventInstruction { @@ -99,17 +106,17 @@ impl EventInstruction { .trim_start_matches('>') .parse::() .ok() - .map(|x| EventTrigger::BatteryAbove(x/100.0)), + .map(|x| EventTrigger::BatteryAbove(x / 100.0)), s if s.starts_with('<') => s .trim_start_matches('<') .parse::() .ok() - .map(|x| EventTrigger::BatteryBelow(x/100.0)), + .map(|x| EventTrigger::BatteryBelow(x / 100.0)), _ => None, } } - fn from_json(other: BatteryEventJson, _version: u64) -> Self { + fn from_json(other: BatteryEventJson, _version: u64, hwmon: Arc) -> Self { Self { trigger: Self::str_to_trigger(&other.trigger).unwrap_or(EventTrigger::Ignored), charge_rate: other.charge_rate, @@ -118,6 +125,7 @@ impl EventInstruction { .map(|x| Battery::str_to_charge_mode(&x)) .flatten(), is_triggered: false, + sysfs_hwmon: hwmon, } } @@ -136,12 +144,17 @@ impl EventInstruction { fn set_charge_rate(&self) -> Result<(), SettingError> { if let Some(charge_rate) = self.charge_rate { - usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, charge_rate) - .map_err(|e| SettingError { - msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), + let attr = if MAX_BATTERY_CHARGE_RATE_ATTR.exists(&*self.sysfs_hwmon) { + MAX_BATTERY_CHARGE_RATE_ATTR + } else { + MAXIMUM_BATTERY_CHARGE_RATE_ATTR + }; + self.sysfs_hwmon.set(attr, charge_rate).map_err( + |e| SettingError { + msg: format!("Failed to write to `{:?}`: {}", attr, e), setting: crate::settings::SettingVariant::Battery, - }) - .map(|_| ()) + }, + ) } else { Ok(()) } @@ -173,12 +186,36 @@ impl Into for EventInstruction { const BATTERY_VOLTAGE: f64 = 7.7; -const BATTERY_CHARGE_RATE_PATH: &str = "/sys/class/hwmon/hwmon5/maximum_battery_charge_rate"; // write-only +/*const BATTERY_CHARGE_RATE_PATH: &str = "/sys/class/hwmon/hwmon5/maximum_battery_charge_rate"; // write-only const BATTERY_CURRENT_NOW_PATH: &str = "/sys/class/power_supply/BAT1/current_now"; // read-only const BATTERY_CHARGE_NOW_PATH: &str = "/sys/class/power_supply/BAT1/charge_now"; // read-only const BATTERY_CHARGE_FULL_PATH: &str = "/sys/class/power_supply/BAT1/charge_full"; // read-only const BATTERY_CHARGE_DESIGN_PATH: &str = "/sys/class/power_supply/BAT1/charge_full_design"; // read-only const USB_PD_IN_MVOLTAGE_PATH: &str = "/sys/class/hwmon/hwmon5/in0_input"; // read-only +const USB_PD_IN_CURRENT_PATH: &str = "/sys/class/hwmon/hwmon5/curr1_input"; // read-only*/ + + +const BATTERY_NEEDS: &[PowerSupplyAttribute] = &[ + PowerSupplyAttribute::Type, + PowerSupplyAttribute::CurrentNow, + PowerSupplyAttribute::ChargeNow, + PowerSupplyAttribute::ChargeFull, + PowerSupplyAttribute::ChargeFullDesign, + PowerSupplyAttribute::CycleCount, + PowerSupplyAttribute::Capacity, + PowerSupplyAttribute::CapacityLevel, +]; + +const HWMON_NEEDS: &[HwMonAttribute] = &[ + HwMonAttribute::name(), + HwMonAttribute::new(HwMonAttributeType::In, 0, HwMonAttributeItem::Input), + HwMonAttribute::new(HwMonAttributeType::Curr, 1, HwMonAttributeItem::Input), + //HwMonAttribute::custom("maximum_battery_charge_rate"), // NOTE: Cannot filter by custom capabilities +]; + +const MAXIMUM_BATTERY_CHARGE_RATE_ATTR: HwMonAttribute = HwMonAttribute::custom("maximum_battery_charge_rate"); +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"); impl Battery { #[inline] @@ -190,6 +227,7 @@ impl Battery { } else { crate::persist::DriverJson::SteamDeckAdvance }; + let hwmon_sys = Arc::new(Self::find_hwmon_sysfs(None::<&'static str>)); match version { 0 => Self { charge_rate: other.charge_rate, @@ -200,11 +238,13 @@ impl Battery { events: other .events .into_iter() - .map(|x| EventInstruction::from_json(x, version)) + .map(|x| EventInstruction::from_json(x, version, hwmon_sys.clone())) .collect(), limits: oc_limits, state: crate::state::steam_deck::Battery::default(), driver_mode: driver, + sysfs_bat: Self::find_battery_sysfs(None::<&'static str>), + sysfs_hwmon: hwmon_sys, }, _ => Self { charge_rate: other.charge_rate, @@ -215,15 +255,68 @@ impl Battery { events: other .events .into_iter() - .map(|x| EventInstruction::from_json(x, version)) + .map(|x| EventInstruction::from_json(x, version, hwmon_sys.clone())) .collect(), limits: oc_limits, state: crate::state::steam_deck::Battery::default(), driver_mode: driver, + sysfs_bat: Self::find_battery_sysfs(None::<&'static str>), + sysfs_hwmon: hwmon_sys, }, } } + fn find_battery_sysfs(root: Option>) -> PowerSupplyPath { + let root = crate::settings::util::root_or_default_sysfs(root); + match root.power_supply(attributes(BATTERY_NEEDS.into_iter().copied())) { + Ok(mut iter) => { + let psu = iter.next() + .unwrap_or_else(|| { + 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()); + psu + }, + Err(e) => { + log::error!("Failed to find SteamDeck battery power_supply in sysfs ({}), using naive fallback", e); + root.power_supply_by_name("BAT1") + } + } + } + + fn find_hwmon_sysfs(root: Option>) -> HwMonPath { + let root = crate::settings::util::root_or_default_sysfs(root); + match root.hwmon_by_name(super::util::JUPITER_HWMON_NAME) { + 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()); + } + hwmon + }, + Err(e) => { + log::warn!("Failed to find SteamDeck battery hwmon {} in sysfs ({}), trying alternate name", + super::util::JUPITER_HWMON_NAME, e); + match root.hwmon_by_name(super::util::STEAMDECK_HWMON_NAME) { + 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::STEAMDECK_HWMON_NAME); + } else { + 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) + } + } + } + } + } + #[inline] fn charge_mode_to_str(mode: ChargeMode) -> String { match mode { @@ -244,6 +337,40 @@ impl Battery { } } + fn set_charge_rate(&mut self) -> Result<(), SettingError> { + if let Some(charge_rate) = self.charge_rate { + self.state.charge_rate_set = true; + let attr = if MAX_BATTERY_CHARGE_RATE_ATTR.exists(&*self.sysfs_hwmon) { + MAX_BATTERY_CHARGE_RATE_ATTR + } else { + MAXIMUM_BATTERY_CHARGE_RATE_ATTR + }; + let path = attr.path(&*self.sysfs_hwmon); + self.sysfs_hwmon.set(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 attr = if MAX_BATTERY_CHARGE_RATE_ATTR.exists(&*self.sysfs_hwmon) { + MAX_BATTERY_CHARGE_RATE_ATTR + } else { + MAXIMUM_BATTERY_CHARGE_RATE_ATTR + }; + let path = attr.path(&*self.sysfs_hwmon); + self.sysfs_hwmon.set(attr, self.limits.charge_rate.max,).map_err( + |e| SettingError { + msg: format!("Failed to write to `{}`: {}", path.display(), e), + setting: crate::settings::SettingVariant::Battery, + }, + ) + } else { + Ok(()) + } + } + fn set_charge_mode(&mut self) -> Result<(), SettingError> { if let Some(charge_mode) = self.charge_mode { self.state.charge_mode_set = true; @@ -268,26 +395,7 @@ impl Battery { fn set_all(&mut self) -> Result<(), Vec> { let mut errors = Vec::new(); - if let Some(charge_rate) = self.charge_rate { - self.state.charge_rate_set = true; - usdpl_back::api::files::write_single(BATTERY_CHARGE_RATE_PATH, charge_rate) - .map_err(|e| SettingError { - msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }) - .unwrap_or_else(|e| errors.push(e)); - } else if self.state.charge_rate_set { - self.state.charge_rate_set = false; - usdpl_back::api::files::write_single( - BATTERY_CHARGE_RATE_PATH, - self.limits.charge_rate.max, - ) - .map_err(|e| SettingError { - msg: format!("Failed to write to `{}`: {}", BATTERY_CHARGE_RATE_PATH, e), - setting: crate::settings::SettingVariant::Battery, - }) - .unwrap_or_else(|e| errors.push(e)); - } + self.set_charge_rate().unwrap_or_else(|e| errors.push(e)); self.set_charge_mode().unwrap_or_else(|e| errors.push(e)); if errors.is_empty() { Ok(()) @@ -303,10 +411,11 @@ impl Battery { } } - pub fn read_current_now() -> Result { - match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CURRENT_NOW_PATH) { + pub fn read_current_now(&self) -> Result { + let attr = PowerSupplyAttribute::CurrentNow; + match self.sysfs_bat.attribute::(attr) { Err(e) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CURRENT_NOW_PATH, e), + msg: format!("Failed to read from `{:?}`: {}", attr, e), setting: crate::settings::SettingVariant::Battery, }), // this value is in uA, while it's set in mA @@ -315,10 +424,17 @@ impl Battery { } } - pub fn read_charge_now() -> Result { - match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_NOW_PATH) { + pub fn read_charge_power(&self) -> Result { + let current = self.read_usb_current()?; + let voltage = self.read_usb_voltage()?; + Ok(current * voltage) + } + + pub fn read_charge_now(&self) -> Result { + let attr = PowerSupplyAttribute::ChargeNow; + match self.sysfs_bat.attribute::(attr) { Err(e) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_NOW_PATH, e), + msg: format!("Failed to read from `{:?}`: {}", attr, e), setting: crate::settings::SettingVariant::Battery, }), // convert to Wh @@ -326,10 +442,11 @@ impl Battery { } } - pub fn read_charge_full() -> Result { - match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_FULL_PATH) { + pub fn read_charge_full(&self) -> Result { + let attr = PowerSupplyAttribute::ChargeFull; + match self.sysfs_bat.attribute::(attr) { Err(e) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", BATTERY_CHARGE_FULL_PATH, e), + msg: format!("Failed to read from `{:?}`: {}", attr, e), setting: crate::settings::SettingVariant::Battery, }), // convert to Wh @@ -337,13 +454,11 @@ impl Battery { } } - pub fn read_charge_design() -> Result { - match usdpl_back::api::files::read_single::<_, u64, _>(BATTERY_CHARGE_DESIGN_PATH) { + pub fn read_charge_design(&self) -> Result { + let attr = PowerSupplyAttribute::ChargeFullDesign; + match self.sysfs_bat.attribute::(attr) { Err(e) => Err(SettingError { - msg: format!( - "Failed to read from `{}`: {}", - BATTERY_CHARGE_DESIGN_PATH, e - ), + msg: format!("Failed to read from `{:?}`: {}", attr, e), setting: crate::settings::SettingVariant::Battery, }), // convert to Wh @@ -351,10 +466,11 @@ impl Battery { } } - pub fn read_usb_voltage() -> Result { - match usdpl_back::api::files::read_single::<_, u64, _>(USB_PD_IN_MVOLTAGE_PATH) { + pub fn read_usb_voltage(&self) -> Result { + let attr = HwMonAttribute::new(HwMonAttributeType::In, 0, HwMonAttributeItem::Input); + match self.sysfs_hwmon.attribute::(attr) { Err(e) => Err(SettingError { - msg: format!("Failed to read from `{}`: {}", USB_PD_IN_MVOLTAGE_PATH, e), + msg: format!("Failed to read from `{:?}`: {}", attr, e), setting: crate::settings::SettingVariant::Battery, }), // convert to V (from mV) @@ -362,6 +478,17 @@ impl Battery { } } + pub fn read_usb_current(&self) -> Result { + let attr = HwMonAttribute::new(HwMonAttributeType::Curr, 1, HwMonAttributeItem::Input); + match self.sysfs_hwmon.attribute::(attr) { + Err(e) => Err(SettingError { + msg: format!("Failed to read `{:?}`: {}", attr, e), + setting: crate::settings::SettingVariant::Battery, + }), + Ok(val) => Ok((val as f64) / 1000.0), // mA -> A + } + } + pub fn system_default() -> Self { let (oc_limits, is_default) = OverclockLimits::load_or_default(); let oc_limits = oc_limits.battery; @@ -377,6 +504,8 @@ impl Battery { limits: oc_limits, state: crate::state::steam_deck::Battery::default(), driver_mode: driver, + sysfs_bat: Self::find_battery_sysfs(None::<&'static str>), + sysfs_hwmon: Arc::new(Self::find_hwmon_sysfs(None::<&'static str>)), } } @@ -416,6 +545,7 @@ impl Into for Battery { charge_rate: self.charge_rate, charge_mode: self.charge_mode.map(Self::charge_mode_to_str), events: self.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())) } } } @@ -454,7 +584,22 @@ impl OnPowerEvent for Battery { PowerMode::BatteryCharge(_) => Ok(()), } .unwrap_or_else(|mut e| errors.append(&mut e)); + let attr_exists = MAX_BATTERY_CHARGE_LEVEL_ATTR.exists(&*self.sysfs_hwmon); + log::info!("Does battery limit attribute (max_battery_charge_level) exist? {}", attr_exists); for ev in &mut self.events { + if attr_exists { + if let EventTrigger::BatteryAbove(level) = ev.trigger { + if let Some(ChargeMode::Idle) = ev.charge_mode { + self.sysfs_hwmon.set(MAX_BATTERY_CHARGE_LEVEL_ATTR, (level * 100.0).round() as u64) + .unwrap_or_else(|e| errors.push( + SettingError { + msg: format!("Failed to write to {:?}: {}", MAX_BATTERY_CHARGE_LEVEL_ATTR, e), + setting: crate::settings::SettingVariant::Battery, + } + )); + } + } + } ev.on_power_event(new_mode) .unwrap_or_else(|mut e| errors.append(&mut e)); } @@ -508,7 +653,7 @@ impl TBattery for Battery { } fn read_charge_full(&self) -> Option { - match Self::read_charge_full() { + match self.read_charge_full() { Ok(x) => Some(x), Err(e) => { log::warn!("read_charge_full err: {}", e.msg); @@ -518,7 +663,7 @@ impl TBattery for Battery { } fn read_charge_now(&self) -> Option { - match Self::read_charge_now() { + match self.read_charge_now() { Ok(x) => Some(x), Err(e) => { log::warn!("read_charge_now err: {}", e.msg); @@ -528,7 +673,7 @@ impl TBattery for Battery { } fn read_charge_design(&self) -> Option { - match Self::read_charge_design() { + match self.read_charge_design() { Ok(x) => Some(x), Err(e) => { log::warn!("read_charge_design err: {}", e.msg); @@ -538,12 +683,30 @@ impl TBattery for Battery { } fn read_current_now(&self) -> Option { - match Self::read_current_now() { - Ok(x) => Some(x as f64), - Err(e) => { - log::warn!("read_current_now err: {}", e.msg); - None + if self.limits.extra_readouts { + match self.read_current_now() { + Ok(x) => Some(x as f64), + Err(e) => { + log::warn!("read_current_now err: {}", e.msg); + None + } } + } else { + None + } + } + + fn read_charge_power(&self) -> Option { + if self.limits.extra_readouts { + match self.read_charge_power() { + Ok(x) => Some(x as f64), + Err(e) => { + log::warn!("read_current_now err: {}", e.msg); + None + } + } + } else { + None } } @@ -561,6 +724,7 @@ impl TBattery for Battery { charge_rate: None, charge_mode: Some(ChargeMode::Idle), is_triggered: false, + sysfs_hwmon: self.sysfs_hwmon.clone(), }; } else { self.events.remove(index); @@ -575,6 +739,7 @@ impl TBattery for Battery { charge_rate: None, charge_mode: Some(ChargeMode::Idle), is_triggered: false, + sysfs_hwmon: self.sysfs_hwmon.clone(), }); } // lower limit @@ -591,6 +756,7 @@ impl TBattery for Battery { charge_rate: None, charge_mode: Some(ChargeMode::Normal), is_triggered: false, + sysfs_hwmon: self.sysfs_hwmon.clone(), }; } else { self.events.remove(index); @@ -606,6 +772,7 @@ impl TBattery for Battery { charge_rate: None, charge_mode: Some(ChargeMode::Normal), is_triggered: false, + sysfs_hwmon: self.sysfs_hwmon.clone(), }); } } @@ -628,7 +795,7 @@ impl TBattery for Battery { log::debug!("Steam Deck power vibe check"); let mut errors = Vec::new(); let mut events = Vec::new(); - match (Self::read_charge_full(), Self::read_charge_now()) { + match (self.read_charge_full(), self.read_charge_now()) { (Ok(full), Ok(now)) => events.push(PowerMode::BatteryCharge(now / full)), (Err(e1), Err(e2)) => { errors.push(e1); @@ -637,7 +804,7 @@ impl TBattery for Battery { (Err(e), _) => errors.push(e), (_, Err(e)) => errors.push(e), } - match Self::read_usb_voltage() { + match self.read_usb_voltage() { Ok(voltage) => { if voltage > 0.0 && self.state.charger_state != crate::state::steam_deck::ChargeState::PluggedIn diff --git a/backend/src/settings/steam_deck/cpu.rs b/backend/src/settings/steam_deck/cpu.rs index 91ec128..a6e4d10 100644 --- a/backend/src/settings/steam_deck/cpu.rs +++ b/backend/src/settings/steam_deck/cpu.rs @@ -1,5 +1,7 @@ use std::convert::Into; +use sysfuss::{BasicEntityPath, SysEntity, SysEntityAttributesExt}; + use super::oc_limits::{CpuLimits, CpusLimits, OverclockLimits}; use super::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT; use crate::api::RangeLimit; @@ -11,6 +13,10 @@ use crate::settings::{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 +]; + #[derive(Debug, Clone)] pub struct Cpus { pub cpus: Vec, @@ -230,9 +236,16 @@ pub struct Cpu { limits: CpuLimits, index: usize, state: crate::state::steam_deck::Cpu, + sysfs: BasicEntityPath, } -const CPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; +//const CPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; +const CPU_CLOCK_LIMITS_ATTRIBUTE: &str = "device/pp_od_clk_voltage"; + +enum ClockType { + Min = 0, + Max = 1, +} impl Cpu { #[inline] @@ -245,6 +258,7 @@ impl Cpu { limits: oc_limits, index: i, state: crate::state::steam_deck::Cpu::default(), + sysfs: Self::find_card_sysfs(other.root), }, _ => Self { online: other.online, @@ -253,99 +267,161 @@ impl Cpu { limits: oc_limits, index: i, state: crate::state::steam_deck::Cpu::default(), + sysfs: Self::find_card_sysfs(other.root), }, } } + fn find_card_sysfs(root: Option>) -> BasicEntityPath { + let root = crate::settings::util::root_or_default_sysfs(root); + match root.class("drm", sysfuss::capability::attributes(crate::settings::util::CARD_NEEDS.into_iter().map(|s| s.to_string()))) { + Ok(iter) => { + let card = iter + .filter(|ent| if let Ok(name) = ent.name() { name.starts_with("card")} else { false }) + .filter(|ent| super::util::card_also_has(ent, CARD_EXTENSIONS)) + .next() + .unwrap_or_else(|| { + log::error!("Failed to find SteamDeck drm in sysfs (no results), using naive fallback"); + BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0")) + }); + 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); + BasicEntityPath::new(root.as_ref().join("sys/class/drm/card0")) + } + } + } + + 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 { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &payload, CPU_CLOCK_LIMITS_ATTRIBUTE, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + }) + } + + fn set_clock_limits(&mut self) -> Result<(), Vec> { + let mut errors = Vec::new(); + if let Some(clock_limits) = &self.clock_limits { + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(true, self.index); + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs)?; + log::debug!( + "Setting CPU {} (min, max) clockspeed to ({:?}, {:?})", + self.index, + clock_limits.min, + clock_limits.max + ); + self.state.clock_limits_set = true; + // max clock + if let Some(max) = clock_limits.max { + self.set_clock_limit(self.index, max, ClockType::Max) + .unwrap_or_else(|e| errors.push(e)); + } + // min clock + if let Some(min) = clock_limits.min { + let valid_min = if min < self.limits.clock_min.min { + self.limits.clock_min.min + } else { + min + }; + self.set_clock_limit(self.index, valid_min, ClockType::Min) + .unwrap_or_else(|e| errors.push(e)); + } + + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } + } else if self.state.clock_limits_set + || (self.state.is_resuming && !self.limits.skip_resume_reclock) + || POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() + { + 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)?; + 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, self.limits.clock_max.max, ClockType::Max) + .unwrap_or_else(|e| errors.push(e)); + // min clock + self.set_clock_limit(self.index, self.limits.clock_min.min, 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)); + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } + } else { + Ok(()) + } + } + + // https://github.com/NGnius/PowerTools/issues/107 + fn clock_unset_workaround(&self) -> Result<(), Vec> { + if !self.state.is_resuming { + let mut errors = Vec::new(); + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(true, self.index); + // 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, self.limits.clock_max.max, ClockType::Max) + .unwrap_or_else(|e| errors.push(e)); + // min clock + self.set_clock_limit(self.index, self.limits.clock_min.min, ClockType::Min) + .unwrap_or_else(|e| errors.push(e)); + + self.set_confirm().unwrap_or_else(|e| errors.push(e)); + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(false, self.index); + if errors.is_empty() { + Ok(()) + } else { + Err(errors) + } + } else { + Ok(()) + } + } + + 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), + setting: crate::settings::SettingVariant::Cpu, + } + }) + } + fn set_force_performance_related(&mut self) -> Result<(), Vec> { let mut errors = Vec::new(); // set clock limits //log::debug!("Setting {} to manual", CPU_FORCE_LIMITS_PATH); //let mode: String = usdpl_back::api::files::read_single(CPU_FORCE_LIMITS_PATH.to_owned()).unwrap(); - if let Some(clock_limits) = &self.clock_limits { - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(true, self.index); - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?; - log::debug!( - "Setting CPU {} (min, max) clockspeed to ({}, {})", - self.index, - clock_limits.min, - clock_limits.max - ); - self.state.clock_limits_set = true; - // max clock - let payload_max = format!("p {} 1 {}\n", self.index / 2, clock_limits.max); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }) - .unwrap_or_else(|e| errors.push(e)); - // min clock - let valid_min = if clock_limits.min < self.limits.clock_min.min { - self.limits.clock_min.min - } else { - clock_limits.min - }; - let payload_min = format!("p {} 0 {}\n", self.index / 2, valid_min); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }) - .unwrap_or_else(|e| errors.push(e)); - } else if self.state.clock_limits_set - || (self.state.is_resuming && !self.limits.skip_resume_reclock) - || POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() - { - self.state.clock_limits_set = false; - if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?; - // disable manual clock limits - log::debug!("Setting CPU {} to default clockspeed", self.index); - // max clock - let payload_max = format!("p {} 1 {}\n", self.index / 2, self.limits.clock_max.max); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_max) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }) - .unwrap_or_else(|e| errors.push(e)); - // min clock - let payload_min = format!("p {} 0 {}\n", self.index / 2, self.limits.clock_min.min); - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, &payload_min) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, CPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Cpu, - }) - .unwrap_or_else(|e| errors.push(e)); - } - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_cpu(false, self.index); - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT - .enforce_level() - .unwrap_or_else(|mut e| errors.append(&mut e)); - } + self.set_clock_limits() + .unwrap_or_else(|mut e| errors.append(&mut e)); // commit changes (if no errors have already occured) if errors.is_empty() { if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { - usdpl_back::api::files::write_single(CPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { - vec![SettingError { - msg: format!("Failed to write `c` to `{}`: {}", CPU_CLOCK_LIMITS_PATH, e), - setting: crate::settings::SettingVariant::Cpu, - }] - }) + self.set_confirm().map_err(|e| vec![e]) } else { Ok(()) } @@ -354,6 +430,23 @@ impl Cpu { } } + fn set_governor(&self) -> Result<(), SettingError> { + if self.index == 0 || self.online { + let governor_path = cpu_governor_path(self.index); + usdpl_back::api::files::write_single(&governor_path, &self.governor).map_err(|e| { + SettingError { + msg: format!( + "Failed to write `{}` to `{}`: {}", + &self.governor, &governor_path, e + ), + setting: crate::settings::SettingVariant::Cpu, + } + }) + } else { + Ok(()) + } + } + fn set_all(&mut self) -> Result<(), Vec> { let mut errors = Vec::new(); // set cpu online/offline @@ -371,19 +464,8 @@ impl Cpu { self.set_force_performance_related() .unwrap_or_else(|mut e| errors.append(&mut e)); - // set governor - if self.index == 0 || self.online { - let governor_path = cpu_governor_path(self.index); - usdpl_back::api::files::write_single(&governor_path, &self.governor) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &self.governor, &governor_path, e - ), - setting: crate::settings::SettingVariant::Cpu, - }) - .unwrap_or_else(|e| errors.push(e)); - } + self.set_governor().unwrap_or_else(|e| errors.push(e)); + if errors.is_empty() { Ok(()) } else { @@ -393,12 +475,14 @@ impl Cpu { fn clamp_all(&mut self) { if let Some(clock_limits) = &mut self.clock_limits { - clock_limits.min = clock_limits - .min - .clamp(self.limits.clock_min.min, self.limits.clock_min.max); - clock_limits.max = clock_limits - .max - .clamp(self.limits.clock_max.min, self.limits.clock_max.max); + if let Some(min) = clock_limits.min { + clock_limits.min = + Some(min.clamp(self.limits.clock_min.min, self.limits.clock_min.max)); + } + if let Some(max) = clock_limits.max { + clock_limits.max = + Some(max.clamp(self.limits.clock_max.min, self.limits.clock_max.max)); + } } } @@ -422,6 +506,7 @@ impl Cpu { limits: oc_limits, index: cpu_index, state: crate::state::steam_deck::Cpu::default(), + sysfs: Self::find_card_sysfs(None::<&'static str>) } } @@ -461,6 +546,7 @@ impl Into for Cpu { online: self.online, clock_limits: self.clock_limits.map(|x| x.into()), governor: self.governor, + root: self.sysfs.root().and_then(|p| p.as_ref().to_str().map(|r| r.to_owned())) } } } diff --git a/backend/src/settings/steam_deck/gpu.rs b/backend/src/settings/steam_deck/gpu.rs index 83bf2bd..f1f428b 100644 --- a/backend/src/settings/steam_deck/gpu.rs +++ b/backend/src/settings/steam_deck/gpu.rs @@ -1,5 +1,7 @@ use std::convert::Into; +use sysfuss::{BasicEntityPath, HwMonPath, SysEntity, capability::attributes, SysEntityAttributesExt, SysAttribute}; + use super::oc_limits::{GpuLimits, OverclockLimits}; use super::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT; use crate::api::RangeLimit; @@ -8,8 +10,9 @@ use crate::settings::TGpu; use crate::settings::{min_max_from_json, MinMax}; use crate::settings::{OnResume, OnSet, SettingError}; -const SLOW_PPT: u8 = 1; -const FAST_PPT: u8 = 2; +// usually in /sys/class/hwmon/hwmon4/ +const SLOW_PPT_ATTRIBUTE: sysfuss::HwMonAttribute = sysfuss::HwMonAttribute::custom("power1_cap"); +const FAST_PPT_ATTRIBUTE: sysfuss::HwMonAttribute = sysfuss::HwMonAttribute::custom("power2_cap"); #[derive(Debug, Clone)] pub struct Gpu { @@ -20,11 +23,27 @@ pub struct Gpu { limits: GpuLimits, state: crate::state::steam_deck::Gpu, driver_mode: crate::persist::DriverJson, + sysfs_card: BasicEntityPath, + sysfs_hwmon: HwMonPath } // same as CPU -const GPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; -const GPU_MEMORY_DOWNCLOCK_PATH: &str = "/sys/class/drm/card0/device/pp_dpm_fclk"; +//const GPU_CLOCK_LIMITS_PATH: &str = "/sys/class/drm/card0/device/pp_od_clk_voltage"; +//const GPU_MEMORY_DOWNCLOCK_PATH: &str = "/sys/class/drm/card0/device/pp_dpm_fclk"; + +const GPU_CLOCK_LIMITS_ATTRIBUTE: &str = "device/pp_od_clk_voltage"; +const GPU_MEMORY_DOWNCLOCK_ATTRIBUTE: &str = "device/pp_dpm_fclk"; + +const CARD_EXTENSIONS: &[&'static str] = &[ + GPU_CLOCK_LIMITS_ATTRIBUTE, + GPU_MEMORY_DOWNCLOCK_ATTRIBUTE, + super::DPM_FORCE_LIMITS_ATTRIBUTE, +]; + +enum ClockType { + Min = 0, + Max = 1, +} impl Gpu { #[inline] @@ -44,6 +63,8 @@ impl Gpu { limits: oc_limits.gpu, state: crate::state::steam_deck::Gpu::default(), driver_mode: driver, + sysfs_card: Self::find_card_sysfs(other.root.clone()), + sysfs_hwmon: Self::find_hwmon_sysfs(other.root), }, _ => Self { fast_ppt: other.fast_ppt, @@ -53,93 +74,104 @@ impl Gpu { limits: oc_limits.gpu, state: crate::state::steam_deck::Gpu::default(), driver_mode: driver, + sysfs_card: Self::find_card_sysfs(other.root.clone()), + sysfs_hwmon: Self::find_hwmon_sysfs(other.root), }, } } + fn find_card_sysfs(root: Option>) -> BasicEntityPath { + let root = crate::settings::util::root_or_default_sysfs(root); + match root.class("drm", attributes(crate::settings::util::CARD_NEEDS.into_iter().map(|s| s.to_string()))) { + Ok(iter) => { + let card = iter + .filter(|ent| if let Ok(name) = ent.name() { name.starts_with("card")} else { false }) + .filter(|ent| super::util::card_also_has(ent, CARD_EXTENSIONS)) + .next() + .unwrap_or_else(|| { + 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()); + card + }, + Err(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")) + } + } + } + + fn find_hwmon_sysfs(root: Option>) -> HwMonPath { + let root = crate::settings::util::root_or_default_sysfs(root); + let hwmon = root.hwmon_by_name(super::util::GPU_HWMON_NAME).unwrap_or_else(|e| { + log::error!("Failed to find SteamDeck gpu hwmon in sysfs ({}), using naive fallback", e); + root.hwmon_by_index(4) + }); + log::info!("Found SteamDeck gpu hwmon {} in sysfs: {}", super::util::GPU_HWMON_NAME, hwmon.as_ref().display()); + 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), + 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 { + msg: format!("Failed to write `c` to `{}`: {}", path.display(), e), + setting: crate::settings::SettingVariant::Gpu, + } + }) + } + fn set_clocks(&mut self) -> Result<(), Vec> { let mut errors = Vec::new(); if let Some(clock_limits) = &self.clock_limits { POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(true); - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?; + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs_card)?; // set clock limits self.state.clock_limits_set = true; // max clock - let payload_max = format!("s 1 {}\n", clock_limits.max); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); + if let Some(max) = clock_limits.max { + self.set_clock_limit(max, ClockType::Max).unwrap_or_else(|e| errors.push(e)); + } // min clock - let payload_min = format!("s 0 {}\n", clock_limits.min); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }) - .unwrap_or_else(|e| errors.push(e)); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else( - |e| { - errors.push(SettingError { - msg: format!("Failed to write `c` to `{}`: {}", GPU_CLOCK_LIMITS_PATH, e), - setting: crate::settings::SettingVariant::Gpu, - }) - }, - ); + if let Some(min) = clock_limits.min { + self.set_clock_limit(min, ClockType::Min).unwrap_or_else(|e| errors.push(e)); + } + + self.set_confirm().unwrap_or_else(|e| errors.push(e)); } else if self.state.clock_limits_set || (self.state.is_resuming && !self.limits.skip_resume_reclock) || POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { self.state.clock_limits_set = false; + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.slow_memory); if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level()?; + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.enforce_level(&self.sysfs_card)?; // disable manual clock limits // max clock - let payload_max = format!("s 1 {}\n", self.limits.clock_max.max); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_max) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_max, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }) + self.set_clock_limit(self.limits.clock_max.max, ClockType::Max) .unwrap_or_else(|e| errors.push(e)); // min clock - let payload_min = format!("s 0 {}\n", self.limits.clock_min.min); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, &payload_min) - .map_err(|e| SettingError { - msg: format!( - "Failed to write `{}` to `{}`: {}", - &payload_min, GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }) + self.set_clock_limit(self.limits.clock_min.min, ClockType::Min) .unwrap_or_else(|e| errors.push(e)); - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").unwrap_or_else( - |e| { - errors.push(SettingError { - msg: format!( - "Failed to write `c` to `{}`: {}", - GPU_CLOCK_LIMITS_PATH, e - ), - setting: crate::settings::SettingVariant::Gpu, - }) - }, - ); + + self.set_confirm().unwrap_or_else(|e| errors.push(e)); + } else { + POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT + .enforce_level(&self.sysfs_card) + .unwrap_or_else(|mut e| errors.append(&mut e)); } - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.slow_memory); - POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT - .enforce_level() - .unwrap_or_else(|mut e| errors.append(&mut e)); } if errors.is_empty() { Ok(()) @@ -148,32 +180,40 @@ impl Gpu { } } + fn set_slow_memory(&self, slow: bool) -> Result<(), SettingError> { + let path = GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.path(&self.sysfs_card); + if slow { + self.sysfs_card.set(GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.to_owned(), slow as u8).map_err(|e| { + SettingError { + msg: format!("Failed to write to `{}`: {}", path.display(), e), + setting: crate::settings::SettingVariant::Gpu, + } + }) + } else { + // NOTE: there is a GPU driver/hardware bug that prevents this from working + self.sysfs_card.set(GPU_MEMORY_DOWNCLOCK_ATTRIBUTE.to_owned(), "0 1\n").map_err(|e| { + SettingError { + msg: format!("Failed to write to `{}`: {}", path.display(), e), + setting: crate::settings::SettingVariant::Gpu, + } + }) + } + } + fn set_force_performance_related(&mut self) -> Result<(), Vec> { let mut errors = Vec::new(); // enable/disable downclock of GPU memory (to 400Mhz?) if self.slow_memory { POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(true); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT - .enforce_level() + .enforce_level(&self.sysfs_card) .unwrap_or_else(|mut e| errors.append(&mut e)); - usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8) - .unwrap_or_else(|e| { - errors.push(SettingError { - msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e), - setting: crate::settings::SettingVariant::Gpu, - }); - }); + self.set_slow_memory(self.slow_memory).unwrap_or_else(|e| errors.push(e)); } else if POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.needs_manual() { - usdpl_back::api::files::write_single(GPU_MEMORY_DOWNCLOCK_PATH, self.slow_memory as u8) - .unwrap_or_else(|e| { - errors.push(SettingError { - msg: format!("Failed to write to `{}`: {}", GPU_MEMORY_DOWNCLOCK_PATH, e), - setting: crate::settings::SettingVariant::Gpu, - }); - }); + self.set_slow_memory(self.slow_memory).unwrap_or_else(|e| errors.push(e)); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT.set_gpu(self.clock_limits.is_some()); POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT - .enforce_level() + .enforce_level(&self.sysfs_card) .unwrap_or_else(|mut e| errors.append(&mut e)); } self.set_clocks() @@ -181,11 +221,9 @@ impl Gpu { // commit changes (if no errors have already occured) if errors.is_empty() { if self.slow_memory || self.clock_limits.is_some() { - usdpl_back::api::files::write_single(GPU_CLOCK_LIMITS_PATH, "c\n").map_err(|e| { - vec![SettingError { - msg: format!("Failed to write `c` to `{}`: {}", GPU_CLOCK_LIMITS_PATH, e), - setting: crate::settings::SettingVariant::Gpu, - }] + self.set_confirm().map_err(|e| { + errors.push(e); + errors }) } else { Ok(()) @@ -200,12 +238,11 @@ impl Gpu { // set fast PPT if let Some(fast_ppt) = &self.fast_ppt { self.state.fast_ppt_set = true; - let fast_ppt_path = gpu_power_path(FAST_PPT); - usdpl_back::api::files::write_single(&fast_ppt_path, fast_ppt) + self.sysfs_hwmon.set(FAST_PPT_ATTRIBUTE, fast_ppt) .map_err(|e| SettingError { msg: format!( - "Failed to write `{}` to `{}`: {}", - fast_ppt, &fast_ppt_path, e + "Failed to write `{}` to `{:?}`: {}", + fast_ppt, FAST_PPT_ATTRIBUTE, e ), setting: crate::settings::SettingVariant::Gpu, }) @@ -215,12 +252,11 @@ impl Gpu { } else if self.state.fast_ppt_set { self.state.fast_ppt_set = false; let fast_ppt = self.limits.fast_ppt_default; - let fast_ppt_path = gpu_power_path(FAST_PPT); - usdpl_back::api::files::write_single(&fast_ppt_path, fast_ppt) + self.sysfs_hwmon.set(FAST_PPT_ATTRIBUTE, fast_ppt) .map_err(|e| SettingError { msg: format!( - "Failed to write `{}` to `{}`: {}", - fast_ppt, &fast_ppt_path, e + "Failed to write `{}` to `{:?}`: {}", + fast_ppt, FAST_PPT_ATTRIBUTE, e ), setting: crate::settings::SettingVariant::Gpu, }) @@ -231,12 +267,11 @@ impl Gpu { // set slow PPT if let Some(slow_ppt) = &self.slow_ppt { self.state.slow_ppt_set = true; - let slow_ppt_path = gpu_power_path(SLOW_PPT); - usdpl_back::api::files::write_single(&slow_ppt_path, slow_ppt) + self.sysfs_hwmon.set(SLOW_PPT_ATTRIBUTE, slow_ppt) .map_err(|e| SettingError { msg: format!( - "Failed to write `{}` to `{}`: {}", - slow_ppt, &slow_ppt_path, e + "Failed to write `{}` to `{:?}`: {}", + slow_ppt, SLOW_PPT_ATTRIBUTE, e ), setting: crate::settings::SettingVariant::Gpu, }) @@ -246,12 +281,11 @@ impl Gpu { } else if self.state.slow_ppt_set { self.state.slow_ppt_set = false; let slow_ppt = self.limits.slow_ppt_default; - let slow_ppt_path = gpu_power_path(SLOW_PPT); - usdpl_back::api::files::write_single(&slow_ppt_path, slow_ppt) + self.sysfs_hwmon.set(SLOW_PPT_ATTRIBUTE, slow_ppt) .map_err(|e| SettingError { msg: format!( - "Failed to write `{}` to `{}`: {}", - slow_ppt, &slow_ppt_path, e + "Failed to write `{}` to `{:?}`: {}", + slow_ppt, SLOW_PPT_ATTRIBUTE, e ), setting: crate::settings::SettingVariant::Gpu, }) @@ -276,12 +310,14 @@ impl Gpu { *slow_ppt = (*slow_ppt).clamp(self.limits.slow_ppt.min, self.limits.slow_ppt.max); } if let Some(clock_limits) = &mut self.clock_limits { - clock_limits.min = clock_limits - .min - .clamp(self.limits.clock_min.min, self.limits.clock_min.max); - clock_limits.max = clock_limits - .max - .clamp(self.limits.clock_max.min, self.limits.clock_max.max); + if let Some(min) = clock_limits.min { + clock_limits.min = + Some(min.clamp(self.limits.clock_min.min, self.limits.clock_min.max)); + } + if let Some(max) = clock_limits.max { + clock_limits.max = + Some(max.clamp(self.limits.clock_max.min, self.limits.clock_max.max)); + } } } @@ -299,6 +335,8 @@ impl Gpu { } else { crate::persist::DriverJson::SteamDeckAdvance }, + sysfs_card: Self::find_card_sysfs(None::<&'static str>), + sysfs_hwmon: Self::find_hwmon_sysfs(None::<&'static str>), } } } @@ -311,6 +349,7 @@ impl Into for Gpu { slow_ppt: self.slow_ppt, 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())) } } } @@ -392,8 +431,3 @@ impl TGpu for Gpu { self.driver_mode.clone() } } - -#[inline] -fn gpu_power_path(power_number: u8) -> String { - format!("/sys/class/hwmon/hwmon4/power{}_cap", power_number) -} diff --git a/backend/src/settings/steam_deck/mod.rs b/backend/src/settings/steam_deck/mod.rs index 49481f7..268fa90 100644 --- a/backend/src/settings/steam_deck/mod.rs +++ b/backend/src/settings/steam_deck/mod.rs @@ -8,6 +8,6 @@ mod util; pub use battery::Battery; pub use cpu::{Cpu, Cpus}; pub use gpu::Gpu; -pub(self) use power_dpm_force::POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT; +pub(self) use power_dpm_force::{POWER_DPM_FORCE_PERFORMANCE_LEVEL_MGMT, DPM_FORCE_LIMITS_ATTRIBUTE}; pub use util::flash_led; diff --git a/backend/src/settings/steam_deck/oc_limits.rs b/backend/src/settings/steam_deck/oc_limits.rs index d0cbeac..f229a0c 100644 --- a/backend/src/settings/steam_deck/oc_limits.rs +++ b/backend/src/settings/steam_deck/oc_limits.rs @@ -1,4 +1,4 @@ -use crate::settings::MinMax; +use crate::api::RangeLimit as MinMax; use serde::{Deserialize, Serialize}; const OC_LIMITS_FILEPATH: &str = "pt_oc.json"; @@ -67,6 +67,7 @@ impl OverclockLimits { #[derive(Serialize, Deserialize, Clone, Debug)] pub(super) struct BatteryLimits { pub charge_rate: MinMax, + pub extra_readouts: bool, } impl Default for BatteryLimits { @@ -76,6 +77,7 @@ impl Default for BatteryLimits { min: 250, max: 2500, }, + extra_readouts: false, } } } @@ -171,6 +173,7 @@ fn oc_limits_filepath() -> std::path::PathBuf { mod tests { use super::*; + #[cfg(not(feature = "dev_stuff"))] // this can fail due to reading from incompletely-written file otherwise #[test] fn load_pt_oc() { let mut file = std::fs::File::open("../pt_oc.json").unwrap(); diff --git a/backend/src/settings/steam_deck/power_dpm_force.rs b/backend/src/settings/steam_deck/power_dpm_force.rs index 06c820a..72404cc 100644 --- a/backend/src/settings/steam_deck/power_dpm_force.rs +++ b/backend/src/settings/steam_deck/power_dpm_force.rs @@ -5,6 +5,8 @@ use std::sync::atomic::{AtomicU64, Ordering}; +use sysfuss::{BasicEntityPath, SysEntityAttributesExt, SysAttribute}; + use crate::settings::SettingError; const DEFAULT_BITS: u64 = 0; @@ -19,7 +21,8 @@ pub struct PDFPLManager(AtomicU64); const GPU_BIT: usize = 1; const CPU_BITS_START: usize = 2; -const DPM_FORCE_LIMITS_PATH: &str = "/sys/class/drm/card0/device/power_dpm_force_performance_level"; +//const DPM_FORCE_LIMITS_PATH: &str = "/sys/class/drm/card0/device/power_dpm_force_performance_level"; +pub const DPM_FORCE_LIMITS_ATTRIBUTE: &str = "device/power_dpm_force_performance_level"; impl PDFPLManager { #[inline] @@ -56,49 +59,44 @@ impl PDFPLManager { self.set(DEFAULT_BITS); } - pub fn enforce_level(&self) -> Result<(), Vec> { + pub fn enforce_level(&self, entity: &BasicEntityPath) -> Result<(), Vec> { let needs = self.needs_manual(); let mut errors = Vec::new(); - let mode: String = usdpl_back::api::files::read_single(DPM_FORCE_LIMITS_PATH.to_owned()) + let path = DPM_FORCE_LIMITS_ATTRIBUTE.path(entity); + let mode: String = entity.attribute(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned()) .map_err(|e| { vec![SettingError { - msg: format!("Failed to read `{}`: {}", DPM_FORCE_LIMITS_PATH, e), + msg: format!("Failed to read `{}`: {}", path.display(), e), setting: crate::settings::SettingVariant::General, }] })?; if mode != "manual" && needs { - log::info!("Setting `{}` to manual", DPM_FORCE_LIMITS_PATH); + log::info!("Setting `{}` to manual", path.display()); // set manual control - usdpl_back::api::files::write_single(DPM_FORCE_LIMITS_PATH, "manual") + entity.set(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned(), "manual") .map_err(|e| { errors.push(SettingError { - msg: format!( - "Failed to write `manual` to `{}`: {}", - DPM_FORCE_LIMITS_PATH, e - ), + msg: format!("Failed to write `manual` to `{}`: {}", path.display(), e), setting: crate::settings::SettingVariant::General, }) }) .unwrap_or(()); } else if mode != "auto" && !needs { - log::info!("Setting `{}` to auto", DPM_FORCE_LIMITS_PATH); + log::info!("Setting `{}` to auto", path.display()); // unset manual control - usdpl_back::api::files::write_single(DPM_FORCE_LIMITS_PATH, "auto") + entity.set(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned(), "auto") .map_err(|e| { errors.push(SettingError { - msg: format!( - "Failed to write `auto` to `{}`: {}", - DPM_FORCE_LIMITS_PATH, e - ), + msg: format!("Failed to write `auto` to `{}`: {}", path.display(), e), setting: crate::settings::SettingVariant::General, }) }) .unwrap_or(()); } if let Ok(mode_now) = - usdpl_back::api::files::read_single::<_, String, _>(DPM_FORCE_LIMITS_PATH.to_owned()) + entity.attribute::(DPM_FORCE_LIMITS_ATTRIBUTE.to_owned()) { - log::debug!("Mode for `{}` is now `{}`", DPM_FORCE_LIMITS_PATH, mode_now); + log::debug!("Mode for `{}` is now `{}`", path.display(), mode_now); } else { log::debug!("Error getting new mode for debugging purposes"); } diff --git a/backend/src/settings/steam_deck/util.rs b/backend/src/settings/steam_deck/util.rs index 525d414..52eb3e9 100644 --- a/backend/src/settings/steam_deck/util.rs +++ b/backend/src/settings/steam_deck/util.rs @@ -8,6 +8,15 @@ 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"; + +pub fn card_also_has(card: &dyn sysfuss::SysEntity, extensions: &'static [&'static str]) -> bool { + extensions.iter() + .all(|ext| card.as_ref().join(ext).exists()) +} + #[inline] fn write2(p0: u8, p1: u8) -> Result { write_to(0x6c, 0x81)?; diff --git a/backend/src/settings/traits.rs b/backend/src/settings/traits.rs index 1e77c4d..4e96882 100644 --- a/backend/src/settings/traits.rs +++ b/backend/src/settings/traits.rs @@ -104,6 +104,8 @@ pub trait TGeneral: OnSet + OnResume + OnPowerEvent + Debug + Send { fn name(&mut self, name: String); fn provider(&self) -> crate::persist::DriverJson; + + fn on_event(&self) -> &'_ crate::persist::OnEventJson; } pub trait TBattery: OnSet + OnResume + OnPowerEvent + Debug + Send { @@ -127,6 +129,8 @@ pub trait TBattery: OnSet + OnResume + OnPowerEvent + Debug + Send { fn read_current_now(&self) -> Option; + fn read_charge_power(&self) -> Option; + fn charge_limit(&mut self, limit: Option); fn get_charge_limit(&self) -> Option; diff --git a/backend/src/settings/unknown/battery.rs b/backend/src/settings/unknown/battery.rs index c4ba71a..ab76959 100644 --- a/backend/src/settings/unknown/battery.rs +++ b/backend/src/settings/unknown/battery.rs @@ -14,6 +14,7 @@ impl Into for Battery { charge_rate: None, charge_mode: None, events: Vec::default(), + root: None, } } } @@ -75,6 +76,10 @@ impl TBattery for Battery { None } + fn read_charge_power(&self) -> Option { + None + } + fn charge_limit(&mut self, _limit: Option) {} fn get_charge_limit(&self) -> Option { diff --git a/backend/src/settings/unknown/cpu.rs b/backend/src/settings/unknown/cpu.rs index bc5f1c4..c3985cf 100644 --- a/backend/src/settings/unknown/cpu.rs +++ b/backend/src/settings/unknown/cpu.rs @@ -180,6 +180,7 @@ pub struct Cpu { pub governor: String, index: usize, state: crate::state::steam_deck::Cpu, + root: std::path::PathBuf, } impl Cpu { @@ -191,12 +192,14 @@ impl Cpu { governor: other.governor, index: i, state: crate::state::steam_deck::Cpu::default(), + root: other.root.unwrap_or_else(|| "/".to_owned()).into(), }, _ => Self { online: other.online, governor: other.governor, index: i, state: crate::state::steam_deck::Cpu::default(), + root: other.root.unwrap_or_else(|| "/".to_owned()).into(), }, } } @@ -243,6 +246,7 @@ impl Cpu { .unwrap_or("schedutil".to_owned()), index: cpu_index, state: crate::state::steam_deck::Cpu::default(), + root: "/".into() } } @@ -263,6 +267,7 @@ impl Into for Cpu { online: self.online, clock_limits: None, governor: self.governor, + root: self.root.to_str().map(|s| s.to_owned()), } } } diff --git a/backend/src/settings/unknown/gpu.rs b/backend/src/settings/unknown/gpu.rs index 150fad7..0b4b73e 100644 --- a/backend/src/settings/unknown/gpu.rs +++ b/backend/src/settings/unknown/gpu.rs @@ -29,6 +29,7 @@ impl Into for Gpu { slow_ppt: None, clock_limits: None, slow_memory: false, + root: None, } } } diff --git a/backend/src/settings/util.rs b/backend/src/settings/util.rs index 725de0a..cede8f6 100644 --- a/backend/src/settings/util.rs +++ b/backend/src/settings/util.rs @@ -6,6 +6,23 @@ pub fn guess_smt(cpus: &Vec) -> bool { guess } +pub fn root_or_default_sysfs(root: Option>) -> sysfuss::SysPath { + if let Some(root) = root { + sysfuss::SysPath::path(root) + } else { + sysfuss::SysPath::default() + } +} + +pub fn always_satisfied<'a, X>(_: &'a X) -> bool { + true +} + +pub const CARD_NEEDS: &[&'static str] = &[ + "dev", + "uevent" +]; + #[cfg(test)] mod test { use super::*; diff --git a/backend/src/utility.rs b/backend/src/utility.rs index 75430f1..742cd32 100644 --- a/backend/src/utility.rs +++ b/backend/src/utility.rs @@ -76,6 +76,9 @@ fn version_filepath() -> std::path::PathBuf { pub fn save_version_file() -> std::io::Result { let path = version_filepath(); + if let Some(parent_dir) = path.parent() { + std::fs::create_dir_all(parent_dir)?; + } std::fs::File::create(path)?.write(crate::consts::PACKAGE_VERSION.as_bytes()) } diff --git a/package.json b/package.json index 0d286ae..c49299a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "PowerTools", - "version": "1.3.1", + "version": "1.4.0", "description": "Power tweaks for power users", "scripts": { "build": "shx rm -rf dist && rollup -c", @@ -9,7 +9,7 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/NGnius/PowerTools.git" + "url": "git+https://git.ngni.us/NG-SD-Plugins/PowerTools.git" }, "keywords": [ "plugin", @@ -21,9 +21,9 @@ "author": "NGnius (Graham) ", "license": "GPL-3.0", "bugs": { - "url": "https://github.com/NGnius/PowerTools/issues" + "url": "https://git.ngni.us/NG-SD-Plugins/PowerTools/issues" }, - "homepage": "https://github.com/NGnius/PowerTools#readme", + "homepage": "https://git.ngni.us/NG-SD-Plugins/PowerTools#readme", "devDependencies": { "@rollup/plugin-commonjs": "^21.1.0", "@rollup/plugin-json": "^4.1.0", @@ -35,12 +35,12 @@ "rollup": "^2.79.1", "rollup-plugin-import-assets": "^1.1.1", "shx": "^0.3.4", - "tslib": "^2.5.0", + "tslib": "^2.5.3", "typescript": "^4.9.5" }, "dependencies": { - "decky-frontend-lib": "~3.20.7", - "react-icons": "^4.8.0", + "decky-frontend-lib": "~3.21.1", + "react-icons": "^4.9.0", "usdpl-front": "file:src/usdpl_front" } } diff --git a/plugin.json b/plugin.json index 4fe6848..97a7714 100644 --- a/plugin.json +++ b/plugin.json @@ -6,6 +6,6 @@ "discord_id": "106537989684887552", "description": "Power tweaks for power users", "tags": [ "utility", "power-management", "root" ], - "image": "https://raw.githubusercontent.com/NGnius/PowerTools/main/assets/thumbnail.png" + "image": "https://git.ngni.us/NG-SD-Plugins/PowerTools/raw/branch/main/assets/thumbnail.png" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6224b02..c815130 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,12 +1,16 @@ -lockfileVersion: '6.0' +lockfileVersion: '6.1' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false dependencies: decky-frontend-lib: - specifier: ~3.20.7 - version: 3.20.7 + specifier: ~3.21.1 + version: 3.21.1 react-icons: - specifier: ^4.8.0 - version: 4.8.0(react@18.2.0) + specifier: ^4.9.0 + version: 4.9.0(react@18.2.0) usdpl-front: specifier: file:src/usdpl_front version: file:src/usdpl_front @@ -26,7 +30,7 @@ devDependencies: version: 4.0.0(rollup@2.79.1) '@rollup/plugin-typescript': specifier: ^8.5.0 - version: 8.5.0(rollup@2.79.1)(tslib@2.5.0)(typescript@4.9.5) + version: 8.5.0(rollup@2.79.1)(tslib@2.5.3)(typescript@4.9.5) '@types/react': specifier: 16.14.0 version: 16.14.0 @@ -43,21 +47,21 @@ devDependencies: specifier: ^0.3.4 version: 0.3.4 tslib: - specifier: ^2.5.0 - version: 2.5.0 + specifier: ^2.5.3 + version: 2.5.3 typescript: specifier: ^4.9.5 version: 4.9.5 packages: - /@jridgewell/gen-mapping@0.3.2: - resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} engines: {node: '>=6.0.0'} dependencies: '@jridgewell/set-array': 1.1.2 - '@jridgewell/sourcemap-codec': 1.4.14 - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.18 dev: true /@jridgewell/resolve-uri@3.1.0: @@ -70,19 +74,23 @@ packages: engines: {node: '>=6.0.0'} dev: true - /@jridgewell/source-map@0.3.2: - resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==} + /@jridgewell/source-map@0.3.3: + resolution: {integrity: sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==} dependencies: - '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.18 dev: true /@jridgewell/sourcemap-codec@1.4.14: resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} dev: true - /@jridgewell/trace-mapping@0.3.17: - resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==} + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.18: + resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} dependencies: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 @@ -138,7 +146,7 @@ packages: rollup: 2.79.1 dev: true - /@rollup/plugin-typescript@8.5.0(rollup@2.79.1)(tslib@2.5.0)(typescript@4.9.5): + /@rollup/plugin-typescript@8.5.0(rollup@2.79.1)(tslib@2.5.3)(typescript@4.9.5): resolution: {integrity: sha512-wMv1/scv0m/rXx21wD2IsBbJFba8wGF3ErJIr6IKRfRj49S85Lszbxb4DCo8iILpluTjk2GAAu9CoZt4G3ppgQ==} engines: {node: '>=8.0.0'} peerDependencies: @@ -152,7 +160,7 @@ packages: '@rollup/pluginutils': 3.1.0(rollup@2.79.1) resolve: 1.22.2 rollup: 2.79.1 - tslib: 2.5.0 + tslib: 2.5.3 typescript: 4.9.5 dev: true @@ -171,35 +179,31 @@ packages: /@types/eslint-scope@3.7.4: resolution: {integrity: sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==} dependencies: - '@types/eslint': 8.37.0 - '@types/estree': 0.0.51 + '@types/eslint': 8.40.2 + '@types/estree': 1.0.1 dev: true - /@types/eslint@8.37.0: - resolution: {integrity: sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==} + /@types/eslint@8.40.2: + resolution: {integrity: sha512-PRVjQ4Eh9z9pmmtaq8nTjZjQwKFk7YIHIud3lRoKRBgUQjgjRmoGxxGEPXQkF+lH7QkHJRNr5F4aBgYCW0lqpQ==} dependencies: - '@types/estree': 0.0.51 - '@types/json-schema': 7.0.11 + '@types/estree': 1.0.1 + '@types/json-schema': 7.0.12 dev: true /@types/estree@0.0.39: resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} dev: true - /@types/estree@0.0.51: - resolution: {integrity: sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==} + /@types/estree@1.0.1: + resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} dev: true - /@types/estree@1.0.0: - resolution: {integrity: sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ==} + /@types/json-schema@7.0.12: + resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} dev: true - /@types/json-schema@7.0.11: - resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} - dev: true - - /@types/node@18.15.11: - resolution: {integrity: sha512-E5Kwq2n4SbMzQOn6wnmBjuK9ouqlURrcZDVfbo9ftDDTFt3nk7ZKK4GMOzoYgnpQJKcxwQw+lGaBvvlMo0qN/Q==} + /@types/node@20.3.1: + resolution: {integrity: sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg==} dev: true /@types/prop-types@15.7.5: @@ -216,15 +220,15 @@ packages: /@types/resolve@1.17.1: resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} dependencies: - '@types/node': 18.15.11 + '@types/node': 20.3.1 dev: true /@types/webpack@5.28.1: resolution: {integrity: sha512-qw1MqGZclCoBrpiSe/hokSgQM/su8Ocpl3L/YHE0L6moyaypg4+5F7Uzq7NgaPKPxUxUbQ4fLPLpDWdR27bCZw==} dependencies: - '@types/node': 18.15.11 + '@types/node': 20.3.1 tapable: 2.2.1 - webpack: 5.78.0 + webpack: 5.87.0 transitivePeerDependencies: - '@swc/core' - esbuild @@ -232,109 +236,109 @@ packages: - webpack-cli dev: true - /@webassemblyjs/ast@1.11.1: - resolution: {integrity: sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==} + /@webassemblyjs/ast@1.11.6: + resolution: {integrity: sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==} dependencies: - '@webassemblyjs/helper-numbers': 1.11.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.1 + '@webassemblyjs/helper-numbers': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 dev: true - /@webassemblyjs/floating-point-hex-parser@1.11.1: - resolution: {integrity: sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==} + /@webassemblyjs/floating-point-hex-parser@1.11.6: + resolution: {integrity: sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==} dev: true - /@webassemblyjs/helper-api-error@1.11.1: - resolution: {integrity: sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==} + /@webassemblyjs/helper-api-error@1.11.6: + resolution: {integrity: sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==} dev: true - /@webassemblyjs/helper-buffer@1.11.1: - resolution: {integrity: sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==} + /@webassemblyjs/helper-buffer@1.11.6: + resolution: {integrity: sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==} dev: true - /@webassemblyjs/helper-numbers@1.11.1: - resolution: {integrity: sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==} + /@webassemblyjs/helper-numbers@1.11.6: + resolution: {integrity: sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==} dependencies: - '@webassemblyjs/floating-point-hex-parser': 1.11.1 - '@webassemblyjs/helper-api-error': 1.11.1 + '@webassemblyjs/floating-point-hex-parser': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 '@xtuc/long': 4.2.2 dev: true - /@webassemblyjs/helper-wasm-bytecode@1.11.1: - resolution: {integrity: sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==} + /@webassemblyjs/helper-wasm-bytecode@1.11.6: + resolution: {integrity: sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==} dev: true - /@webassemblyjs/helper-wasm-section@1.11.1: - resolution: {integrity: sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==} + /@webassemblyjs/helper-wasm-section@1.11.6: + resolution: {integrity: sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==} dependencies: - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/helper-buffer': 1.11.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.1 - '@webassemblyjs/wasm-gen': 1.11.1 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 dev: true - /@webassemblyjs/ieee754@1.11.1: - resolution: {integrity: sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==} + /@webassemblyjs/ieee754@1.11.6: + resolution: {integrity: sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==} dependencies: '@xtuc/ieee754': 1.2.0 dev: true - /@webassemblyjs/leb128@1.11.1: - resolution: {integrity: sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==} + /@webassemblyjs/leb128@1.11.6: + resolution: {integrity: sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==} dependencies: '@xtuc/long': 4.2.2 dev: true - /@webassemblyjs/utf8@1.11.1: - resolution: {integrity: sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==} + /@webassemblyjs/utf8@1.11.6: + resolution: {integrity: sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==} dev: true - /@webassemblyjs/wasm-edit@1.11.1: - resolution: {integrity: sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==} + /@webassemblyjs/wasm-edit@1.11.6: + resolution: {integrity: sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==} dependencies: - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/helper-buffer': 1.11.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.1 - '@webassemblyjs/helper-wasm-section': 1.11.1 - '@webassemblyjs/wasm-gen': 1.11.1 - '@webassemblyjs/wasm-opt': 1.11.1 - '@webassemblyjs/wasm-parser': 1.11.1 - '@webassemblyjs/wast-printer': 1.11.1 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/helper-wasm-section': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-opt': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + '@webassemblyjs/wast-printer': 1.11.6 dev: true - /@webassemblyjs/wasm-gen@1.11.1: - resolution: {integrity: sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==} + /@webassemblyjs/wasm-gen@1.11.6: + resolution: {integrity: sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==} dependencies: - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.1 - '@webassemblyjs/ieee754': 1.11.1 - '@webassemblyjs/leb128': 1.11.1 - '@webassemblyjs/utf8': 1.11.1 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 dev: true - /@webassemblyjs/wasm-opt@1.11.1: - resolution: {integrity: sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==} + /@webassemblyjs/wasm-opt@1.11.6: + resolution: {integrity: sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==} dependencies: - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/helper-buffer': 1.11.1 - '@webassemblyjs/wasm-gen': 1.11.1 - '@webassemblyjs/wasm-parser': 1.11.1 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-buffer': 1.11.6 + '@webassemblyjs/wasm-gen': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 dev: true - /@webassemblyjs/wasm-parser@1.11.1: - resolution: {integrity: sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==} + /@webassemblyjs/wasm-parser@1.11.6: + resolution: {integrity: sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==} dependencies: - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/helper-api-error': 1.11.1 - '@webassemblyjs/helper-wasm-bytecode': 1.11.1 - '@webassemblyjs/ieee754': 1.11.1 - '@webassemblyjs/leb128': 1.11.1 - '@webassemblyjs/utf8': 1.11.1 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/helper-api-error': 1.11.6 + '@webassemblyjs/helper-wasm-bytecode': 1.11.6 + '@webassemblyjs/ieee754': 1.11.6 + '@webassemblyjs/leb128': 1.11.6 + '@webassemblyjs/utf8': 1.11.6 dev: true - /@webassemblyjs/wast-printer@1.11.1: - resolution: {integrity: sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==} + /@webassemblyjs/wast-printer@1.11.6: + resolution: {integrity: sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==} dependencies: - '@webassemblyjs/ast': 1.11.1 + '@webassemblyjs/ast': 1.11.6 '@xtuc/long': 4.2.2 dev: true @@ -346,16 +350,16 @@ packages: resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} dev: true - /acorn-import-assertions@1.8.0(acorn@8.8.2): - resolution: {integrity: sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==} + /acorn-import-assertions@1.9.0(acorn@8.9.0): + resolution: {integrity: sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==} peerDependencies: acorn: ^8 dependencies: - acorn: 8.8.2 + acorn: 8.9.0 dev: true - /acorn@8.8.2: - resolution: {integrity: sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==} + /acorn@8.9.0: + resolution: {integrity: sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==} engines: {node: '>=0.4.0'} hasBin: true dev: true @@ -388,15 +392,15 @@ packages: concat-map: 0.0.1 dev: true - /browserslist@4.21.5: - resolution: {integrity: sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==} + /browserslist@4.21.9: + resolution: {integrity: sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true dependencies: - caniuse-lite: 1.0.30001474 - electron-to-chromium: 1.4.353 - node-releases: 2.0.10 - update-browserslist-db: 1.0.10(browserslist@4.21.5) + caniuse-lite: 1.0.30001503 + electron-to-chromium: 1.4.433 + node-releases: 2.0.12 + update-browserslist-db: 1.0.11(browserslist@4.21.9) dev: true /buffer-from@1.1.2: @@ -408,8 +412,8 @@ packages: engines: {node: '>=6'} dev: true - /caniuse-lite@1.0.30001474: - resolution: {integrity: sha512-iaIZ8gVrWfemh5DG3T9/YqarVZoYf0r188IjaGwx68j4Pf0SGY6CQkmJUIE+NZHkkecQGohzXmBGEwWDr9aM3Q==} + /caniuse-lite@1.0.30001503: + resolution: {integrity: sha512-Sf9NiF+wZxPfzv8Z3iS0rXM1Do+iOy2Lxvib38glFX+08TCYYYGR5fRJXk4d77C4AYwhUjgYgMsMudbh2TqCKw==} dev: true /chrome-trace-event@1.0.3: @@ -433,8 +437,8 @@ packages: resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} dev: true - /decky-frontend-lib@3.20.7: - resolution: {integrity: sha512-Zwwbo50cqpTbCfSCZaqITgTRvWs7pK9KO1A+Oo2sCC/DqOfyUtEH5niNPid4Qxu+yh4lsbEjTurJk1nCfd+nZw==} + /decky-frontend-lib@3.21.1: + resolution: {integrity: sha512-30605ET9qqZ6St6I9WmMmLGgSrTIdMwo7xy85+lRaF1miUd2icOGEJjwnbVcZDdkal+1fJ3tNEDXlchVfG4TrA==} dev: false /deepmerge@4.3.1: @@ -442,20 +446,20 @@ packages: engines: {node: '>=0.10.0'} dev: true - /electron-to-chromium@1.4.353: - resolution: {integrity: sha512-IdJVpMHJoBT/nn0GQ02wPfbhogDVpd1ud95lP//FTf5l35wzxKJwibB4HBdY7Q+xKPA1nkZ0UDLOMyRj5U5IAQ==} + /electron-to-chromium@1.4.433: + resolution: {integrity: sha512-MGO1k0w1RgrfdbLVwmXcDhHHuxCn2qRgR7dYsJvWFKDttvYPx6FNzCGG0c/fBBvzK2LDh3UV7Tt9awnHnvAAUQ==} dev: true - /enhanced-resolve@5.12.0: - resolution: {integrity: sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==} + /enhanced-resolve@5.15.0: + resolution: {integrity: sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==} engines: {node: '>=10.13.0'} dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 dev: true - /es-module-lexer@0.9.3: - resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} + /es-module-lexer@1.3.0: + resolution: {integrity: sha512-vZK7T0N2CBmBOixhmjdqx2gWVbFZ4DXZ/NyRMZVlJXPa7CyFS+/a4QQsDGDQy9ZfEzxFuNEsMLeQJnKP2p5/JA==} dev: true /escalade@3.1.1: @@ -583,8 +587,8 @@ packages: builtin-modules: 3.3.0 dev: true - /is-core-module@2.11.0: - resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==} + /is-core-module@2.12.1: + resolution: {integrity: sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==} dependencies: has: 1.0.3 dev: true @@ -596,14 +600,14 @@ packages: /is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} dependencies: - '@types/estree': 1.0.0 + '@types/estree': 1.0.1 dev: true /jest-worker@27.5.1: resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/node': 18.15.11 + '@types/node': 20.3.1 merge-stream: 2.0.0 supports-color: 8.1.1 dev: true @@ -668,8 +672,8 @@ packages: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} dev: true - /node-releases@2.0.10: - resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} + /node-releases@2.0.12: + resolution: {integrity: sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==} dev: true /once@1.4.0: @@ -707,8 +711,8 @@ packages: safe-buffer: 5.2.1 dev: true - /react-icons@4.8.0(react@18.2.0): - resolution: {integrity: sha512-N6+kOLcihDiAnj5Czu637waJqSnwlMNROzVZMhfX68V/9bu9qHaMIJC4UdozWoOk57gahFCNHwVvWzm0MTzRjg==} + /react-icons@4.9.0(react@18.2.0): + resolution: {integrity: sha512-ijUnFr//ycebOqujtqtV9PFS7JjhWg0QU6ykURVHuL4cbofvRCf3f6GMn9+fBktEFQOIVZnuAYLZdiyadRQRFg==} peerDependencies: react: '*' dependencies: @@ -733,7 +737,7 @@ packages: resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} hasBin: true dependencies: - is-core-module: 2.11.0 + is-core-module: 2.12.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 dev: true @@ -766,11 +770,11 @@ packages: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} dev: true - /schema-utils@3.1.1: - resolution: {integrity: sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==} + /schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} engines: {node: '>= 10.13.0'} dependencies: - '@types/json-schema': 7.0.11 + '@types/json-schema': 7.0.12 ajv: 6.12.6 ajv-keywords: 3.5.2(ajv@6.12.6) dev: true @@ -834,8 +838,8 @@ packages: engines: {node: '>=6'} dev: true - /terser-webpack-plugin@5.3.7(webpack@5.78.0): - resolution: {integrity: sha512-AfKwIktyP7Cu50xNjXF/6Qb5lBNzYaWpU6YfoX3uZicTx0zTy0stDDCsvjDapKsSDvOeWo5MEq4TmdBy2cNoHw==} + /terser-webpack-plugin@5.3.9(webpack@5.87.0): + resolution: {integrity: sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==} engines: {node: '>= 10.13.0'} peerDependencies: '@swc/core': '*' @@ -850,27 +854,27 @@ packages: uglify-js: optional: true dependencies: - '@jridgewell/trace-mapping': 0.3.17 + '@jridgewell/trace-mapping': 0.3.18 jest-worker: 27.5.1 - schema-utils: 3.1.1 + schema-utils: 3.3.0 serialize-javascript: 6.0.1 - terser: 5.16.8 - webpack: 5.78.0 + terser: 5.18.0 + webpack: 5.87.0 dev: true - /terser@5.16.8: - resolution: {integrity: sha512-QI5g1E/ef7d+PsDifb+a6nnVgC4F22Bg6T0xrBrz6iloVB4PUkkunp6V8nzoOOZJIzjWVdAGqCdlKlhLq/TbIA==} + /terser@5.18.0: + resolution: {integrity: sha512-pdL757Ig5a0I+owA42l6tIuEycRuM7FPY4n62h44mRLRfnOxJkkOHd6i89dOpwZlpF6JXBwaAHF6yWzFrt+QyA==} engines: {node: '>=10'} hasBin: true dependencies: - '@jridgewell/source-map': 0.3.2 - acorn: 8.8.2 + '@jridgewell/source-map': 0.3.3 + acorn: 8.9.0 commander: 2.20.3 source-map-support: 0.5.21 dev: true - /tslib@2.5.0: - resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==} + /tslib@2.5.3: + resolution: {integrity: sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==} dev: true /typescript@4.9.5: @@ -879,13 +883,13 @@ packages: hasBin: true dev: true - /update-browserslist-db@1.0.10(browserslist@4.21.5): - resolution: {integrity: sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==} + /update-browserslist-db@1.0.11(browserslist@4.21.9): + resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} hasBin: true peerDependencies: browserslist: '>= 4.21.0' dependencies: - browserslist: 4.21.5 + browserslist: 4.21.9 escalade: 3.1.1 picocolors: 1.0.0 dev: true @@ -913,8 +917,8 @@ packages: engines: {node: '>=10.13.0'} dev: true - /webpack@5.78.0: - resolution: {integrity: sha512-gT5DP72KInmE/3azEaQrISjTvLYlSM0j1Ezhht/KLVkrqtv10JoP/RXhwmX/frrutOPuSq3o5Vq0ehR/4Vmd1g==} + /webpack@5.87.0: + resolution: {integrity: sha512-GOu1tNbQ7p1bDEoFRs2YPcfyGs8xq52yyPBZ3m2VGnXGtV9MxjrkABHm4V9Ia280OefsSLzvbVoXcfLxjKY/Iw==} engines: {node: '>=10.13.0'} hasBin: true peerDependencies: @@ -924,16 +928,16 @@ packages: optional: true dependencies: '@types/eslint-scope': 3.7.4 - '@types/estree': 0.0.51 - '@webassemblyjs/ast': 1.11.1 - '@webassemblyjs/wasm-edit': 1.11.1 - '@webassemblyjs/wasm-parser': 1.11.1 - acorn: 8.8.2 - acorn-import-assertions: 1.8.0(acorn@8.8.2) - browserslist: 4.21.5 + '@types/estree': 1.0.1 + '@webassemblyjs/ast': 1.11.6 + '@webassemblyjs/wasm-edit': 1.11.6 + '@webassemblyjs/wasm-parser': 1.11.6 + acorn: 8.9.0 + acorn-import-assertions: 1.9.0(acorn@8.9.0) + browserslist: 4.21.9 chrome-trace-event: 1.0.3 - enhanced-resolve: 5.12.0 - es-module-lexer: 0.9.3 + enhanced-resolve: 5.15.0 + es-module-lexer: 1.3.0 eslint-scope: 5.1.1 events: 3.3.0 glob-to-regexp: 0.4.1 @@ -942,9 +946,9 @@ packages: loader-runner: 4.3.0 mime-types: 2.1.35 neo-async: 2.6.2 - schema-utils: 3.1.1 + schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.7(webpack@5.78.0) + terser-webpack-plugin: 5.3.9(webpack@5.87.0) watchpack: 2.4.0 webpack-sources: 3.2.3 transitivePeerDependencies: diff --git a/pt_oc.json b/pt_oc.json index 79d3c37..4ebd7c1 100644 --- a/pt_oc.json +++ b/pt_oc.json @@ -3,7 +3,8 @@ "charge_rate": { "min": 250, "max": 2500 - } + }, + "extra_readouts": false }, "cpus": { "cpus": [ diff --git a/src/backend.ts b/src/backend.ts index 8bc6761..07fe9d8 100644 --- a/src/backend.ts +++ b/src/backend.ts @@ -117,6 +117,10 @@ export async function getBatteryChargeDesign(): Promise { return (await call_backend("BATTERY_charge_design", []))[0]; } +export async function getBatteryChargePower(): Promise { + return (await call_backend("BATTERY_charge_power", []))[0]; +} + export async function getBatteryChargeRate(): Promise { return (await call_backend("BATTERY_get_charge_rate", []))[0]; } @@ -302,3 +306,41 @@ export async function onPluggedIn(): Promise { export async function onUnplugged(): Promise { return (await call_backend("GENERAL_on_unplugged", []))[0]; } + +export type Message = { + /// Message identifier + id: number | null, + /// Message title + title: string, + /// Message content + body: string, + /// Link for further information + url: string | null, +}; + +export async function getMessages(since: number | null): Promise { + return (await call_backend("MESSAGE_get", [since])); +} + +export async function dismissMessage(id: number): Promise { + return (await call_backend("MESSAGE_dismiss", [id]))[0]; +} + +export type Periodicals = { + battery_current: number | null, + battery_charge_now: number | null, + battery_charge_full: number | null, + battery_charge_power: number | null, + settings_path: string | null, +}; + +export async function getPeriodicals(): Promise { + const result: any[] = await call_backend("GENERAL_get_periodicals", []); + return { + battery_current: result[0], + battery_charge_now: result[1], + battery_charge_full: result[2], + battery_charge_power: result[3], + settings_path: result[4], + }; +} diff --git a/src/components/battery.tsx b/src/components/battery.tsx index 14b86ee..0199e1b 100644 --- a/src/components/battery.tsx +++ b/src/components/battery.tsx @@ -20,6 +20,7 @@ import { CHARGE_MODE_BATT, CURRENT_BATT, CHARGE_LIMIT_BATT, + CHARGE_POWER_BATT, } from "../consts"; import { set_value, get_value} from "usdpl-front"; @@ -54,12 +55,18 @@ export class Battery extends Component { {get_value(CHARGE_FULL_BATT).toFixed(1)} Wh ({(100 * get_value(CHARGE_FULL_BATT) / get_value(CHARGE_DESIGN_BATT)).toFixed(1)}%) } - + {get_value(CHARGE_POWER_BATT) != null && get_value(CHARGE_POWER_BATT) > 0 && + + {get_value(CHARGE_POWER_BATT).toFixed(2)} W + + } + {get_value(CURRENT_BATT) != null && {get_value(CURRENT_BATT)} mA - + } {(get_value(LIMITS_INFO) as backend.SettingsLimits).battery.charge_current != null && { + constructor(props: backend.IdcProps) { + super(props); + this.state = { + reloadThingy: "/shrug", + }; + } + + render() { + const reloadGUI = (x: string) => this.setState({reloadThingy: x}); + const messages: backend.Message[] = get_value(MESSAGE_LIST) as backend.Message[]; + if (messages.length != 0) { + const message = messages[0]; + return ( +
+ {message.title} +
+ + { if (message.url) { Navigation.NavigateToExternalWeb(message.url); } }}> + {message.body} + + { + if (message.id) { + backend.dismissMessage(message.id); + } + messages.shift(); + set_value(MESSAGE_LIST, messages); + reloadGUI("MessageDismissed"); + }} + > + {tr("Dismiss")} + + +
+ ) + } else { + return + } + } +} diff --git a/src/consts.ts b/src/consts.ts index 749bbe8..4364cb6 100644 --- a/src/consts.ts +++ b/src/consts.ts @@ -10,6 +10,7 @@ export const CHARGE_LIMIT_BATT = "BATTERY_charge_limit"; export const CHARGE_NOW_BATT = "BATTERY_charge_now"; export const CHARGE_FULL_BATT = "BATTERY_charge_full"; export const CHARGE_DESIGN_BATT = "BATTERY_charge_design"; +export const CHARGE_POWER_BATT = "BATTERY_charge_power"; //export const TOTAL_CPUS = "CPUs_total"; export const ONLINE_CPUS = "CPUs_online"; @@ -30,3 +31,8 @@ export const PERSISTENT_GEN = "GENERAL_persistent"; export const NAME_GEN = "GENERAL_name"; export const PATH_GEN = "GENERAL_path"; +export const MESSAGE_LIST = "MESSAGE_messages"; + +export const PERIODICAL_BACKEND_PERIOD = 5000; // milliseconds +export const AUTOMATIC_REAPPLY_WAIT = 2000; // milliseconds + diff --git a/src/index.tsx b/src/index.tsx index 5a7daaa..df1407d 100755 --- a/src/index.tsx +++ b/src/index.tsx @@ -39,6 +39,7 @@ import { CHARGE_NOW_BATT, CHARGE_FULL_BATT, CHARGE_DESIGN_BATT, + CHARGE_POWER_BATT, ONLINE_CPUS, ONLINE_STATUS_CPUS, @@ -57,16 +58,23 @@ import { PERSISTENT_GEN, NAME_GEN, PATH_GEN, + + MESSAGE_LIST, + + PERIODICAL_BACKEND_PERIOD, + AUTOMATIC_REAPPLY_WAIT, } from "./consts"; import { set_value, get_value } from "usdpl-front"; import { Debug } from "./components/debug"; import { Gpu } from "./components/gpu"; import { Battery } from "./components/battery"; import { Cpus } from "./components/cpus"; +import { DevMessages } from "./components/message"; var periodicHook: NodeJS.Timer | null = null; var lifetimeHook: any = null; var startHook: any = null; +var endHook: any = null; var usdplReady = false; type MinMax = { @@ -113,6 +121,7 @@ const reload = function() { backend.resolve(backend.getBatteryChargeNow(), (rate: number) => { set_value(CHARGE_NOW_BATT, rate) }); backend.resolve(backend.getBatteryChargeFull(), (rate: number) => { set_value(CHARGE_FULL_BATT, rate) }); backend.resolve(backend.getBatteryChargeDesign(), (rate: number) => { set_value(CHARGE_DESIGN_BATT, rate) }); + backend.resolve(backend.getBatteryChargePower(), (rate: number) => { set_value(CHARGE_POWER_BATT, rate) }); //backend.resolve(backend.getCpuCount(), (count: number) => { set_value(TOTAL_CPUS, count)}); backend.resolve(backend.getCpusOnline(), (statii: boolean[]) => { @@ -150,6 +159,8 @@ const reload = function() { backend.resolve(backend.getInfo(), (info: string) => { set_value(BACKEND_INFO, info) }); backend.resolve(backend.getDriverProviderName("gpu"), (driver: string) => { set_value(DRIVER_INFO, driver) }); + + backend.resolve(backend.getMessages(null), (messages: backend.Message[]) => { set_value(MESSAGE_LIST, messages) }); }; // init USDPL WASM and connection to back-end @@ -185,22 +196,30 @@ const reload = function() { ); }); + //@ts-ignore + endHook = SteamClient.Apps.RegisterForGameActionEnd((actionType) => { + backend.log(backend.LogLevel.Info, "RegisterForGameActionEnd callback(" + actionType + ")"); + setTimeout(() => backend.forceApplySettings(), AUTOMATIC_REAPPLY_WAIT); + }); + backend.log(backend.LogLevel.Debug, "Registered PowerTools callbacks, hello!"); })(); const periodicals = function() { - backend.resolve(backend.getBatteryCurrent(), (rate: number) => { set_value(CURRENT_BATT, rate) }); - backend.resolve(backend.getBatteryChargeNow(), (rate: number) => { set_value(CHARGE_NOW_BATT, rate) }); - backend.resolve(backend.getBatteryChargeFull(), (rate: number) => { set_value(CHARGE_FULL_BATT, rate) }); + backend.resolve(backend.getPeriodicals(), (periodicals) => { + set_value(CURRENT_BATT, periodicals.battery_current); + set_value(CHARGE_NOW_BATT, periodicals.battery_charge_now); + set_value(CHARGE_FULL_BATT, periodicals.battery_charge_full); + set_value(CHARGE_POWER_BATT, periodicals.battery_charge_power); - backend.resolve(backend.getGeneralSettingsPath(), (path: string) => { + const path = periodicals.settings_path; const oldValue = get_value(PATH_GEN); set_value(PATH_GEN, path); if (path != oldValue) { backend.log(backend.LogLevel.Info, "Frontend values reload triggered by path change: " + oldValue + " -> " + path); reload(); } - }); + }) }; const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { @@ -215,7 +234,7 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { periodicHook = setInterval(function() { periodicals(); reloadGUI("periodic" + (new Date()).getTime().toString()); - }, 1000); + }, PERIODICAL_BACKEND_PERIOD); if (!usdplReady || !get_value(LIMITS_INFO)) { // Not translated on purpose (to avoid USDPL issues) @@ -237,6 +256,8 @@ const Content: VFC<{ serverAPI: ServerAPI }> = ({}) => { return ( + + @@ -314,15 +335,16 @@ export default definePlugin((serverApi: ServerAPI) => { ico = ; } return { - title:
I'm a tool
, + title:
PowerTools
, content: , icon: ico, onDismount() { backend.log(backend.LogLevel.Debug, "PowerTools shutting down"); clearInterval(periodicHook!); periodicHook = null; - lifetimeHook!.unregister(); - startHook!.unregister(); + lifetimeHook?.unregister(); + startHook?.unregister(); + endHook?.unregister(); //serverApi.routerHook.removeRoute("/decky-plugin-test"); backend.log(backend.LogLevel.Debug, "Unregistered PowerTools callbacks, so long and thanks for all the fish."); }, diff --git a/translations/fr-CA.mo b/translations/fr-CA.mo index 673bd8c..f25dd78 100644 Binary files a/translations/fr-CA.mo and b/translations/fr-CA.mo differ diff --git a/translations/fr-CA.po b/translations/fr-CA.po index d7e8c2a..fbb09fb 100644 --- a/translations/fr-CA.po +++ b/translations/fr-CA.po @@ -65,6 +65,11 @@ msgstr "Présentement (Charge)" msgid "Max (Design)" msgstr "Max (Conçue)" +#: components/battery.tsx:60 +# (Wattage of battery charging input) +msgid "Charge Power" +msgstr "Puissance de charge" + # (Charge current limit override toggle) #: components/battery.tsx:59 msgid "Charge Current Limits" diff --git a/translations/fr-FR.mo b/translations/fr-FR.mo index 673bd8c..f25dd78 100644 Binary files a/translations/fr-FR.mo and b/translations/fr-FR.mo differ diff --git a/translations/pt.pot b/translations/pt.pot index 79fe733..1c15573 100644 --- a/translations/pt.pot +++ b/translations/pt.pot @@ -64,6 +64,11 @@ msgstr "" msgid "Max (Design)" msgstr "" +#: components/battery.tsx:60 +# (Wattage of battery charging input) +msgid "Charge Power" +msgstr "" + #: components/battery.tsx:59 # (Charge current limit override toggle) msgid "Charge Current Limits" diff --git a/translations/ru-RU.mo b/translations/ru-RU.mo new file mode 100644 index 0000000..30e36e2 Binary files /dev/null and b/translations/ru-RU.mo differ diff --git a/translations/test.mo b/translations/test.mo deleted file mode 100644 index 4def730..0000000 Binary files a/translations/test.mo and /dev/null differ diff --git a/translations/test.po b/translations/test.po deleted file mode 100644 index 8ba4fcb..0000000 --- a/translations/test.po +++ /dev/null @@ -1,227 +0,0 @@ -# TEMPLATE TITLE. -# Copyright (C) 2023 NGnius -# This file is distributed under the same license as the PowerTools package. -# NGnius (Graham) , 2023. -msgid "" -msgstr "" -"Project-Id-Version: v1.1\n" -"Report-Msgid-Bugs-To: https://github.com/NGnius/PowerTools/issues\n" -"POT-Creation-Date: 2023-01-10 20:06-0500\n" -"PO-Revision-Date: 2023-01-10 20:06-0500\n" -"Last-Translator: NGnius \n" -"Language-Team: NGnius \n" -"Language: conlang\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=utf-8\n" -"Content-Transfer-Encoding: 8bit\n" - -# -- index.tsx -- - -#: index.tsx:226 -# (Section title) -msgid "Miscellaneous" -msgstr "test123" - -#: index.tsx:226 -# (Profile persistence toggle) -msgid "Persistent" -msgstr "test123" - -#: index.tsx:227 -# (Profile persistence toggle description) -msgid "Save profile and load it next time" -msgstr "test123" - -#: index.tsx:239 -# (Profile display) -msgid "Profile" -msgstr "test123" - -# -- components/battery.tsx -- - -#: components/battery.tsx:42 -# (Battery section title) -msgid "Battery" -msgstr "test123" - -#: components/battery.tsx:46 -# (Charge of battery at this moment, with percentage of expected full charge in brackets) -msgid "Now (Charge)" -msgstr "test123" - -#: components/battery.tsx:52 -# (Maximum capacity of battery, with percentage of design capacity in brackets) -msgid "Max (Design)" -msgstr "test123" - -#: components/battery.tsx:59 -# (Charge current limit override toggle) -msgid "Charge Current Limits" -msgstr "test123" - -#: components/battery.tsx:60 -# (Charge current limit override toggle description) -msgid "Control battery charge rate when awake" -msgstr "test123" - -#: components/battery.tsx:74 -# (Battery maximum input current with unit) -msgid "Maximum (mA)" -msgstr "test123" - -#: components/battery.tsx:97,115 -# (Battery charge mode override toggle) -msgid "Charge Mode" -msgstr "test123" - -#: components/battery.tsx:98 -# (Battery charge mode override toggle description) -msgid "Force battery charge mode" -msgstr "test123" - -#: components/battery.tsx:112 -# (Battery charge mode dropdown) -msgid "Mode" -msgstr "test123" - -#: components/battery.tsx:133 -# (Battery current display) -msgid "Current" -msgstr "test123" - -# -- components/cpus.tsx -- - -#: components/cpus.tsx:64 -# (CPU section title) -msgid "CPU" -msgstr "test123" - -#: components/cpus.tsx:70 -# (CPU advanced mode toggle) -msgid "Advanced" -msgstr "test123" - -#: components/cpus.tsx:71 -# (CPU advanced mode toggle description) -msgid "Enables per-thread configuration" -msgstr "test123" - -#: components/cpus.tsx:88 -# (CPU Simultaneous MultiThreading toggle) -msgid "SMT" -msgstr "test123" - -#: components/cpus.tsx:89 -# (CPU SMT toggle description) -msgid "Enables odd-numbered CPUs" -msgstr "test123" - -#: components/cpus.tsx:106 -# (CPU thread count slider) -msgid "Threads" -msgstr "test123" - -#: components/cpus.tsx:137 -#: components/gpu.tsx:112 -# (Clock speed override toggle) -msgid "Frequency Limits" -msgstr "test123" - -#: components/cpus.tsx:138 -#: components/gpu.tsx:113 -# (Clock speed override toggle description) -msgid "Set bounds on clock speed" -msgstr "test123" - -#: components/cpus.tsx:165 -#: components/gpu.tsx:137 -# (Minimum clock speed with unit) -msgid "Minimum (MHz)" -msgstr "test123" - -#: components/cpus.tsx:195 -#: components/gpu.tsx:160 -# (Maximum clock speed with unit) -msgid "Maximum (MHz)" -msgstr "test123" - -# advanced mode - -#: components/cpus.tsx:226 -# (CPU selection slider) -msgid "Selected CPU" -msgstr "test123" - -#: components/cpus.tsx:246 -# (CPU Online toggle) -msgid "Online" -msgstr "test123" - -#: components/cpus.tsx:247 -# (CPU Online description) -msgid "Allow the CPU thread to do work" -msgstr "test123" - -#: components/cpus.tsx:342 -# (CPU scheduling governor dropdown -- governor names are not translated) -msgid "Governor" -msgstr "test123" - -# -- components/debug.tsx -- - -#: components/debug.tsx:29 -# (Debug section title) -msgid "Debug" -msgstr "test123" - -#: components/debug.tsx:33 -# (Version display for native back-end of PowerTools) -msgid "Native" -msgstr "test123" - -#: components/debug.tsx:47 -# (Mode display for framework of USDPL API) -msgid "Framework" -msgstr "test123" - -#: components/debug.tsx:54 -# (Display for software implementation in PowerTools which applies settings) -msgid "Driver" -msgstr "test123" - -# -- components/gpu.tsx -- - -#: components/gpu.tsx:34 -# (GPU section title) -msgid "GPU" -msgstr "test123" - -#: components/gpu.tsx:39 -# (PPT Limits override toggle) -msgid "PowerPlay Limits" -msgstr "test123" - -#: components/gpu.tsx:40 -# (PPT Limits override toggle description) -msgid "Override APU TDP settings" -msgstr "test123" - -#: components/gpu.tsx:63 -# (SlowPPT slider with unit) -msgid "SlowPPT (W)" -msgstr "test123" - -#: components/gpu.tsx:87 -# (FastPPT slider with unit) -msgid "FastPPT (W)" -msgstr "test123" - -#: components/gpu.tsx:112 -# (Reduce memory clock speed toggle) -msgid "Downclock Memory" -msgstr "test123" - -#: components/gpu.tsx:112 -# (Reduce memory clock speed toggle description) -msgid "Force RAM into low-power mode" -msgstr "test123" diff --git a/translations/uk-UA.mo b/translations/uk-UA.mo new file mode 100644 index 0000000..cb725de Binary files /dev/null and b/translations/uk-UA.mo differ