Add victus-fan: userspace stock-driver fan controller for Ubuntu / Secure Boot#17
Open
jayeshbarman wants to merge 1 commit into
Open
Add victus-fan: userspace stock-driver fan controller for Ubuntu / Secure Boot#17jayeshbarman wants to merge 1 commit into
jayeshbarman wants to merge 1 commit into
Conversation
…e Boot) victus-fan is a self-contained userspace fan controller for setups that cannot load the patched hp-wmi DKMS module — notably Ubuntu with Secure Boot enabled, where unsigned out-of-tree modules are rejected. It drives ONLY the stock in-tree hp-wmi pwm1_enable (two-state MAX/AUTO) and ties fan behaviour to the active power profile plus CPU / iGPU / NVIDIA temperatures, with hysteresis. Ships a root systemd daemon (victus-fand), a CLI (victus-fanctl), systemd packaging and an Ubuntu installer. No kernel module, no GUI. Added under victus-fan/ so it sits alongside the existing kernel-module controller without touching it (only a pointer is added to the top-level README). Licensed GPL-3.0-or-later to match the project. Tested end-to-end on an HP Victus 15-fb0xxx running Ubuntu 26.04 (see victus-fan/docs/TESTING.md).
Owner
|
Thank you for your pr , will review it soon |
There was a problem hiding this comment.
Pull request overview
Adds a new victus-fan/ subproject: a self-contained userspace (Python stdlib) fan-control daemon + CLI intended to work on Ubuntu with Secure Boot by using only the stock in-tree hp-wmi interface (pwm1_enable two-state control), plus install/uninstall and systemd packaging.
Changes:
- Introduces
victus-fand(root systemd daemon) andvictus-fanctl(user CLI) that map power profile + temps topwm1_enablewith hysteresis and a status file. - Adds Ubuntu-oriented install/uninstall scripts and systemd unit/tmpfiles + default config.
- Updates top-level README to point Ubuntu/Secure Boot users to
victus-fan/.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
victus-fan/install.sh |
Installs daemon/CLI/docs, creates victusfan group, sets up config, enables systemd service. |
victus-fan/uninstall.sh |
Stops/disables service, restores firmware AUTO, removes installed artifacts. |
victus-fan/daemon/victus-fand |
Root daemon implementing discovery, polling, hysteresis, and sysfs writes to pwm1_enable. |
victus-fan/daemon/victus-fanctl |
CLI to inspect status and atomically edit /etc/victus-fan/config.json. |
victus-fan/packaging/victus-fan.service |
systemd unit for running victus-fand as root. |
victus-fan/packaging/victus-fan.tmpfiles |
Creates /run/victus-fan/ for the daemon’s status output. |
victus-fan/packaging/config.default.json |
Default thresholds/settings for the daemon/CLI. |
victus-fan/README.md |
Full user documentation for install, operation, config, and troubleshooting. |
victus-fan/docs/TESTING.md |
Hardware-specific test/verification record. |
README.md |
Adds a top-level pointer to the new Ubuntu/Secure Boot userspace flow. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+49
to
+53
| rm -f /usr/lib/victus-fan/victus-fand || true | ||
| rmdir /usr/lib/victus-fan 2>/dev/null || true | ||
| rm -f /usr/bin/victus-fanctl || true | ||
| rm -f /etc/systemd/system/victus-fan.service || true | ||
| rm -f /etc/tmpfiles.d/victus-fan.conf || true |
|
|
||
| SRC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" | ||
|
|
||
| # Re-exec with sudo if not root; keep SUDO_USER for the extension cleanup. |
Comment on lines
+44
to
+46
| echo "!! WARNING: could not resolve a non-root desktop user via SUDO_USER." | ||
| echo "!! Group membership and the GNOME extension will be skipped." | ||
| echo "!! Re-run with: sudo ./install.sh (from your user session)." |
Comment on lines
+2
to
+3
| # The daemon writes /run/victus-fan/status.json (mode 0644, world-readable) here | ||
| # each poll loop. UIs (GTK app, GNOME extension, CLI) read that status file. |
| NVIDIA_SMI_TIMEOUT_SEC = 2 | ||
|
|
||
| # ---------------------------------------------------------------------------- | ||
| # Default configuration (single source of truth mirrored in config.default.json) |
|
|
||
| def find_nvidia_pci_device(): | ||
| """ | ||
| Locate the NVIDIA dGPU PCI device (vendor 0x10de, class starts 0x0300). |
| klass = read_text(os.path.join(d, "class")) | ||
| if vendor is None or klass is None: | ||
| continue | ||
| if vendor.lower() == NVIDIA_VENDOR and klass.lower().startswith("0x0300"): |
Comment on lines
+426
to
+430
| on_thr = thresholds.get(label + "_on") | ||
| off_thr = thresholds.get(label + "_off") | ||
| if on_thr is None or off_thr is None: | ||
| continue | ||
| present.append((label, val, on_thr, off_thr)) |
Comment on lines
+475
to
+477
| override = config.get("override", "policy") | ||
| profile_map = config.get("profile_map", {}) | ||
| low_battery_pct = config.get("low_battery_pct", 20) |
Comment on lines
+496
to
+498
| profiles = config.get("profiles", {}) | ||
| thresholds = profiles.get(effective) | ||
| if not isinstance(thresholds, dict): |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
victus-fan/— a self-contained userspace fan controller for HP Victus / Omen laptops, for environments where the patchedhp-wmiDKMS module cannot be used.The README already notes the project "does not currently ship a full Ubuntu installer." This addresses exactly that gap. On Ubuntu with Secure Boot enabled, the existing flow cannot run — Ubuntu ships no patched
hp-wmi, and an unsigned out-of-tree module is rejected by Secure Boot.victus-fanworks there because it uses only the stock, in-treehp-wmidriver — nothing is compiled, signed, or DKMS-built.How it works
Stock
hp-wmiexposes a two-statepwm1_enable(0= MAX,2= firmware AUTO;1is rejected, and there is no PWM-duty / fan-target file). So a small root daemon (victus-fand) maps your power profile + CPU / iGPU / NVIDIA temperatures onto those two states with hysteresis:nvidia-smionly when it is already awake (never wakes a runtime-suspended dGPU, so it does not cost battery).SIGTERM).victus-fanctl(status / override / thresholds). No GUI.Scope & safety
victus-fan/— no existing files are changed except a short pointer added to the top-level README.Tested
Built and verified end-to-end on an HP Victus 15-fb0xxx running Ubuntu 26.04 LTS (kernel 7.0, Secure Boot on): all power modes, heat-triggered MAX, manual overrides, the restore-fans-on-stop safety path, and the group-based permission model. Full report:
victus-fan/docs/TESTING.md.