Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dev
tests
__pycache__
__pycache__
**/__pycache__
11 changes: 0 additions & 11 deletions Makefile

This file was deleted.

200 changes: 118 additions & 82 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,157 +5,193 @@ This tool provides fan control for HP Omen Max, Victus and Omen laptops on Linux
## Context

This tool includes a backported `hp-wmi` driver patch from the upcoming Linux 6.20 kernel, which introduces native fan control support for many devices from the following models:
1. **HP Omen Max**
2. **HP Victus**
3. **HP Omen**

1. **HP Omen Max**
2. **HP Victus**
3. **HP Omen**

The patch can be installed on versions before `6.20`.

**Reference Kernel Commit:**
[platform/x86: hp-wmi: add manual fan control for Victus S models](https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/commit/?h=for-next&id=46be1453e6e61884b4840a768d1e8ffaf01a4c1c)

This program also includes a modification that sets the max speed according to calibration if the query to get the Max RPM fails for your device.

## Tested Hardware

* **Model:** HP OMEN MAX 16-AH0001NT (8D41)
* **OS:** Arch Linux 6.18.6
- **Model:** HP OMEN MAX 16-AH0001NT (8D41)
- **OS:** Arch Linux 6.18.6

## Installation

### Clone the repository
Clone the repository or download the latest source code from the [Releases](https://github.com/arfelious/omen-fan-control/releases) page.
Choose one of the following: **pipx/uv** (recommended), **Arch Linux packages**, or **clone + run from source**.

### Option A: pipx or uv (recommended)

Install the app in an isolated environment. Driver sources are bundled; you can run `install-patch` from the app.

**Using pipx:**

```bash
pipx install git+https://github.com/arfelious/omen-fan-control.git
# Then:
sudo omen-fan-control status
sudo omen-fan-control-gui # GUI
```

**Using uv:**

```bash
uv tool install git+https://github.com/arfelious/omen-fan-control.git
sudo omen-fan-control status
sudo omen-fan-control-gui
```

**System deps (for driver build):** install kernel headers and build tools (e.g. Arch: `linux-headers base-devel`, Debian/Ubuntu: `linux-headers-$(uname -r) build-essential`).

### Option B: Arch Linux (PKGBUILD)

Two packages: the **DKMS kernel module** (optional; persists across kernel updates) and the **Python app**.

1. **Kernel module (DKMS)** – run from the package dir (makepkg needs PKGBUILD in cwd):
```bash
cd omen-fan-control/arch/hp-wmi-omen && makepkg -sf
sudo pacman -U hp-wmi-omen-dkms-*.pkg.tar.zst
```
2. **Python application** – run from the package dir:
```bash
cd omen-fan-control/arch/omen-fan-control && makepkg -sf
sudo pacman -U omen-fan-control-*.pkg.tar.zst
```
Driver data is installed under `/usr/share/omen-fan-control`; the app uses it when you run `install-patch permanent` (e.g. for calibration-based patching). Set `OMEN_FAN_CONTROL_DIR=/usr/share/omen-fan-control` if not using the provided `profile.d` snippet.

### Option C: Clone and run from source (single copy under `src/`)

All code and driver sources live under `src/`

```bash
git clone https://github.com/arfelious/omen-fan-control.git
cd omen-fan-control
```

### Dependencies
**Dependencies**

**1. System Dependencies**
You must install kernel headers and build tools for the driver patch to compile.
* **Arch:** `pacman -S linux-headers base-devel`
* **Debian/Ubuntu:** `apt install linux-headers-$(uname -r) build-essential`
- **System:** kernel headers and build tools (Arch: `pacman -S linux-headers base-devel`; Debian/Ubuntu: `apt install linux-headers-$(uname -r) build-essential`).
- **Python:** `click`, `PyQt6`. Either use **uv** (recommended) or pip.

**2. Python Dependencies**
You can install the required Python packages (`click`, `PyQt6`) via your package manager OR pip, preferably with a virtual environment.
**Run from repo (no install)**

* **Option A: Package Manager**
* **Arch:** `pacman -S python-click python-pyqt6`
* **Debian/Ubuntu:** `apt install python3-click python3-pyqt6`
With **uv** (adds project to path automatically):

* **Option B: Pip**
```bash
pip install -r requirements.txt
```
```bash
uv sync
uv run omen-fan-control --help
uv run omen-fan-control-gui
sudo uv run omen-fan-control install-patch permanent
sudo uv run omen-fan-control service install
```

### Install Driver Patch
You can install the modified driver temporarily (current session) or permanently (DKMS-style patch).
With **pip** (run the package module with `src` on `PYTHONPATH`):

```bash
# Permanent Installation (Recommended)
sudo python3 omen_cli.py install-patch permanent

# Temporary Installation (Until Reboot)
sudo python3 omen_cli.py install-patch temporary
pip install -r requirements.txt
export PYTHONPATH=src
python -m omen_fan_control.cli --help
python -m omen_fan_control.gui
sudo env PYTHONPATH=src python -m omen_fan_control.cli install-patch permanent
sudo env PYTHONPATH=src python -m omen_fan_control.cli service install
```

### Install Background Service
For proper curve control and watchdog operation, install the background service:
Or install the package in editable mode and use the same commands as pipx:

```bash
sudo python3 omen_cli.py service install
uv sync # or: pip install -e .
uv run omen-fan-control status
sudo uv run omen-fan-control-gui
```

You can also install it from the settings page in the graphical interface.
## Usage

- **Installed** (pipx, uv tool, or Arch): run `omen-fan-control` and `omen-fan-control-gui`.
- **From clone:** run `uv run omen-fan-control` / `uv run omen-fan-control-gui`, or `PYTHONPATH=src python -m omen_fan_control.cli` / `python -m omen_fan_control.gui`.

Examples below use `omen-fan-control`; from clone use one of the forms above.

### GUI
A graphical interface is available for simpler configuration.

```bash
sudo python3 omen_gui.py
sudo omen-fan-control-gui
```

**GUI Fan Curve**

|<img width="400" height="300" alt="Omen Fan Control GUI" src="https://github.com/user-attachments/assets/57f1a966-d7a6-4c5f-8090-a1e947349bd9" />|
|---|


### CLI
The `omen_cli.py` script manages everything.

**Check Status:**
```bash
sudo python3 omen_cli.py status
```
**Possible Settings**
```bash
python omen_cli.py settings --help
```
**Current Settings Configuration**
**Check status**

```bash
python omen_cli.py settings
sudo omen-fan-control status
```

**Set Settings (Moving Average Window, etc.):**
**Settings**

```bash
sudo python3 omen_cli.py options --ma-window 10 --curve-interpolation smooth
omen-fan-control settings --help
omen-fan-control settings
sudo omen-fan-control options --ma-window 10 --curve-interpolation smooth
```

**Manual Fan Control:**
**Fan control**

```bash
# Set specific speed
sudo python3 omen_cli.py fan-control --mode manual --value 80%
# Manual speed
sudo omen-fan-control fan-control --mode manual --value 80%

# Set Curve Mode (requires service)
sudo python3 omen_cli.py fan-control --mode curve
# Curve mode (requires service)
sudo omen-fan-control fan-control --mode curve

# Set Auto (Default)
sudo python3 omen_cli.py fan-control --mode auto
```
# Auto (default)
sudo omen-fan-control fan-control --mode auto

**Using Custom Curves:**
```bash
sudo python3 omen_cli.py fan-control --curve-csv my_curve.csv
# Custom curve CSV (temp, percent per line)
sudo omen-fan-control fan-control --curve-csv my_curve.csv
```
Where the csv file has values in `temp, percent` order

<br>

**Detailed Information**
**Other**

Commands provide detailed information when `--help` is passed with the command
```bash
python omen_cli.py fan-control --help
omen-fan-control fan-control --help
```

## Uninstallation

To remove the service and restore the original kernel driver:

1. **Remove Service:**
```bash
sudo python3 omen_cli.py service remove
```

2. **Restore Driver:**
```bash
sudo python3 omen_cli.py install-patch restore
```
This restores the original `.ko` files from the backups created during installation.
1. **Remove service**
```bash
sudo omen-fan-control service remove
```
2. **Restore original driver**
```bash
sudo omen-fan-control install-patch restore
```
Restores the original `.ko` files from backups created during installation.

## Disclaimer

**USE AT YOUR OWN RISK.**
Modifying kernel drivers and manipulating thermal control systems can potentially damage your hardware or cause instability. This software is provided "as is" without warranty of any kind. This was tested on my personal hardware, and the used `hp-wmi.c` is a patched version of the one in the upcoming `6.20` kernel, so your mileage may vary.

<details>
<summary>Acknowledgements</summary>
<br>
Acknowledgements


**Probes:**
- https://github.com/alou-S/omen-fan/blob/main/docs/probes.md

- [https://github.com/alou-S/omen-fan/blob/main/docs/probes.md](https://github.com/alou-S/omen-fan/blob/main/docs/probes.md)

**Linux 6.20 Kernel HP-WMI Driver:**
- https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/commit/?h=for-next&id=46be1453e6e61884b4840a768d1e8ffaf01a4c1c

</details>
- [https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/commit/?h=for-next&id=46be1453e6e61884b4840a768d1e8ffaf01a4c1c](https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/commit/?h=for-next&id=46be1453e6e61884b4840a768d1e8ffaf01a4c1c)

40 changes: 40 additions & 0 deletions arch/hp-wmi-omen/PKGBUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# DKMS kernel module: patched hp-wmi for HP Omen/Victus fan control (Linux < 6.20)
_pkgbase=hp-wmi-omen
pkgname="${_pkgbase}-dkms"
pkgver=1.0
pkgrel=1
pkgdesc="Patched hp-wmi driver for HP Omen/Victus fan control (DKMS; for kernels < 6.20)"
url="https://github.com/arfelious/omen-fan-control"
license=("GPL")
arch=("x86_64")
depends=('glibc' 'dkms')
makedepends=()
conflicts=()
provides=("hp-wmi-omen")
source=("PKGBUILD")
sha256sums=("SKIP")

prepare() {
# Copy driver from repo (same layout as betel: dkms.conf + src/Makefile + src/hp-wmi-omen/)
local reporoot
if [[ -f "$startdir/src/omen_fan_control/data/driver/hp-wmi-omen/hp-wmi.c" ]]; then
reporoot="$startdir"
else
reporoot="$startdir/../.."
fi
local driver="$reporoot/src/omen_fan_control/data/driver"
cp -f "$driver/dkms.conf" "$srcdir/"
mkdir -p "$srcdir/src"
cp -f "$driver/src/Makefile" "$srcdir/src/"
cp -dr --no-preserve=ownership "$driver/hp-wmi-omen" "$srcdir/src/"
}

package() {
local dkms_dir="/usr/src/${_pkgbase}-${pkgver}"
install -Dm644 dkms.conf "${pkgdir}${dkms_dir}/dkms.conf"
sed -e "s/@PKGNAME@/${_pkgbase}/g" \
-e "s/@PKGVER@/${pkgver}/g" \
-i "${pkgdir}${dkms_dir}/dkms.conf"
install -Dm644 src/Makefile "${pkgdir}${dkms_dir}/src/Makefile"
cp -dr --no-preserve=ownership "./src/hp-wmi-omen" "${pkgdir}${dkms_dir}/src"
}
59 changes: 59 additions & 0 deletions arch/omen-fan-control/PKGBUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Python application: CLI and GUI for HP Omen/Victus fan control
# Install driver separately (hp-wmi-omen-dkms) or use "omen-fan-control install-patch" from this app.
pkgname=omen-fan-control
pkgver=1.0.0
pkgrel=1
pkgdesc="Fan control for HP Omen Max, Victus and Omen laptops on Linux (CLI + GUI)"
url="https://github.com/arfelious/omen-fan-control"
license=("GPL-3.0-or-later")
arch=("any")
depends=("python-click" "python-pyqt6")
makedepends=("python-build" "python-installer" "python-hatchling")
optdepends=("hp-wmi-omen-dkms: persist patched driver across kernel updates")
source=("PKGBUILD")
sha256sums=("SKIP")

prepare() {
local reporoot
if [[ -f "$startdir/pyproject.toml" ]]; then
reporoot="$startdir"
else
reporoot="$startdir/../.."
fi
cp -f "$reporoot/pyproject.toml" "$srcdir/"
cp -f "$reporoot/README.md" "$reporoot/LICENSE.md" "$srcdir/" 2>/dev/null || true
cp -r "$reporoot/src" "$srcdir/"
}

build() {
cd "$srcdir"
python -m build --wheel --no-isolation
}

package() {
local whl
whl=$(echo "$srcdir"/dist/omen_fan_control*.whl)
python -m installer --compile-bytecode=0 -d "$pkgdir" "$whl"

# Driver data for "install-patch permanent" (same layout as hp-wmi-omen-dkms: dkms.conf + hp-wmi-omen/)
local driver="$srcdir/src/omen_fan_control/data/driver"
install -Dm644 "$driver/dkms.conf" "$pkgdir/usr/share/omen-fan-control/driver/dkms.conf"
cp -dr --no-preserve=ownership "$driver/hp-wmi-omen" "$pkgdir/usr/share/omen-fan-control/driver/"
install -Dm755 "$driver/install_driver.sh" "$pkgdir/usr/share/omen-fan-control/driver/install_driver.sh"
install -dm755 "$pkgdir/usr/share/omen-fan-control/driver/hooks"
for f in "$driver/hooks/"*; do
[[ -f "$f" ]] && install -Dm644 "$f" "$pkgdir/usr/share/omen-fan-control/driver/hooks/$(basename "$f")"
done

# systemd service (placeholder @EXECSTART@ replaced with installed executable path)
install -dm755 "$pkgdir/usr/lib/systemd/system"
sed 's|@EXECSTART@|/usr/bin/omen-fan-control serve|g' \
"$srcdir/src/omen_fan_control/data/omen-fan-control.service" \
> "$pkgdir/usr/lib/systemd/system/omen-fan-control.service"
chmod 644 "$pkgdir/usr/lib/systemd/system/omen-fan-control.service"

# profile.d so OMEN_FAN_CONTROL_DIR is set for all users
install -dm755 "$pkgdir/etc/profile.d"
printf '%s\n' 'export OMEN_FAN_CONTROL_DIR=/usr/share/omen-fan-control' > "$pkgdir/etc/profile.d/omen-fan-control.sh"
chmod 644 "$pkgdir/etc/profile.d/omen-fan-control.sh"
}
Loading