From f58a011f4d5a61198e31eb24a6e6e6cdf25c64b8 Mon Sep 17 00:00:00 2001 From: oxpoe Date: Tue, 13 Oct 2026 06:18:01 +0700 Subject: [PATCH] GAMEMAX IceBurg LCD Linux bridge: sender + tray app Reverse-engineered Linux driver for the LCD panel of the GAMEMAX IceBurg Digital AIO cooler (HID 5131:2007). Includes: - src/gamemax_report.py pure-stdlib sender: reads hwmon/proc sensors and streams the 65-byte HID report the firmware understands (no deps) - src/gamemax_gui.py PySide6 tray app: animated monitor, fan/temperature channel pickers, autostart, blank mode, single instance, crash log - packaging/ AppImage build script, udev rule, systemd user unit - tools/ IL dump helpers used to read the vendor MSIL - docs/ full reverse-engineering analysis - DISCLAIMER.md Linux-compatibility project, not affiliated with vendor Co-authored-by: REA (managed-code analysis) --- .gitignore | 15 + DISCLAIMER.md | 39 ++ README.md | 123 +++++ assets/icon-128.png | Bin 0 -> 6909 bytes assets/preview-blank-mode.png | Bin 0 -> 102923 bytes assets/preview.png | Bin 0 -> 89738 bytes docs/reverse-engineering.md | 204 ++++++++ packaging/70-gamemax.rules | 5 + packaging/build_appimage.sh | 63 +++ packaging/gamemax-report.service | 13 + src/gamemax_gui.py | 804 +++++++++++++++++++++++++++++++ src/gamemax_report.py | 443 +++++++++++++++++ src/icon.png | Bin 0 -> 14550 bytes tools/ildump.py | 103 ++++ tools/string_refs.py | 81 ++++ 15 files changed, 1893 insertions(+) create mode 100644 .gitignore create mode 100644 DISCLAIMER.md create mode 100644 README.md create mode 100644 assets/icon-128.png create mode 100644 assets/preview-blank-mode.png create mode 100644 assets/preview.png create mode 100644 docs/reverse-engineering.md create mode 100644 packaging/70-gamemax.rules create mode 100755 packaging/build_appimage.sh create mode 100644 packaging/gamemax-report.service create mode 100755 src/gamemax_gui.py create mode 100755 src/gamemax_report.py create mode 100644 src/icon.png create mode 100755 tools/ildump.py create mode 100755 tools/string_refs.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2a0ef5a --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# build artefacts +dist/ +build/ +*.AppImage +__pycache__/ +*.pyc + +# machine-specific analysis artefacts (regenerate with REA) +evidence/ +snapshots/ +*.rea.backup + +# local bits +*.log +config.json diff --git a/DISCLAIMER.md b/DISCLAIMER.md new file mode 100644 index 0000000..0a08f16 --- /dev/null +++ b/DISCLAIMER.md @@ -0,0 +1,39 @@ +# Disclaimer + +**Bahasa Indonesia** + +Aplikasi ini dibuat oleh **oxpoe** semata-mata untuk **kompatibilitas Linux dengan +perangkat keras** (khususnya layar LCD pada AIO cooler). Tujuannya agar pengguna +Linux bisa memakai perangkat yang secara resmi hanya didukung aplikasi Windows. + +1. **Tidak berafiliasi** dengan GAMEMAX, GameMax, atau vendor mana pun. Proyek ini + tidak disponsori, tidak didukung, dan tidak berhubungan dengan pembuat perangkat. +2. **Dibuat untuk interoperabilitas.** Protokolnya dipelajari secara independen dari + perilaku perangkat dan dari aplikasi vendor yang sudah terpasang di komputer + penulis (rekayasa balik untuk kompatibilitas). Tidak ada kode, berkas, atau aset + milik vendor yang disertakan dalam repositori ini. +3. **Merek dagang** seperti GAMEMAX, GameMax, IceBurg, serta nama produk lain + adalah milik pemegangnya masing-masing. Ikon aplikasi di repositori ini adalah + karya orisinal, bukan logo vendor. +4. **Risiko ditanggung pengguna.** Perangkat lunak ini menulis data ke perangkat USB + HID. Penulis telah mengujinya pada perangkat miliknya sendiri, tetapi tidak ada + jaminan apa pun — termasuk jaminan kelayakan untuk tujuan tertentu. Gunakan dengan + risiko Anda sendiri. +5. **Tanpa jaminan.** Perangkat lunak disediakan "sebagaimana adanya" di bawah + lisensi MIT; lihat `LICENSE`. +6. **Perkakas pihak ketiga** yang dipakai saat analisis (mis. REA, Ghidra, PySide6) + tetap tunduk pada lisensinya masing-masing dan tidak didistribusikan ulang di sini. + +**English** + +This project is made by **oxpoe** purely for **Linux hardware compatibility** — +so that Linux users can drive the LCD panel of a device that is officially supported +only by a Windows application. + +- Not affiliated with, sponsored by, or endorsed by GAMEMAX/GameMax or any vendor. +- Independently reverse engineered for interoperability. No vendor code, binaries, + or assets are redistributed; the application icon is original artwork. +- Trademarks belong to their respective owners. +- The software writes to a USB HID device. It was tested on the author's own hardware + only. Use at your own risk, provided "as is", without warranty of any kind (MIT). +- Third-party analysis tools keep their own licenses. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7a3c0d1 --- /dev/null +++ b/README.md @@ -0,0 +1,123 @@ +# GAMEMAX LCD — Linux bridge & tray app + +Drive the LCD panel of a GAMEMAX **IceBurg Digital** AIO cooler from Linux: a small +sender plus a tray application (GUI) with live monitoring, settings and autostart. + +Reverse engineered independently from the Windows vendor software +(`PcInfoMonitorPro.exe` / "IceBurg Digital Software"); the protocol notes are in +[`docs/reverse-engineering.md`](docs/reverse-engineering.md) (Indonesian). + +Author: **oxpoe** · License: **MIT** · Please read [DISCLAIMER.md](DISCLAIMER.md). + +![Tray app preview](assets/preview.png) + +## Features + +- Sends CPU temp/load/clock/fan/power, GPU temp/load/clock/fan/power, RAM and disk + usage to the panel as a 65-byte HID report (the layout the firmware understands) +- Reads sensors from standard Linux interfaces: `hwmon`, `/proc/stat`, `cpufreq`, + `/proc/meminfo`, `statvfs` — no extra dependencies (pure Python, stdlib only) +- **Tray app** (`--tray-only`) plus a window with an animated gauge, bars and details +- **Settings**: fan channel (pick the header your fans are on), CPU temperature source, + send/sample interval — saved to `~/.config/gamemax-report/config.json` +- **Clear mode indicators**: green "showing sensor data" / orange "blank (zeros)" / + grey "sending stopped", dimmed tray icon and a desktop notification per change +- **Autostart** via a systemd user unit (equivalent of the vendor's Task Scheduler trick) +- **Plug and play**: the service waits for the device, streams while present and keeps + waiting through unplug/replug; a udev rule grants access to the logged-in user +- **Single instance**: launching the app again just raises the running window +- **AppImage build** script (`packaging/build_appimage.sh`, PySide6 bundled) + +The GUI labels are in Indonesian. + +## Requirements + +- Linux with a working `hidraw` stack (tested on CachyOS / Arch, KDE Wayland) +- Python 3.10+ for the sender (stdlib only) +- For the tray app: PySide6 (`uv run --with pyside6 python src/gamemax_gui.py`) + or use the prebuilt AppImage + +## Install + +```bash +# 1. device access for the logged-in user (once, needs root) +sudo cp packaging/70-gamemax.rules /etc/udev/rules.d/ +sudo udevadm control --reload && sudo udevadm trigger --subsystem-match=hidraw + +# 2. try it without installing anything +cd src +python3 gamemax_report.py --dry-run # build and print a report, no device writes +python3 gamemax_report.py --listen 5 # read panel -> host reports (none on this panel) + +# 3. send for real +python3 gamemax_report.py --count 3 # a few reports +python3 gamemax_report.py # keep streaming (Ctrl-C to stop) +``` + +## Run as a background service (autostart + plug and play) + +```bash +mkdir -p ~/.local/share/gamemax-report ~/.config/systemd/user +cp src/gamemax_report.py ~/.local/share/gamemax-report/ +cp packaging/gamemax-report.service ~/.config/systemd/user/ +systemctl --user daemon-reload +systemctl --user enable --now gamemax-report.service +journalctl --user -u gamemax-report -f # shows "waiting for 0x5131:0x2007" / "opened ..." +``` + +The tray app can do all of this for you (buttons *Pasang / perbarui layanan*, +*Mulai otomatis saat login*). + +## Tray app / AppImage + +```bash +uv run --with pyside6 python src/gamemax_gui.py # window + tray +uv run --with pyside6 python src/gamemax_gui.py --tray-only + +bash packaging/build_appimage.sh # -> dist/GAMEMAX-LCD-x86_64.AppImage +``` + +## Protocol (verified on hardware) + +VID `0x5131` / PID `0x2007`, vendor-defined HID page `0xFF00`, 64-byte IN + 64-byte OUT, +no report IDs. The host sends 64 data bytes: + +| Offset | Field | Notes | +|---|---|---| +| 0 | report ID | always 0 | +| 1 | 64 | payload length | +| 2 | CPU temp | 0..99 °C, two digits only; values ≥ 128 are ignored by firmware | +| 3 | CPU load % | | +| 4..5 | RPM slot | big-endian u16 — the panel shows *this* field next to the fan icon | +| 6..7 | CPU clock MHz | big-endian u16 | +| 8..9 | CPU power W | big-endian u16 | +| 10 | GPU temp | 0..99 °C | +| 11 | GPU load % | | +| 12..13 | GPU clock MHz | big-endian u16 | +| 14..15 | GPU fan RPM | big-endian u16 | +| 16..17 | GPU power W | big-endian u16 | +| 18 | RAM usage % | | +| 19..20 | total RAM MiB | big-endian u16 | +| 21 | disk free % | | +| 22..23 | total disk GB | big-endian u16 | +| 24..64 | unused | zero | + +Firmware behaviours worth knowing: the panel latches values it accepts, blinks the +value area when the data stops changing, cannot display three digits, has a fixed `°C` +label, and offers no command to power the display off. + +## Repository layout + +``` +src/ gamemax_report.py (sender) gamemax_gui.py (tray app) icon.png +packaging/ build_appimage.sh 70-gamemax.rules gamemax-report.service +tools/ ildump.py, string_refs.py — helpers used to read the vendor MSIL +docs/ reverse-engineering.md — full analysis (Indonesian) +assets/ previews and icon +``` + +## Credits + +Reverse engineered and written by **oxpoe**, with the help of +[REA](https://github.com/morluto/rea) (managed-code analysis) and Ghidra. +Not affiliated with GAMEMAX/GameMax — see [DISCLAIMER.md](DISCLAIMER.md). diff --git a/assets/icon-128.png b/assets/icon-128.png new file mode 100644 index 0000000000000000000000000000000000000000..2ea35b405550b31ee2ec61eeb24ec5211e64da0a GIT binary patch literal 6909 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 z�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 z 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 Ys4vyU?@B4k$b(f?)O?DNe;NEg0MF;EX#fBK literal 0 HcmV?d00001 diff --git a/assets/preview.png b/assets/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..9df59dcc22ca3d5f2ffebbc2942f88075bc39c77 GIT binary patch literal 89738 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 literal 0 HcmV?d00001 diff --git a/docs/reverse-engineering.md b/docs/reverse-engineering.md new file mode 100644 index 0000000..66598c5 --- /dev/null +++ b/docs/reverse-engineering.md @@ -0,0 +1,204 @@ +# GAMEMAX PcInfoMonitorPro — Recon & HID Protocol + +Target: `GAMEMAX_V1.0.0/app/` (installer `GAMEMAX_V1.0.0.04(1).exe`) +Analisis: 2026-10-13, REA 6.4.0 + Ghidra 12.1.2 (managed static provider), IL dumper lokal. + +## 1. Isi target + +| File | Peran | Teknologi | +|---|---|---| +| `PcInfoMonitorPro.exe` | Aplikasi utama (GUI) | PE32 mixed-mode C++/CLI + Qt5, **logika = MSIL** (457 method body) | +| `allComputerInfoGetPro.exe` | Helper console (dipanggil terpisah) | mixed-mode C++/CLI, sebagian besar CRT | +| `WitmodHardwareInfoLibrary.dll` | Model data sensor (CPU/GPU/mobo) | .NET Framework, CIL murni | +| `LibreHardwareMonitorLib.dll` | Sumber data sensor | OSS pihak ketiga (bukan kode vendor) | +| `HidSharp.dll` | HID library .NET | OSS pihak ketiga (tidak dipakai jalur utama) | +| `hidapi.dll` | I/O HID | OSS, **dipakai** untuk buka/tulis device | +| `Qt5*.dll`, `opengl32sw.dll`, `D3Dcompiler_47.dll` | Framework UI | Qt 5 native | +| `configDir/appConfig.ini` | Konfigurasi app | `[AppInfo] AppName=GAMEMAX, AppVersion=V_1.0.0.04, AppID=ABCDEF6543A1`, warna tema, font Microsoft YaHei | + +Catatan: vendor internal tampil sebagai `MyCompanyWitmod` / `WITMOD`; GAMEMAX adalah merek OEM-nya. + +## 2. Arsitektur logika + +Semua logika aplikasi dikompilasi ke **MSIL** (mixed-mode `/clr`), sehingga +decompile native (Ghidra) pada metode aplikasi menghasilkan sampah. Metode +dideklarasikan sebagai fungsi global bernama bertitik, mis. +`MainHidInterFace.hidApi_Write`, `DMainWidget.onGetPcInfoOk`, di bawah tipe ``. +Native hanya: Qt DLL, hidapi, CRT. + +Alur HID: +``` +DMainWidget.onGetPcInfoOk (bangun report 65 byte dari sensor) + -> MainHidInterFace.hidApi_Write (mutex + copy 65 B + QList enqueue) + -> MainHidInterFace.run (thread: QList.takeFirst -> hid_write, poll 500 us) +``` + +## 3. Device target & pembukaan + +`MainHidInterFace.getuUsbHidDeviceList`: +1. `hid_enumerate(0, 0)` — semua HID +2. filter `vendor_id == 20785 (0x5131)` **dan** `product_id == 8199 (0x2007)` +3. ambil `path` (offset 0, string ASCII) → `hid_open_path` +4. daftar device aktif dimuat via `RegisterDeviceNotificationW` (plug/unplug, sinyal + `sigHidDeviceConnectChanging_Into/Remove`, `sigOpenHidSuccessful`) + +Tulis **satu arah**: tidak ada `hid_read*` yang diimpor — app hanya mengirim. + +## 4. Protokol tulis (terverifikasi dari IL) + +- Transfer `hid_write(handle, buf, 65)`: 65 byte = 1 byte report ID + 64 byte payload +- `buf[0] = 0` (report ID 0) +- `buf[1] = 64` (0x40, panjang payload) +- Nilai 16-bit **big-endian** (high byte dulu) +- Suhu: jika checkbox unit tercentang → nilai dipakai apa adanya; jika tidak → + `round((v - 32) / 1.8) | 0x80`. **Bit 0x80 menandakan nilai Fahrenheit.** +- Pengiriman berulang tiap 500 us selama device terbuka + +### Layout report (dari `DMainWidget.onGetPcInfoOk`) + +| Offset | Isi | Sumber | +|---|---|---| +| 0 | 0 | report ID | +| 1 | 64 | panjang payload | +| 2 | CPU temp | `GetCpu_Temperature` (+flag 0x80 bila °F) | +| 3 | CPU load | `GetCpu_Load` | +| 4..5 | CPU clock (MHz, BE16) | `GetCpu_Clock` | +| 6..7 | CPU fan (RPM, BE16) | `GetCpu_Fan` | +| 8..9 | BE16 dari struct lokal | belum dipetakan | +| 10 | GPU temp | `GetGpu_Temperature` (+flag 0x80) | +| 11 | GPU load | `GetGpu_CoreLoad` | +| 12..13 | GPU clock (BE16) | `GetGpu_CoreClock` | +| 14..15 | GPU fan (BE16) | `GetGpu_Fan` | +| 16..17 | GPU power (BE16) | `GetGpu_Power` | +| 18 | u8 dari struct lokal | belum dipetakan | +| 19..20 | BE16 dari struct lokal | belum dipetakan | +| 21 | u8 dari struct lokal | belum dipetakan | +| 22..23 | BE16 dari struct lokal | belum dipetakan | +| 24..64 | 0 | tidak ditulis jalur ini | + +Nilai sensor berasal dari `WitmodHardwareInfoLibrary.Monitor` (wrapper tipis di atas +LibreHardwareMonitor): CPU/GPU Temperature, Load, CoreLoad, Clock, Clock_Max, Fan, +Fan_Max, Power, Power_Max. + +## 5. Bukti & artefak + +- `analysis/evidence/hid-write-protocol.json` — Evidence bundle REA (12 records, 5.5 MB) +- `analysis/snapshots/pcinfomonitorpro.json` — snapshot Ghidra (bisa dibuka ulang tanpa import) +- `analysis/tools/ildump.py` — disassembler IL (dnfile+dncil) untuk membaca MSIL dengan + operand terselesaikan; venv: `uv venv ilenv && uv pip install --python ilenv/bin/python dnfile dncil` + +## 6. Hasil lanjutan + +### 6.1 Hanya ada satu jenis perintah HID +Seluruh IL (457 body) dipindai: setiap fungsi hidapi dipanggil tepat sekali +(`hid_init`, `hid_enumerate`, `hid_free_enumeration`, `hid_open_path`, +`hid_set_nonblocking`, `hid_write`, `hid_close`, `hid_exit`) dan `hidApi_Write` +hanya punya **satu pemanggil** (`DMainWidget.onGetPcInfoOk`). Tidak ada +`hid_read*`/`hid_get_feature_report` — tidak ada perintah lain (brightness, +mode, dll.) di jalur ini. + +### 6.2 Auto-start + self-elevation (Task Scheduler) +`DMainWidget.initThemeData` (fungsi startup besar, offset IL ~4380-4520): +1. Menulis penanda ke QSettings: `StartupTaskOKver---` +2. `ShellExecuteW(verb="runas", file="schtasks", params=`
+ `/create /tn "%1" /tr "\"%2\" %3" /sc onlogon /rl highest` + - `%2` = `QCoreApplication.applicationFilePath()` (path exe sendiri) + - `%3` = `---StartupByTaskMinWindow` (penanda argumen) + - verb `runas` → UAC sekali di awal, task berjalan dengan token tertinggi tiap logon +3. `main` memindai `argv` untuk `---StartupByTaskMinWindow`, lalu mencetak + "Program was started by Task Scheduler." / "Program was not started by Task Scheduler." + dan memulai aplikasi terminimalkan +4. Manifest exe: `requestedExecutionLevel level='requireAdministrator'` + +Efek: aplikasi otomatis berjalan sebagai admin tanpa prompt UAC di setiap logon. + +### 6.3 `allComputerInfoGetPro.exe` = stub test +`main`: `new Monitor(); GetComputerInfo(); Sleep(500); printf("Over ... ..."); getchar();` +— harness uji developer untuk `WitmodHardwareInfoLibrary`, bukan bagian alur runtime. +Nama file ini **tidak dirujuk** oleh PcInfoMonitorPro.exe (ASCII maupun UTF-16) dan +tidak ada di installer. + +### 6.4 Layout report — LENGKAP (terverifikasi di device) + +| Offset | Isi | Sumber di aplikasi | Terverifikasi | +|---|---|---|---| +| 0 | 0 | report ID | ✅ | +| 1 | 64 | panjang payload | ✅ | +| 2 | CPU temp (0..127) | `GetCpu_Temperature` | ✅ tampil di layar | +| 3 | CPU load % | `GetCpu_Load` | ✅ | +| 4..5 | CPU clock MHz (BE16) | `GetCpu_Clock` | ✅ — **device merender byte ini di slot "RPM"** | +| 6..7 | CPU fan RPM (BE16) | `GetCpu_Fan` | ✅ (device tidak menampilkannya di halaman ini) | +| 8..9 | **CPU power W** (BE16) | `GetCpu_Power` | ✅ | +| 10 | GPU temp (0..127) | `GetGpu_Temperature` | ✅ | +| 11 | GPU load % | `GetGpu_CoreLoad` | ✅ | +| 12..13 | GPU clock MHz (BE16) | `GetGpu_CoreClock` | ✅ | +| 14..15 | GPU fan RPM (BE16) | `GetGpu_Fan` | ✅ | +| 16..17 | GPU power W (BE16) | `GetGpu_Power` | ✅ | +| 18 | RAM usage % | `GlobalMemoryStatusEx` → `dwMemoryLoad` | ✅ | +| 19..20 | total RAM MiB (BE16) | `ullTotalPhys` × 2⁻²⁰ | ✅ | +| 21 | disk free % | `GetDiskFreeSpaceExW` (free/total × 100) | ✅ | +| 22..23 | total disk GB (BE16) | total bytes >> 30 | ✅ | +| 24..64 | nol | tidak dipakai | ✅ | + +Catatan pembalikan dari dugaan awal: byte 8..9 **bukan** counter waktu melainkan +CPU power; 19..20 dan 22..23 adalah RAM total dan ukuran disk, bukan waktu. + +### 6.5 Perilaku firmware yang ditemukan saat pengujian + +1. **Nilai ≥ 128 ditolak.** Aplikasi asli menulis suhu Celsius dengan bit `0x80` + aktif. Firmware IceBurg **mengabaikan field itu** dan mempertahankan nilai terakhir + yang valid (pengujian: 99 °C mentok sampai nilai tanpa flag dikirim). Jadi kirim + suhu 0..127 tanpa flag. +2. **Kedip = indikator "nilai tidak berubah".** Saat semua field statis, angka tengah + berkedip ~1×/detik; saat nilai berubah (suhu naik 40→90) kedip hilang. Bukan efek + laju kirim — kedip tetap ada walau kita berhenti mengirim. +3. **Plafon laju ~8 report/detik.** Endpoint interrupt OUT `bInterval 160 ms`; setiap + `write()` hidraw menunggu URB selesai (~125 ms). Aplikasi asli menumpuk antrean dari + loop 500 µs (`QTimer.setInterval(10)` + `QThread.usleep(500)`), efektifnya sama. +4. **Selalu "streaming"**, tidak ada handshake/init: buka lalu tulis 64 byte. +5. **Slot RPM salah byte.** Diuji silang di hardware: kirim clock=4000 dan fan=1500 → + layar menampilkan 4000 di slot RPM. Jadi firmware memakai byte 4..5 untuk slot itu, + padahal aplikasi asli menaruh clock CPU di sana (bug pasangan app/firmware). + Implementasi pengganti menukar clock/fan agar layar menampilkan RPM fan sungguhan. +6. **Akurasi dibandingkan system monitor**: suhu cocok (selisih hanya pembulatan ke + integer), load cocok; keduanya tampil dengan delay beberapa detik akibat jendela + sampling dan laju device. + +## 7. Implementasi pengganti (jalan di host ini) + +`analysis/tools/gamemax_report.py` — Python murni, tanpa dependensi: +- auto-detect node hidraw dari VID:PID (`0x5131:0x2007`) +- baca sensor Linux: hwmon (CPU = maksimum Tctl/Tccd*, GPU, fan, power), `/proc/stat`, + cpufreq, `/proc/meminfo`, `statvfs("/")` +- bangun report 65 byte sesuai tabel di 6.4, tulis 64 byte payload ke hidraw +- `--dry-run` mencetak report + nilai; `--listen N` membaca pesan device→host + (device ini tidak pernah mengirim apa pun); `--count`, `--interval`, `--unit c|f`, + `--flag-celsius` (fidelitas ke aplikasi asli), override tiap field via `--cpu-temp` dll. +- `self_check()` mengunci header, urutan big-endian, dan semantik satuan + +`analysis/tools/70-gamemax.rules` — udev rule `TAG+="uaccess"` untuk node hidraw. +`analysis/tools/gamemax-report.service` — unit systemd **user** (padanan +`schtasks /sc onlogon` aplikasi asli), sudah aktif di mesin ini: + +```bash +systemctl --user status gamemax-report.service +journalctl --user -u gamemax-report -f +systemctl --user disable --now gamemax-report.service # matikan +``` + +Uji yang sudah lolos: dry-run + assert, kirim nyata, device menampilkan load/RPM/suhu +sesuai kiriman, dan tampilan mengikuti perubahan nilai. + +## 8. Device: GameMax IceBurg 240 Digital BK + +Ditemukan di mesin ini sebagai `Bus 001 Device 005: ID 5131:2007` (usb.ids salah +menamainya "MSR-101U card reader" — descriptor-nya vendor-defined 0xFF00, 64 byte IN ++ 64 byte OUT, tanpa report ID). Produknya: **GameMax IceBurg 240 Digital BK**, AIO +240 mm dengan blok LCD; "IceBurg 240 Digital Software" dari halaman produk +(gamemaxpc.com/cpu-liquid-cooler/1550.html) adalah `PcInfoMonitorPro.exe` yang kita +bongkar. Layar menampilkan halaman CPU (ikon CPU + load %, suhu besar, RPM, 6 titik +indikator halaman) dan menganimasikan busur kiri/kanan. + +Verifikasi: setelah `gamemax-report.service` aktif, device menampilkan suhu/load/RPM +dari sensor Linux, mengikuti perubahan nilai, dan berkedip hanya saat nilai statis +(perilaku firmware, disepakati dibiarkan apa adanya). diff --git a/packaging/70-gamemax.rules b/packaging/70-gamemax.rules new file mode 100644 index 0000000..31aed9f --- /dev/null +++ b/packaging/70-gamemax.rules @@ -0,0 +1,5 @@ +# Vendor-defined HID device used by GAMEMAX PcInfoMonitorPro (VID 0x5131, PID 0x2007). +# Grants the logged-in desktop user access to its hidraw node. +# Install: sudo cp 70-gamemax.rules /etc/udev/rules.d/ +# sudo udevadm control --reload && sudo udevadm trigger --subsystem-match=hidraw +SUBSYSTEM=="hidraw", ATTRS{idVendor}=="5131", ATTRS{idProduct}=="2007", TAG+="uaccess" diff --git a/packaging/build_appimage.sh b/packaging/build_appimage.sh new file mode 100755 index 0000000..a06c52b --- /dev/null +++ b/packaging/build_appimage.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# Build the GAMEMAX LCD tray app as an AppImage. +# +# bash packaging/build_appimage.sh [output_dir] +# +# Needs: uv (for the throwaway build venv) and network on first run. +# Produces dist/GAMEMAX-LCD-x86_64.AppImage with PySide6, the sender script and the icon. +set -euo pipefail + +PACKAGING_DIR="$(cd "$(dirname "$0")" && pwd)" +ROOT_DIR="$(cd "$PACKAGING_DIR/.." && pwd)" +OUT_DIR="${1:-$ROOT_DIR/dist}" +BUILD_DIR="${BUILD_DIR:-/tmp/gamemax-appimage}" +VENV="${VENV:-/tmp/gamemax-appimage-venv}" +APPIMAGETOOL_URL="https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage" + +mkdir -p "$OUT_DIR" "$BUILD_DIR" +cd "$BUILD_DIR" +cp "$ROOT_DIR/src/gamemax_gui.py" "$ROOT_DIR/src/gamemax_report.py" "$ROOT_DIR/src/icon.png" . + +# 1. throwaway venv with PySide6 + PyInstaller +if [ ! -x "$VENV/bin/pyinstaller" ]; then + uv venv "$VENV" + uv pip install --python "$VENV/bin/python" pyside6 pyinstaller +fi + +# 2. bundle the app (PySide6 + the sender script + the icon) +"$VENV/bin/pyinstaller" --noconfirm --windowed --name gamemax-lcd \ + --add-data "gamemax_report.py:." --add-data "icon.png:." gamemax_gui.py + +# 3. assemble the AppDir +APPDIR="$BUILD_DIR/AppDir" +rm -rf "$APPDIR" +mkdir -p "$APPDIR/usr/bin" +cp -r "$BUILD_DIR/dist/gamemax-lcd/." "$APPDIR/usr/bin/" +install -m 755 /dev/stdin "$APPDIR/AppRun" <<'EOF' +#!/bin/sh +HERE="$(dirname "$(readlink -f "$0")")" +exec "$HERE/usr/bin/gamemax-lcd" "$@" +EOF +cp "$ROOT_DIR/src/icon.png" "$APPDIR/gamemax-lcd.png" +cat > "$APPDIR/gamemax-lcd.desktop" <<'EOF' +[Desktop Entry] +Type=Application +Name=GAMEMAX IceBurg LCD +GenericName=AI LCD controller +Comment=Status, on/off, monitor, and settings for the GAMEMAX IceBurg AIO LCD +Exec=gamemax-lcd +Icon=gamemax-lcd +Terminal=false +Categories=System;Utility; +EOF + +# 4. package +if [ ! -x "$BUILD_DIR/appimagetool" ]; then + curl -fsSL "$APPIMAGETOOL_URL" -o "$BUILD_DIR/appimagetool" + chmod +x "$BUILD_DIR/appimagetool" +fi +OUT="$OUT_DIR/GAMEMAX-LCD-x86_64.AppImage" +ARCH=x86_64 "$BUILD_DIR/appimagetool" "$APPDIR" "$OUT" +chmod +x "$OUT" +echo "built: $OUT" +echo "verify: $OUT --selftest (or APPIMAGE_EXTRACT_AND_RUN=1 $OUT --selftest)" diff --git a/packaging/gamemax-report.service b/packaging/gamemax-report.service new file mode 100644 index 0000000..60914cf --- /dev/null +++ b/packaging/gamemax-report.service @@ -0,0 +1,13 @@ +[Unit] +Description=GAMEMAX HID sensor display bridge (PcInfoMonitorPro replacement) +Documentation=file:///mnt/SSD/Work/REVERSE-EGENERING/analysis/01-recon.md +After=graphical-session.target + +[Service] +Type=simple +ExecStart=/usr/bin/python3 /mnt/SSD/Work/REVERSE-EGENERING/analysis/tools/gamemax_report.py --unit c --interval 0.5 +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=default.target diff --git a/src/gamemax_gui.py b/src/gamemax_gui.py new file mode 100755 index 0000000..368d232 --- /dev/null +++ b/src/gamemax_gui.py @@ -0,0 +1,804 @@ +#!/usr/bin/env python3 +"""GAMEMAX IceBurg LCD — GUI tray: status, nyala/mati, pemantauan beranimasi, pengaturan. + +Streaming tetap dijalankan oleh layanan systemd (gamemax-report.service); GUI ini +mengendalikannya dan memakai gamemax_report.py sebagai pengirim. + + gamemax_gui.py # jendela + tray (default) + gamemax_gui.py --tray-only # tanpa jendela + gamemax_gui.py --selftest # uji muat tanpa tampilan (untuk build AppImage) +""" +import json +import math +import os +import shutil +import subprocess +import sys +import threading +import time +import traceback + +from PySide6.QtCore import QPointF, QRectF, Qt, QThread, QTimer, Signal +from PySide6.QtGui import (QAction, QColor, QConicalGradient, QFont, QIcon, + QPainter, QPen, QPixmap) +from PySide6.QtWidgets import ( + QApplication, QCheckBox, QComboBox, QFormLayout, QGroupBox, QHBoxLayout, QLabel, + QMenu, QPlainTextEdit, QProgressBar, QPushButton, QSystemTrayIcon, QVBoxLayout, QWidget, +) +from PySide6.QtNetwork import QLocalServer, QLocalSocket + +HERE = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, HERE) +import gamemax_report as gr # noqa: E402 + +SERVICE = "gamemax-report.service" +CONFIG_PATH = gr.CONFIG_PATH +INSTALL_DIR = os.path.expanduser("~/.local/share/gamemax-report") +UNIT_PATH = os.path.expanduser(f"~/.config/systemd/user/{SERVICE}") +RULE_PATH = "/etc/udev/rules.d/70-gamemax.rules" + +UNIT_TEMPLATE = """[Unit] +Description=GAMEMAX HID sensor display bridge (PcInfoMonitorPro replacement) +After=graphical-session.target + +[Service] +Type=simple +ExecStart=/usr/bin/python3 {script} --wait --interval {interval} --sample {sample} +Restart=always +RestartSec=3 + +[Install] +WantedBy=default.target +""" + +RULE_TEMPLATE = ('SUBSYSTEM=="hidraw", ATTRS{idVendor}=="5131", ATTRS{idProduct}=="2007", ' + 'TAG+="uaccess"\n') + +CRASH_LOG = os.path.join(os.path.dirname(CONFIG_PATH), "gui-crash.log") +ACCENT = QColor(222, 247, 80) # warna aksen GAMEMAX dari appConfig.ini +DIM = QColor(120, 128, 120) + + +def crash_log(text): + """Catat galat ke berkas supaya bisa diperiksa setelah aplikasi berhenti.""" + try: + os.makedirs(os.path.dirname(CRASH_LOG), exist_ok=True) + with open(CRASH_LOG, "a") as fh: + fh.write(time.strftime("[%Y-%m-%d %H:%M:%S] ") + text.rstrip() + "\n") + except OSError: + pass + + +def systemctl(*args): + return subprocess.run(["systemctl", "--user", *args], capture_output=True, text=True) + + +def service_active(): + return systemctl("is-active", SERVICE).stdout.strip() == "active" + + +def service_enabled(): + return systemctl("is-enabled", SERVICE).stdout.strip() == "enabled" + + +def dimmed_icon(path, opacity=0.35): + """Ikon tray versi redup untuk menandai layar tidak menampilkan sensor.""" + icon = QIcon(path) + pixmap = icon.pixmap(64, 64) + if pixmap.isNull(): + return icon + dim = QPixmap(pixmap.size()) + dim.fill(Qt.transparent) + painter = QPainter(dim) + painter.setOpacity(opacity) + painter.drawPixmap(0, 0, pixmap) + painter.end() + return QIcon(dim) + + +def icon_path(): + for name in ("icon.png", "icon.ico", "gamemax.png"): + path = os.path.join(HERE, name) + if os.path.exists(path): + return path + return "" + + +class Task(QThread): + """Menjalankan aksi lambat (systemctl/pkexec/salin berkas) di luar thread UI. + + PENTING: method yang dijalankan di sini tidak boleh menyentuh widget Qt + (membaca combo/checkbox atau memanggil refresh()); ambil nilainya di thread UI + dan kirim sebagai argumen. + """ + + done = Signal(str, bool, str) + + def __init__(self, label, fn): + super().__init__() + self.label, self.fn = label, fn + + def run(self): + try: + self.done.emit(self.label, True, self.fn() or "") + except Exception as exc: # noqa: BLE001 + self.done.emit(self.label, False, str(exc)) + + +class Animated: + """Nilai yang bergerak halus menuju target (digerakkan QTimer 33 ms).""" + + def __init__(self, value=0.0): + self.shown = value + self.target = value + + def tick(self, ease=0.18): + if abs(self.target - self.shown) < 0.5: + self.shown = self.target + else: + self.shown += (self.target - self.shown) * ease + return self.shown + + +class Gauge(QWidget): + """Busur 240 derajat untuk suhu (0..99 °C), dengan jarum dan angka besar.""" + + def __init__(self, title, vmax=99, unit="°C"): + super().__init__() + self.title, self.vmax, self.unit = title, vmax, unit + self.value = Animated() + self.setMinimumSize(220, 220) + + def set(self, value): + self.value.target = 0.0 if value is None else min(self.vmax, value) + + def tick(self): + self.value.tick(0.25) + self.update() + + def paintEvent(self, _): + p = QPainter(self) + p.setRenderHint(QPainter.Antialiasing) + w, h = self.width(), self.height() + side = min(w, h) - 12 + rect = QRectF((w - side) / 2, (h - side) / 2 + 6, side, side) + start, span = 210, -240 # derajat: kiri-bawah -> kanan-bawah + frac = max(0.0, min(1.0, self.value.shown / self.vmax)) + + p.setPen(QPen(QColor(58, 62, 58), 14, Qt.SolidLine, Qt.RoundCap)) + p.drawArc(rect, start * 16, span * 16) + if frac > 0: + grad = QConicalGradient(rect.center(), -60) + grad.setColorAt(0.0, ACCENT) + grad.setColorAt(0.5, QColor(255, 170, 60)) + grad.setColorAt(1.0, QColor(255, 90, 60)) + p.setPen(QPen(grad, 14, Qt.SolidLine, Qt.RoundCap)) + p.drawArc(rect, start * 16, int(span * frac * 16)) + + angle = math.radians(start + span * frac) + r = side / 2 - 8 + cx, cy = rect.center().x(), rect.center().y() + p.setPen(QPen(ACCENT, 5, Qt.SolidLine, Qt.RoundCap)) + p.drawLine(QPointF(cx, cy), QPointF(cx + r * math.cos(angle), cy - r * math.sin(angle))) + + p.setPen(ACCENT) + f = QFont(); f.setPointSize(max(22, side // 5)); f.setBold(True) + p.setFont(f) + p.drawText(QRectF(rect.x(), cy - side / 6, side, side / 3), Qt.AlignCenter, + f"{int(round(self.value.shown))}") + p.setPen(QColor(210, 214, 210)) + f.setPointSize(max(9, side // 14)); f.setBold(False) + p.setFont(f) + p.drawText(QRectF(rect.x(), cy + side / 8, side, side / 5), Qt.AlignCenter, + f"{self.unit} · {self.title}") + + +class Bar(QWidget): + """Bar horizontal beranimasi dengan label dan nilai.""" + + def __init__(self, title, vmax, unit=""): + super().__init__() + self.title, self.vmax, self.unit = title, vmax, unit + self.value = Animated() + self.setMinimumHeight(46) + + def set(self, value): + self.value.target = 0.0 if value is None else max(0.0, min(self.vmax, value)) + + def tick(self): + self.value.tick() + self.update() + + def paintEvent(self, _): + p = QPainter(self) + p.setRenderHint(QPainter.Antialiasing) + w, h = self.width(), self.height() + f = QFont(); f.setPointSize(10) + p.setFont(f) + p.setPen(QColor(210, 214, 210)) + frac = self.value.shown / self.vmax + shown = int(round(self.value.shown)) + p.drawText(QRectF(0, 0, w, 20), Qt.AlignLeft, self.title) + p.setPen(ACCENT) + p.drawText(QRectF(0, 0, w, 20), Qt.AlignRight, f"{shown}{self.unit}") + track = QRectF(0, h - 18, w, 12) + p.setPen(Qt.NoPen) + p.setBrush(QColor(58, 62, 58)) + p.drawRoundedRect(track, 6, 6) + if frac > 0.001: + fill = QRectF(0, h - 18, max(6.0, w * frac), 12) + p.setBrush(ACCENT if frac < 0.8 else QColor(255, 120, 70)) + p.drawRoundedRect(fill, 6, 6) + + +class Window(QWidget): + def __init__(self, tray): + super().__init__() + self.tray = tray + self.prev_stat = gr.stat_snapshot() + self.setWindowTitle("GAMEMAX IceBurg LCD") + self.setWindowIcon(QIcon(icon_path())) + self.setMinimumWidth(640) + root = QVBoxLayout(self) + + hint = QLabel("Kontrol layar LCD AIO GAMEMAX. Pilih slot kipas/sumber suhu di " + "Pengaturan lalu klik Simpan & terapkan.") + hint.setWordWrap(True) + hint.setStyleSheet("color:#c8ccc8;") + root.addWidget(hint) + + # ---- banner mode layar (jelas: normal / kosong / berhenti) + self.mode_banner = QLabel() + self.mode_banner.setAlignment(Qt.AlignCenter) + self.mode_banner.setMinimumHeight(34) + root.addWidget(self.mode_banner) + + # ---- header status + self.status = QLabel() + self.status.setStyleSheet("font-size: 13px;") + root.addWidget(self.status) + + # ---- kontrol utama + controls = QHBoxLayout() + self.toggle = QPushButton("Aktifkan layar") + self.toggle.setMinimumHeight(38) + self.toggle.setStyleSheet("font-weight: bold;") + self.toggle.clicked.connect(lambda: self.start_task("mengubah status layanan", self.on_toggle)) + self.toggle.setToolTip("Mulai/hentikan pengiriman data sensor ke layar LCD") + controls.addWidget(self.toggle, 2) + self.blank = QCheckBox("Layar kosong") + self.blank.toggled.connect(self.on_blank_clicked) + self.blank.setToolTip("Kirim nilai nol ke layar (panel tetap beranimasi)") + controls.addWidget(self.blank) + test = QPushButton("Kirim uji") + test.setToolTip("Kirim satu report contoh: 55 °C, beban 50 %, kipas 1500 RPM") + test.clicked.connect(self.send_test) + controls.addWidget(test) + root.addLayout(controls) + + # indikator proses berjalan (aksi dijalankan di thread terpisah) + self.busy = QProgressBar() + self.busy.setRange(0, 0) # mode tak tentu -> animasi berjalan + self.busy.setTextVisible(False) + self.busy.setFixedHeight(10) + self.busy.hide() + root.addWidget(self.busy) + self.busy_label = QLabel() + self.busy_label.setStyleSheet("color:#deF750;") + self.busy_label.hide() + root.addWidget(self.busy_label) + self.buttons = [self.toggle, test] + + # ---- papan monitor beranimasi + board = QGroupBox("Pemantauan langsung") + self.board = board + bl = QHBoxLayout(board) + self.gauge = Gauge("CPU", 99, "°C") + bl.addWidget(self.gauge, 1) + bars = QVBoxLayout() + self.bar_load = Bar("Beban CPU", 100, " %") + self.bar_fan = Bar("Kipas CPU (slot RPM)", 2000, " RPM") + self.bar_clock = Bar("Frekuensi CPU", 6000, " MHz") + for b in (self.bar_load, self.bar_fan, self.bar_clock): + bars.addWidget(b) + self.info = QLabel() + self.info.setStyleSheet("color:#c8ccc8;") + bars.addWidget(self.info) + bars.addStretch(1) + bl.addLayout(bars, 2) + root.addWidget(board) + + # ---- pengaturan + settings = QGroupBox("Pengaturan") + form = QFormLayout(settings) + self.fan = QComboBox() + self.fan.setToolTip("Kanal kipas yang dikirim ke layar; pilih kanal yang berputar " + "kalau kipas dipindah ke header lain") + self.temp = QComboBox() + form.addRow("Slot kipas (RPM)", self.fan) + form.addRow("Sumber suhu CPU", self.temp) + self.autostart = QCheckBox("Mulai otomatis saat login") + self.autostart.toggled.connect( + lambda checked: self.start_task("mulai otomatis saat login", + lambda: self.on_autostart(checked))) + form.addRow("", self.autostart) + row = QHBoxLayout() + save = QPushButton("Simpan && terapkan") + save.clicked.connect(self.on_save_clicked) + row.addWidget(save) + install = QPushButton("Pasang / perbarui layanan") + install.clicked.connect(lambda: self.start_task("memasang layanan", self.install_service)) + row.addWidget(install) + rule = QPushButton("Pasang aturan udev") + rule.clicked.connect(lambda: self.start_task("memasang aturan udev", self.install_rule)) + row.addWidget(rule) + self.buttons += [save, install, rule] + form.addRow("", row) + root.addWidget(settings) + + # ---- detail + log + self.detail = QPlainTextEdit() + self.detail.setReadOnly(True) + self.detail.setFixedHeight(110) + root.addWidget(self.detail) + self.logview = QPlainTextEdit() + self.logview.setReadOnly(True) + self.logview.setFixedHeight(64) + root.addWidget(self.logview) + + self.reload_choices() + self.reload_config() + + # 33 ms -> animasi; 1000 ms -> baca sensor + self.anim = QTimer(self, timeout=self.tick, interval=33) + self.anim.start() + self.poll = QTimer(self, timeout=self.refresh, interval=1000) + self.poll.start() + self.refresh() + if gr.load_config(CONFIG_PATH).get("blank"): + self.log("PERHATIAN: mode layar kosong sedang aktif dari konfigurasi " + "(layar menampilkan nilai nol). Hilangkan centang 'Layar kosong' " + "untuk kembali ke nilai sensor.") + + # -------------------------------------------------------------- pengaturan + def reload_choices(self): + self.fan.clear() + self.fan.addItem("Otomatis (kipas tercepat yang berputar)", "") + for c in gr.hwmon_channels("fan*_input"): + rpm = "" if c["value"] is None else f" — {int(c['value'])} RPM" + self.fan.addItem(f"{c['chip']} {c['file']}{rpm}", f"{c['chip']}/{c['file']}") + self.temp.clear() + self.temp.addItem("Otomatis (sensor CPU tertinggi)", "") + channels = [c for c in gr.hwmon_channels("temp*_input") if c["value"] is not None] + channels.sort(key=lambda c: (c["chip"] not in gr.CPU_CHIPS, c["chip"], c["file"])) + for c in channels: + name = c["label"] or c["file"] + tag = "" if c["chip"] in gr.CPU_CHIPS else " (bukan CPU) " + self.temp.addItem(f"{c['chip']}{tag} {name} — {c['value'] / 1000:.1f} °C", + f"{c['chip']}/{c['file']}") + + def reload_config(self): + cfg = gr.load_config(CONFIG_PATH) + for combo, key in ((self.fan, "fan_channel"), (self.temp, "temp_channel")): + idx = combo.findData(cfg.get(key) or "") + combo.setCurrentIndex(idx if idx >= 0 else 0) + self.autostart.blockSignals(True) + self.autostart.setChecked(service_enabled()) + self.autostart.blockSignals(False) + + def config(self): + return { + "fan_channel": self.fan.currentData() or None, + "temp_channel": self.temp.currentData() or None, + "unit": "c", # panel hanya punya label °C + "interval": 0.5, + "sample": 0.5, + "vendor_layout": False, + "blank": bool(self.blank.isChecked()), + } + + # -------------------------------------------------------------- tugas latar + def start_task(self, label, fn): + if getattr(self, "_task", None) is not None and self._task.isRunning(): + self.log("masih ada proses berjalan — tunggu sampai indikator selesai") + return + self.busy_label.setText(f"Sedang bekerja: {label}…") + self.busy.show() + self.busy_label.show() + for button in self.buttons: + button.setEnabled(False) + task = Task(label, fn) + task.done.connect(self.on_task_done) + self._task = task + task.start() + + def on_task_done(self, label, ok, message): + self.busy.hide() + self.busy_label.hide() + for button in self.buttons: + button.setEnabled(True) + self.log(("selesai: " if ok else "GAGAL: ") + label + (f" — {message}" if message else "")) + self.refresh() + + # -------------------------------------------------------------- aksi + def on_toggle(self): + try: + self.ensure_unit() + want_active = not service_active() + for attempt in (1, 2): + systemctl("start" if want_active else "stop", SERVICE) + if service_active() == want_active: + return (f"layanan {'AKTIF' if want_active else 'nonaktif'}" + + ("" if attempt == 1 else f" (percobaan ke-{attempt})")) + else: + return "status layanan tidak berubah seperti yang diminta" + except Exception as exc: # noqa: BLE001 + return f"galat: {exc}" + + def on_autostart(self, checked): + try: + self.ensure_unit() + systemctl("daemon-reload") + res = systemctl("enable" if checked else "disable", SERVICE) + state = service_enabled() + return (f"mulai otomatis saat login: {'AKTIF' if state else 'nonaktif'}" + + ("" if res.returncode == 0 else f" ({res.stderr.strip()})")) + except Exception as exc: # noqa: BLE001 + return f"galat autostart: {exc}" + + def on_blank_clicked(self, checked): + """Dijalankan di thread UI: baca widget di sini, kerjakan sisanya di latar.""" + cfg = self.config() + cfg["blank"] = bool(checked) + self.start_task("mode layar kosong", lambda: self.on_blank(checked, cfg)) + + def on_blank(self, checked, cfg): + """Mode layar kosong ditangani pengirim (config "blank").""" + try: + self.write_config(cfg) + self.ensure_unit(cfg) + if checked and not service_active(): + systemctl("start", SERVICE) + elif service_active(): + systemctl("restart", SERVICE) + return ("layar kosong: AKTIF (report bernilai nol)" if checked + else "layar kosong: nonaktif (kembali ke nilai sensor)") + except Exception as exc: # noqa: BLE001 + return f"galat mode layar kosong: {exc}" + + def write_config(self, cfg): + os.makedirs(os.path.dirname(CONFIG_PATH), exist_ok=True) + with open(CONFIG_PATH, "w") as fh: + json.dump(cfg, fh, indent=2) + + def ensure_unit(self, cfg=None): + if not os.path.exists(UNIT_PATH): + self.install_service(cfg) + + def send_test(self): + node = gr.find_device() + if not node: + self.log("perangkat tidak terdeteksi") + return + v = gr.read_sensors(self.prev_stat, {"fan_channel": self.fan.currentData(), + "temp_channel": self.temp.currentData()}) + v.update({"cpu_temp": 55, "gpu_temp": 60, "cpu_load": 50, "cpu_fan": 1500, + "cpu_clock": 4000, "cpu_power": 66}) + try: + with open(node, "wb", buffering=0) as fh: + fh.write(gr.build_report(v, "c")[1:]) + self.log(f"report uji terkirim ke {node} (55 °C / 50 % / 1500 RPM)") + except OSError as exc: + self.log(f"gagal mengirim uji: {exc}") + + def install_service(self, cfg=None): + try: + os.makedirs(INSTALL_DIR, exist_ok=True) + script = os.path.join(INSTALL_DIR, "gamemax_report.py") + shutil.copyfile(os.path.join(HERE, "gamemax_report.py"), script) + os.makedirs(os.path.dirname(UNIT_PATH), exist_ok=True) + cfg = cfg or {} + with open(UNIT_PATH, "w") as fh: + fh.write(UNIT_TEMPLATE.format(script=script, + interval=cfg.get("interval", 0.5), + sample=cfg.get("sample", 0.5))) + systemctl("daemon-reload") + return f"layanan dipasang: {UNIT_PATH}" + except Exception as exc: # noqa: BLE001 + return f"gagal memasang layanan: {exc}" + + def install_rule(self): + script = "/tmp/gamemax-udev-install.sh" + try: + with open(script, "w") as fh: + fh.write("#!/bin/sh\n" + f"cat > {RULE_PATH} <<'EOF'\n{RULE_TEMPLATE}EOF\n" + "udevadm control --reload\n" + "udevadm trigger --subsystem-match=hidraw\n") + os.chmod(script, 0o755) + res = subprocess.run(["pkexec", "sh", script], capture_output=True, text=True) + return ("aturan udev dipasang" if res.returncode == 0 + else f"gagal memasang udev: {res.stderr.strip() or res.returncode}") + except FileNotFoundError: + return f"pkexec tidak tersedia; jalankan manual: sudo sh {script}" + except Exception as exc: # noqa: BLE001 + return f"galat udev: {exc}" + + def fix_fan_choice(self): + """Slot kipas terpilih yang diam sementara ada kipas lain berputar akan dialihkan.""" + if not self.fan.currentData(): + return "" + spinning = [(c["chip"], c["file"], int(c["value"])) for c in gr.hwmon_channels("fan*_input") + if c["value"] and c["chip"] not in gr.GPU_CHIPS] + if gr.channel_value(self.fan.currentData()) or not spinning: + return "" + chip, fname, rpm = max(spinning, key=lambda t: t[2]) + idx = self.fan.findData(f"{chip}/{fname}") + if idx < 0: + return "" + old = self.fan.currentText() + self.fan.setCurrentIndex(idx) + return f"slot lama membaca 0 RPM ({old.split(' —')[0]}) -> dialihkan ke {chip} {fname} ({rpm} RPM)" + + def on_save_clicked(self): + """Thread UI: koreksi slot kipas lalu baca pengaturan sebelum dikerjakan.""" + note = self.fix_fan_choice() + self.start_task("menyimpan pengaturan", + lambda: self.save_settings(self.config(), note)) + + def save_settings(self, cfg, note=""): + try: + self.write_config(cfg) + self.ensure_unit(cfg) + if service_active(): + systemctl("restart", SERVICE) + tail = " (layanan dijalankan ulang)" + else: + systemctl("start", SERVICE) + tail = " (layanan dinyalakan)" + return "pengaturan disimpan & diterapkan" + tail + (f" | {note}" if note else "") + except Exception as exc: # noqa: BLE001 + return f"gagal menyimpan: {exc}" + + def log(self, text): + self.logview.appendPlainText(text) + + def warn_once(self, text): + if getattr(self, "_warned", None) != text: + self._warned = text + self.log(text) + + # -------------------------------------------------------------- refresh + def refresh(self): + try: + active = service_active() + node = gr.find_device() + enabled = service_enabled() + blank_on = bool(gr.load_config(CONFIG_PATH).get("blank")) + mode = "normal" if active and not blank_on else ("kosong" if blank_on else "berhenti") + banner = { + "normal": ("Layar menampilkan data sensor", "#1d3b1d", "#b8f5b8"), + "kosong": ("LAYAR KOSONG — panel menampilkan nilai nol (animasi firmware tetap jalan)", + "#4a3a10", "#ffd479"), + "berhenti": ("PENGIRIMAN DIHENTIKAN — panel menampilkan data terakhir yang diterima", + "#3a3a3a", "#d0d0d0"), + }[mode] + self.mode_banner.setText(banner[0]) + self.board.setTitle({ + "normal": "Pemantauan langsung — nilai ini yang dikirim ke layar", + "kosong": "Pemantauan langsung — nilai sensor (yang DIKIRIM ke layar: nol)", + "berhenti": "Pemantauan langsung — nilai sensor (TIDAK dikirim, layanan mati)", + }[mode]) + self.mode_banner.setStyleSheet( + f"background:{banner[1]}; color:{banner[2]}; border-radius:4px; " + "font-weight:bold; padding:4px;") + if getattr(self, "_mode", None) != mode: + self._mode = mode + labels = {"normal": "Layar kembali menampilkan data sensor", + "kosong": "Layar dikosongkan (nilai nol)", + "berhenti": "Pengiriman data dihentikan"} + if mode != "normal" or getattr(self, "_mode_seen", False): + subprocess.run(["notify-send", "-a", "GAMEMAX LCD", "Status layar", + labels[mode]], capture_output=True) + self._mode_seen = True + dot = "🟢" if active else "⚪" + self.status.setText( + f"{dot} Perangkat: {node or 'tidak terdeteksi'}  ·  " + f"Layanan: {'AKTIF' if active else 'nonaktif'}  ·  " + f"Mulai otomatis: {'ya' if enabled else 'tidak'}" + + ("  ·  Layar: KOSONG (nilai nol)" + if blank_on else "")) + self.toggle.setText("Matikan layar" if active else "Aktifkan layar") + self.autostart.blockSignals(True) + self.autostart.setChecked(enabled) + self.autostart.blockSignals(False) + self.blank.blockSignals(True) + self.blank.setChecked(bool(gr.load_config(CONFIG_PATH).get("blank"))) + self.blank.blockSignals(False) + self.tray.sync(active) + + cfg = {"fan_channel": self.fan.currentData(), + "temp_channel": self.temp.currentData()} + v = gr.read_sensors(self.prev_stat, cfg) + self.prev_stat = gr.stat_snapshot() + self.gauge.set(v["cpu_temp"]) + self.bar_load.set(v["cpu_load"]) + self.bar_fan.set(v["cpu_fan"]) + spinning = [(c["chip"], c["file"], int(c["value"])) for c in gr.hwmon_channels("fan*_input") + if c["value"] and c["chip"] not in gr.GPU_CHIPS] + if self.fan.currentData() and not (v["cpu_fan"] or 0) and spinning: + best = max(spinning, key=lambda t: t[2]) + self.warn_once(f"slot kipas terpilih membaca 0 RPM; kipas berputar ada di " + f"{best[0]} {best[1]} ({best[2]} RPM) — pilih itu lalu Simpan") + self.bar_clock.set(v["cpu_clock"]) + self.detail.setPlainText( + (f"Daya CPU : {v['cpu_power']:.0f} W\n" if v["cpu_power"] else "Daya CPU : —\n") + + (f"GPU : {v['gpu_temp']:.0f} °C · beban {v['gpu_load'] or '—'} % · " + f"{int(v['gpu_clock'] or 0)} MHz\n" if v["gpu_temp"] else "GPU : —\n") + + (f"Memori : {v['ram_load']} % dari {int(v['ram_mb'])} MiB\n" + if v["ram_load"] and v["ram_mb"] else "Memori : —\n") + + (f"Penyimpanan : {v['disk_free']} % kosong dari {v['disk_gb']:.0f} GB\n" + if v["disk_free"] and v["disk_gb"] else "Penyimpanan : —\n") + + "Isi report : " + gr.build_report(v, "c").hex(" ")) + except Exception as exc: # noqa: BLE001 + self.log(f"galat pembaruan: {exc}") + if os.environ.get("GAMEMAX_DEBUG"): + self.log(traceback.format_exc()) + + def tick(self): + for widget in (self.gauge, self.bar_load, self.bar_fan, self.bar_clock): + widget.tick() + + +class Tray: + def __init__(self, app): + self.app = app + self.icon = QSystemTrayIcon(QIcon(icon_path()), app) + self.blank_action = QAction("Layar kosong (nilai nol)", app) + self.blank_action.setCheckable(True) + menu = QMenu() + show = QAction("Buka jendela", menu) + show.triggered.connect(self.show_window) + toggle = QAction("Aktifkan / matikan", menu) + toggle.triggered.connect(lambda: self.window.on_toggle()) + self.blank_action.triggered.connect(lambda checked: self.window.blank.setChecked(checked)) + quit_action = QAction("Keluar", menu) + quit_action.triggered.connect(app.quit) + menu.addAction(show) + menu.addAction(toggle) + menu.addAction(self.blank_action) + menu.addSeparator() + menu.addAction(quit_action) + self.icon.setContextMenu(menu) + self.icon.activated.connect( + lambda reason: self.show_window() if reason == QSystemTrayIcon.Trigger else None) + self.window = Window(self) + self.icon.show() + + def sync(self, active): + blank = bool(gr.load_config(CONFIG_PATH).get("blank")) + state = ("layar kosong (nilai nol)" if blank and active + else ("pengiriman dihentikan" if not active else "normal")) + self.icon.setToolTip(f"GAMEMAX LCD: {state}") + base = icon_path() + self.icon.setIcon(dimmed_icon(base) if state != "normal" else QIcon(base)) + window = getattr(self, "window", None) + if window is not None: + self.blank_action.setChecked(window.blank.isChecked()) + + def show_window(self): + self.window.showNormal() # keluar dari minimize + self.window.setWindowState((self.window.windowState() & ~Qt.WindowMinimized) + | Qt.WindowActive) + self.window.raise_() + self.window.activateWindow() + if QSystemTrayIcon.isSystemTrayAvailable(): + self.icon.showMessage("GAMEMAX LCD", "Jendela dibuka dari permintaan kedua.", + QSystemTrayIcon.Information, 3000) + + +SOCKET_NAME = "gamemax-lcd-" + os.environ.get("USER", "user") + + +def main(): + try: + return _main() + except Exception: # noqa: BLE001 + crash_log("FATAL\n" + traceback.format_exc()) + raise + + +def _main(): + app = QApplication(sys.argv) + app.setApplicationName("GAMEMAX LCD") + app.setQuitOnLastWindowClosed(False) + + # hanya satu instance: yang kedua memunculkan jendela yang sudah ada lalu keluar + probe = QLocalSocket() + probe.connectToServer(SOCKET_NAME) + if probe.waitForConnected(400): + probe.write(b"raise") + probe.waitForBytesWritten(400) + print("GAMEMAX LCD sudah berjalan — instance pertama diminta membuka jendelanya.") + # Beri tahu lewat notifikasi desktop juga, karena keluarnya proses kedua bisa + # terlihat seperti crash saat diluncurkan dari menu. + subprocess.run(["notify-send", "-a", "GAMEMAX LCD", "Sudah berjalan", + "Aplikasi sudah aktif — jendelanya dibuka, cek taskbar/tray."], + capture_output=True) + return 0 + QLocalServer.removeServer(SOCKET_NAME) + server = QLocalServer() + server.listen(SOCKET_NAME) + + tray = Tray(app) + server.newConnection.connect(lambda: tray.show_window()) + app.aboutToQuit.connect(lambda: (server.close(), QLocalServer.removeServer(SOCKET_NAME))) + # Jendela selalu dibuka saat diluncurkan; tray tetap ada kalau didukung desktop. + tray.show_window() + if "--tray-only" in sys.argv: + tray.window.hide() + if not QSystemTrayIcon.isSystemTrayAvailable(): + tray.window.log("Tray tidak tersedia di desktop ini — pakai jendela ini untuk kontrol.") + def report_exception(*tb): + text = "".join(traceback.format_exception(*tb)).strip() + crash_log(text) + try: + tray.window.log("GALAT: " + text.splitlines()[-1]) + except Exception: # noqa: BLE001 + pass + + sys.excepthook = report_exception + threading.excepthook = lambda args: report_exception(args.exc_type, args.exc_value, args.exc_traceback) + if "--selftest-actions" in sys.argv: # uji aksi GUI pada bundel beku + w = tray.window + steps = (("simpan & terapkan", lambda: w.save_settings(w.config())), + ("layar kosong ON", lambda: w.on_blank(True, {**w.config(), "blank": True})), + ("layar kosong OFF", lambda: w.on_blank(False, {**w.config(), "blank": False})), + ("matikan layar", w.on_toggle), + ("nyalakan layar", w.on_toggle), + ("autostart ON", lambda: w.on_autostart(True)), + ("kirim uji", w.send_test), + ("pasang layanan", lambda: w.install_service(w.config()))) + for name, fn in steps: + try: + fn() + print(f"[ OK ] {name}") + except Exception as exc: # noqa: BLE001 + print(f"[GAGAL] {name}: {exc}") + # jalur asinkron yang dipakai tombol: centang layar kosong + simpan + def wait_task(seconds=10): + t0 = time.time() + while time.time() - t0 < seconds: + task = getattr(w, "_task", None) + if task is not None and not task.isRunning(): + break + app.processEvents() + time.sleep(0.05) + for _ in range(10): + app.processEvents() + time.sleep(0.02) + + for name, trigger in (("centang layar kosong", lambda: w.blank.setChecked(True)), + ("lepas centang", lambda: w.blank.setChecked(False)), + ("simpan lewat tombol", w.on_save_clicked)): + try: + trigger() + wait_task() + print(f"[ OK ] {name} (asinkron)") + except Exception as exc: # noqa: BLE001 + print(f"[GAGAL] {name} (asinkron): {exc}") + w.refresh() + print("log:", " | ".join(w.logview.toPlainText().splitlines()[-6:])) + return 0 + if "--selftest" in sys.argv: + QTimer.singleShot(1200, app.quit) + rc = app.exec() + if "--selftest" in sys.argv: + print(f"selftest OK (kipas={tray.window.fan.count()} suhu={tray.window.temp.count()})") + return rc + + +if __name__ == "__main__": + if "--selftest" in sys.argv: + os.environ.setdefault("QT_QPA_PLATFORM", "offscreen") + sys.exit(main()) diff --git a/src/gamemax_report.py b/src/gamemax_report.py new file mode 100755 index 0000000..4d2fc8f --- /dev/null +++ b/src/gamemax_report.py @@ -0,0 +1,443 @@ +#!/usr/bin/env python3 +"""Push hardware sensor data to a GAMEMAX AIO LCD (HID VID 0x5131, PID 0x2007). + +Reverse-engineered from PcInfoMonitorPro.exe (GAMEMAX V1.0.0.04) — see ../01-recon.md. +Report layout, derived from DMainWidget.onGetPcInfoOk: + + byte 0 report ID, always 0 + byte 1 64 (0x40), payload length + byte 2 CPU temp (0..127). The original app ORs 0x80 for Celsius, but this + firmware ignores every value >= 128, so we send plain numbers + byte 3 CPU load % + byte 4..5 RPM slot (big-endian u16) -- panel renders this field next to the fan icon + byte 6..7 CPU clock MHz (big-endian u16) -- original app's byte order + byte 8..9 CPU power W (big-endian u16) + byte 10 GPU temp (0..127), same rule as CPU temp + byte 11 GPU load % + byte 12..13 GPU clock MHz (big-endian u16) + byte 14..15 GPU fan RPM (big-endian u16) + byte 16..17 GPU power W (big-endian u16) + byte 18 RAM usage % + byte 19..20 total RAM MiB (big-endian u16) + byte 21 disk free % + byte 22..23 total disk GB (big-endian u16) + byte 24..64 zero + +The panel reads byte 4..5 for the "RPM" field while the original app puts the CPU +clock there, so by default the two values are swapped so the panel shows a real fan +speed; --vendor-layout restores the original placement. + +Observed ceiling: the interrupt OUT endpoint (bInterval 160 ms) accepts about +8 reports/s and each hidraw write blocks until its URB completes. + +Plug and play: with --wait the process stays alive, waits for the device to appear +and keeps streaming through unplug/replug, which is what the systemd unit uses. + + python gamemax_report.py --dry-run --cpu-temp 55 + python gamemax_report.py --wait # service mode + python gamemax_report.py --list-sensors # JSON for the GUI +""" +import argparse +import glob +import json +import os +import select +import signal +import sys +import threading +import time + +VID, PID = 0x5131, 0x2007 +REPORT_SIZE = 65 +CONFIG_PATH = os.path.expanduser("~/.config/gamemax-report/config.json") +VALUE_KEYS = ("cpu_temp", "gpu_temp", "cpu_load", "cpu_clock", "cpu_fan", "cpu_power", + "gpu_load", "gpu_clock", "gpu_fan", "gpu_power", + "ram_load", "ram_mb", "disk_free", "disk_gb") +CONFIG_KEYS = ("fan_channel", "temp_channel", "unit", "interval", "sample", + "flag_celsius", "vendor_layout", "disk_path", "blank") + + +def load_config(path=CONFIG_PATH): + try: + with open(path) as fh: + data = json.load(fh) + return data if isinstance(data, dict) else {} + except (OSError, ValueError): + return {} + + +def u16(value): + v = max(0, min(0xFFFF, int(value or 0))) + return bytes((v >> 8, v & 0xFF)) + + +def temp_byte(value, unit, flag_celsius=False): + """Wire values are Celsius 0..127. + + The original app ORs 0x80 when the UI unit is Celsius; the IceBurg panel rejects + values >= 128 (it keeps showing the last accepted one), so we only do that when + --flag-celsius is requested. --unit f converts the supplied Fahrenheit values. + """ + if value is None: + return 0 + # The panel shows at most two digits and its unit label is fixed to Celsius, so + # values above 99 are clamped (verified on hardware); --unit f sends the number + # as-is for fidelity with the original app, but the panel still labels it °C. + v = max(0, min(99, int(round(value)))) + return v | 0x80 if flag_celsius else v + + +def build_report(v, unit, flag_celsius=False, vendor_layout=False): + r = bytearray(REPORT_SIZE) + clock, fan = v.get("cpu_clock"), v.get("cpu_fan") + if not vendor_layout: # this panel renders byte 4..5 in the slot labelled RPM + clock, fan = fan, clock + r[0] = 0 + r[1] = 64 + r[2] = temp_byte(v.get("cpu_temp"), unit, flag_celsius) + r[3] = int(v.get("cpu_load") or 0) & 0xFF + r[4:6] = u16(clock) + r[6:8] = u16(fan) + r[8:10] = u16(v.get("cpu_power")) + r[10] = temp_byte(v.get("gpu_temp"), unit, flag_celsius) + r[11] = int(v.get("gpu_load") or 0) & 0xFF + r[12:14] = u16(v.get("gpu_clock")) + r[14:16] = u16(v.get("gpu_fan")) + r[16:18] = u16(v.get("gpu_power")) + r[18] = int(v.get("ram_load") or 0) & 0xFF + r[19:21] = u16(v.get("ram_mb")) + r[21] = int(v.get("disk_free") or 0) & 0xFF + r[22:24] = u16(v.get("disk_gb")) + return bytes(r) + + +def self_check(): + """Lock the protocol shape the original enforces.""" + r = build_report({"cpu_temp": 60, "gpu_temp": 70, "cpu_clock": 5000, "cpu_fan": 1200, + "cpu_power": 88, "gpu_power": 250, "ram_load": 42, "ram_mb": 32768, + "disk_free": 30, "disk_gb": 1951}, "c") + assert len(r) == REPORT_SIZE, len(r) + assert r[0] == 0 and r[1] == 64, r[:2].hex() + assert r[2] == 60 and r[10] == 70, (r[2], r[10]) # plain Celsius, no flag + flagged = build_report({"cpu_temp": 60}, "c", flag_celsius=True) + assert flagged[2] == 0xBC, hex(flagged[2]) # original app's byte + assert r[4:6] == b"\x04\xb0" and r[6:8] == b"\x13\x88" # fan in RPM slot, BE + vendor = build_report({"cpu_clock": 5000, "cpu_fan": 1200}, "c", vendor_layout=True) + assert vendor[4:6] == b"\x13\x88" and vendor[6:8] == b"\x04\xb0" # original placement + assert r[8:10] == b"\x00\x58" and r[16:18] == b"\x00\xfa" + assert r[18] == 42 and r[19:21] == b"\x80\x00" # 32768 MiB + assert r[21] == 30 and r[22:24] == b"\x07\x9f" # 1951 GB + assert r[24:] == bytes(41) + assert build_report({"cpu_temp": 100}, "f")[2] == 99 # clamped to two digits + assert build_report({"cpu_temp": 77}, "f")[2] == 77 # Fahrenheit sent as-is + return r + + +# ---------------------------------------------------------------- hwmon access + +def hwmon_read(path, scale=1.0): + try: + with open(path) as fh: + return float(fh.read().strip()) / scale + except (OSError, ValueError): + return None + + +def hwmon_channels(pattern="fan*_input"): + """List every hwmon channel as {"chip", "file", "label", "value"}.""" + out = [] + for path in sorted(glob.glob(f"/sys/class/hwmon/hwmon*/{pattern}")): + base, fname = os.path.dirname(path), os.path.basename(path) + try: + chip = open(os.path.join(base, "name")).read().strip() + except OSError: + continue + label = None + try: + label = open(os.path.join(base, fname.replace("_input", "_label"))).read().strip() + except OSError: + pass + out.append({"chip": chip, "file": fname, "label": label, + "value": hwmon_read(path)}) + return out + + +def channel_value(spec, scale=1.0): + """Read an explicit channel like "nct6798/fan2_input".""" + if not spec or "/" not in spec: + return None + chip, fname = spec.split("/", 1) + for path in glob.glob(f"/sys/class/hwmon/hwmon*/{fname}"): + try: + if open(os.path.join(os.path.dirname(path), "name")).read().strip() != chip: + continue + except OSError: + continue + return hwmon_read(path, scale) + return None + + +def hwmon_max(chips, pattern="temp*_input", scale=1.0): + """Highest matching reading; a CPU exposes Tctl plus per-CCD Tccd sensors.""" + best = None + for ch in hwmon_channels(pattern): + if not any(c == "*" or c in ch["chip"] for c in chips): + continue + if ch["value"] is None: + continue + value = ch["value"] / scale + if best is None or value > best: + best = value + return best + + +CPU_CHIPS = ["k10temp", "coretemp", "zenpower", "cpu_thermal"] +GPU_CHIPS = ["amdgpu", "nouveau", "i915"] + + +def cpu_temp(cfg): + scale = 1000.0 + explicit = channel_value(cfg.get("temp_channel"), scale) + if explicit is not None: + return explicit + return (hwmon_max(CPU_CHIPS, "temp*_input", scale) + or hwmon_max(CPU_CHIPS, "temp1_input", scale)) + + +def cpu_fan(cfg): + explicit = channel_value(cfg.get("fan_channel")) + if explicit is not None: + return explicit + fans = [c["value"] for c in hwmon_channels("fan*_input") + if c["value"] and c["chip"] not in GPU_CHIPS] + return max(fans) if fans else 0 + + +def meminfo(key): + try: + with open("/proc/meminfo") as fh: + for line in fh: + if line.startswith(key): + return float(line.split()[1]) # kB + except OSError: + pass + return None + + +def stat_snapshot(): + with open("/proc/stat") as fh: + p = [int(x) for x in fh.readline().split()[1:]] + return p[3] + p[4], sum(p) + + +def load_pct(prev, now): + idle, total = prev + idle2, total2 = now + return None if total2 == total else round(100 * (1 - (idle2 - idle) / (total2 - total))) + + +def read_sensors(prev=None, cfg=None): + cfg = cfg or {} + total_kb, avail_kb = meminfo("MemTotal"), meminfo("MemAvailable") + try: + st = os.statvfs(cfg.get("disk_path") or "/") + disk_free = round(100 * st.f_bavail / st.f_blocks) if st.f_blocks else None + disk_gb = st.f_blocks * st.f_frsize / 2**30 + except OSError: + disk_free = disk_gb = None + return { + "cpu_temp": cpu_temp(cfg), # Celsius; temp_byte handles the unit + "gpu_temp": hwmon_max(GPU_CHIPS, "temp*_input", 1000.0), + "cpu_load": None if prev is None else load_pct(prev, stat_snapshot()), + "cpu_clock": hwmon_read("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", 1000.0), + "cpu_fan": cpu_fan(cfg), + "cpu_power": hwmon_max(CPU_CHIPS, "power*_input", 1e6), + "gpu_clock": (hwmon_max(GPU_CHIPS, "freq*_input", 1e6) + or hwmon_read("/sys/class/drm/card0/device/pp_dpm_sclk")), + "gpu_fan": hwmon_max(GPU_CHIPS, "fan*_input") or 0, + "gpu_load": hwmon_max(GPU_CHIPS, "gpu_busy_percent"), + "gpu_power": hwmon_max(GPU_CHIPS, "power*_input", 1e6), + "ram_load": None if not (total_kb and avail_kb) else round(100 * (1 - avail_kb / total_kb)), + "ram_mb": None if not total_kb else total_kb / 1024, + "disk_free": disk_free, + "disk_gb": disk_gb, + } + + +class Sampler(threading.Thread): + """Refresh sensor values in the background so the send cadence stays independent.""" + + def __init__(self, interval, cfg=None): + super().__init__(daemon=True) + self.interval = interval + self.cfg = cfg or {} + self.values = {} + self.lock = threading.Lock() + self.stop = threading.Event() + self.prev = stat_snapshot() + + def run(self): + while not self.stop.is_set(): + now = stat_snapshot() + v = read_sensors(self.prev, self.cfg) + self.prev = now + with self.lock: + self.values = v + self.stop.wait(self.interval) + + def snapshot(self): + with self.lock: + return dict(self.values) + + +def find_device(): + """Return the hidraw node whose HID_ID reports VID:PID 5131:2007.""" + want = f"{VID:08X}:{PID:08X}" + for uevent in sorted(glob.glob("/sys/class/hidraw/hidraw*/device/uevent")): + try: + text = open(uevent).read() + except OSError: + continue + if want in text.upper(): + return "/dev/" + uevent.split("/")[4] + return None + + +def stream(a, overrides): + """Open the device and stream reports. Returns (sent, seconds).""" + node = a.device or find_device() + if not node: + return None + fd = os.open(node, os.O_RDWR) + print(f"terbuka {node} ({VID:#06x}:{PID:#06x})", flush=True) + sampler = Sampler(a.sample, {"fan_channel": a.fan_channel, "temp_channel": a.temp_channel}) + sampler.start() + time.sleep(min(a.sample, 0.5)) # wait for the first sample + sent, t0 = 0, time.time() + try: + while a.count == 0 or sent < a.count: + v = {} if a.blank else sampler.snapshot() + v.update(overrides) + os.write(fd, build_report(v, a.unit, a.flag_celsius, a.vendor_layout)[1:]) + sent += 1 + time.sleep(a.interval) + finally: + sampler.stop.set() + os.close(fd) + return sent, time.time() - t0 + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--dry-run", action="store_true", help="print the report instead of sending it") + ap.add_argument("--listen", type=float, metavar="SECONDS", + help="passively print device->host reports for this long") + ap.add_argument("--device", help="hidraw node; default: auto-detect by VID:PID") + ap.add_argument("--unit", choices=["c", "f"], help="unit of the values you supply") + ap.add_argument("--interval", type=float, help="seconds between reports (device caps at ~8/s)") + ap.add_argument("--sample", type=float, help="sensor refresh interval") + ap.add_argument("--count", type=int, default=0, help="stop after N reports (0 = run until Ctrl-C)") + ap.add_argument("--flag-celsius", action="store_true", default=None, + help="emit the original app's 0x80 Celsius flag (this firmware ignores it)") + ap.add_argument("--vendor-layout", action="store_true", default=None, + help="original app's byte order (clock lands in the panel's RPM slot)") + ap.add_argument("--fan-channel", help='explicit fan channel, e.g. "nct6798/fan2_input"') + ap.add_argument("--temp-channel", help='explicit temp channel, e.g. "k10temp/temp3_input"') + ap.add_argument("--blank", action="store_true", default=None, + help="kirim report bernilai nol (mode 'layar kosong')") + ap.add_argument("--wait", action="store_true", + help="stay alive and wait for the device (plug and play, service mode)") + ap.add_argument("--list-sensors", action="store_true", + help="print available fan/temp channels as JSON and exit") + ap.add_argument("--config", default=CONFIG_PATH, help="JSON config path") + for key in VALUE_KEYS: + ap.add_argument(f"--{key.replace('_', '-')}", type=float, default=None) + a = ap.parse_args() + + if a.list_sensors: + print(json.dumps({ + "fans": hwmon_channels("fan*_input"), + "temps": hwmon_channels("temp*_input"), + "cpu_chips": CPU_CHIPS, + "gpu_chips": GPU_CHIPS, + "device": find_device(), + "config": load_config(a.config), + }, indent=2)) + return 0 + + print("pemeriksaan format:", self_check().hex(" "), flush=True) + + # config provides defaults; explicit flags win + cfg = load_config(a.config) + for key in CONFIG_KEYS: + if getattr(a, key, None) is None and cfg.get(key) is not None: + setattr(a, key, cfg[key]) + a.unit = a.unit or "c" + a.interval = 0.5 if a.interval is None else a.interval + a.sample = 0.5 if a.sample is None else a.sample + a.flag_celsius = bool(a.flag_celsius) + a.vendor_layout = bool(a.vendor_layout) + a.blank = bool(a.blank) + + overrides = {k: getattr(a, k) for k in VALUE_KEYS if getattr(a, k) is not None} + + if a.dry_run: + v = {} if a.blank else read_sensors(stat_snapshot(), {"fan_channel": a.fan_channel, + "temp_channel": a.temp_channel}) + v.update(overrides) + print("nilai:", {k: (round(x, 1) if isinstance(x, float) else x) + for k, x in sorted(v.items())}) + print("isi report:", build_report(v, a.unit, a.flag_celsius, a.vendor_layout).hex(" ")) + return 0 + + if a.listen: + node = a.device or find_device() + if not node: + print(f"node hidraw untuk {VID:#06x}:{PID:#06x} tidak ditemukan", file=sys.stderr) + return 1 + fd = os.open(node, os.O_RDONLY | os.O_NONBLOCK) + print(f"mendengarkan di {node} selama {a.listen} detik") + deadline, seen = time.time() + a.listen, 0 + try: + while time.time() < deadline: + if select.select([fd], [], [], 0.3)[0]: + seen += 1 + print(f" report {seen}: {os.read(fd, 64).hex(' ')}") + finally: + os.close(fd) + print(f"report diterima: {seen}") + return 0 + + if not a.wait: + result = stream(a, overrides) + if result is None: + print(f"node hidraw untuk {VID:#06x}:{PID:#06x} tidak ditemukan", file=sys.stderr) + return 1 + sent, dt = result + print(f"terkirim {sent} report ({sent / dt:.1f}/detik)") + return 0 + + # plug and play: wait for the device, stream, and go back to waiting on unplug + stop = threading.Event() + signal.signal(signal.SIGTERM, lambda *_: stop.set()) + signal.signal(signal.SIGINT, lambda *_: stop.set()) + print(f"menunggu {VID:#06x}:{PID:#06x} (Ctrl-C atau SIGTERM untuk berhenti)", flush=True) + while not stop.is_set(): + if not find_device(): + stop.wait(2) + continue + try: + result = stream(a, overrides) + if result: + sent, dt = result + print(f"perangkat terlepas setelah {sent} report ({sent / dt:.1f}/detik), menunggu lagi", flush=True) + except OSError as exc: + print(f"galat perangkat ({exc}), menunggu lagi", flush=True) + stop.wait(2) + print("berhenti") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/src/icon.png b/src/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..d1cd797ea2298fec0a4a875be87a718f957d9332 GIT binary patch literal 14550 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 literal 0 HcmV?d00001 diff --git a/tools/ildump.py b/tools/ildump.py new file mode 100755 index 0000000..a5c61be --- /dev/null +++ b/tools/ildump.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 +"""Dump MSIL of methods in a .NET/mixed-mode assembly with resolved operands. + +Usage: + ildump.py list + ildump.py dump + ildump.py callers +""" +import re +import sys + +import dnfile +from dncil.cil.body.reader import read_method_body_from_bytes + +TBL = {0x01: "TypeRef", 0x02: "TypeDef", 0x04: "Field", 0x06: "MethodDef", + 0x0A: "MemberRef", 0x1B: "TypeSpec", 0x2B: "MethodSpec", 0x70: "String"} +CALLISH = {"call", "callvirt", "ldftn", "newobj", "ldvirtftn", "jmp"} + + +def type_name(pe, row): + if row is None: + return "?" + for attr in ("TypeName", "Name"): + if hasattr(row, attr) and getattr(row, attr): + ns = getattr(row, "TypeNamespace", "") or "" + return str(f"{ns}.{getattr(row, attr)}").lstrip(".") + return "?" + + +def build_maps(pe): + md = pe.net.mdtables + names = {} + for i, row in enumerate(md.MethodDef.rows): + names[0x06000000 | (i + 1)] = str(row.Name) + for i, row in enumerate(md.MemberRef.rows): + parent = "?" + try: + parent = type_name(pe, row.Class.row) if row.Class else "?" + except Exception: + pass + names[0x0A000000 | (i + 1)] = f"{parent}::{str(row.Name)}" + for i, row in enumerate(md.Field.rows): + names[0x04000000 | (i + 1)] = str(row.Name) + for tbl, base in (("TypeDef", 0x02000000), ("TypeRef", 0x01000000)): + for i, row in enumerate(getattr(md, tbl).rows): + names[base | (i + 1)] = type_name(pe, row) + return names + + +def decode(pe, row, maps): + raw = pe.get_data(row.Rva, 12 + 65536) + body = read_method_body_from_bytes(raw) + out = [] + for ins in body.instructions: + op = getattr(ins.opcode, "name", str(ins.opcode)).lower() + operand = ins.operand + val = getattr(operand, "value", operand) + text = "" + if isinstance(val, int) and val > 0x02000000: + text = maps.get(val, f"0x{val:08x}") + if val >> 24 == 0x70: + try: + text = repr(pe.net.user_strings.get(val & 0xFFFFFF)) + except Exception: + text = "" + elif val is not None: + text = str(val) + out.append((ins.offset, op, text)) + return out + + +def main(): + path, cmd, pattern = sys.argv[1], sys.argv[2], sys.argv[3] + pe = dnfile.dnPE(path) + maps = build_maps(pe) + rx = re.compile(pattern) + md = pe.net.mdtables + rows = [(0x06000000 | (i + 1), row) for i, row in enumerate(md.MethodDef.rows)] + targets = [(t, r) for t, r in rows if rx.search(str(r.Name))] + if cmd == "list": + for t, r in targets: + print(f"{t:08x} {str(r.Name)}") + return + if cmd == "callers": + for t, r in rows: + try: + for off, op, text in decode(pe, r, maps): + if op in CALLISH and rx.search(text): + print(f"{str(r.Name)} @il+{off}: {op} {text}") + except Exception: + continue + return + for t, r in targets: + print(f"=== {t:08x} {str(r.Name)}") + try: + for off, op, text in decode(pe, r, maps): + print(f" +{off:4} {op:16} {text}") + except Exception as e: + print(f" ") + + +if __name__ == "__main__": + main() diff --git a/tools/string_refs.py b/tools/string_refs.py new file mode 100755 index 0000000..5fb383c --- /dev/null +++ b/tools/string_refs.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +"""Find which IL methods reference a string stored in the native data section. + +Resolves: string bytes -> RVA -> FieldRva row -> Field token -> IL instructions. +Usage: string_refs.py [--context N] +""" +import re +import struct +import sys + +import dnfile + +CALLISH = {"call", "callvirt", "ldftn", "newobj", "ldsflda", "ldsfld", "ldstr", "ldtoken"} + + +def rva_of_offset(pe, off): + for s in pe.sections: + start = s.PointerToRawData + if start <= off < start + s.SizeOfRawData: + return s.VirtualAddress + (off - start) + return None + + +def main(): + path, needle = sys.argv[1], sys.argv[2] + data = open(path, "rb").read() + pe = dnfile.dnPE(path) + hits = [] + for enc in ("ascii", "utf-16-le"): + b = needle.encode(enc) + hits += [m.start() for m in re.finditer(re.escape(b), data)] + rvas = {rva_of_offset(pe, h) for h in hits} - {None} + print(f"needle {needle!r}: {len(hits)} occurrences, rvas: {[hex(r) for r in rvas]}") + + fields = {} # field token -> FieldRva rva + for i, row in enumerate(pe.net.mdtables.FieldRva.rows): + fields[0x04000000 | (i + 1)] = row.Rva + matching = {t: r for t, r in fields.items() if r in rvas} + print("matching field tokens:", {hex(t): hex(r) for t, r in matching.items()}) + + names = {} + for i, row in enumerate(pe.net.mdtables.Field.rows): + names[0x04000000 | (i + 1)] = str(row.Name) + # any string whose RVA sits inside the string's own blob (same field) + related = set(matching) + for t, r in fields.items(): + if any(r <= rv < r + len(needle) + 64 for rv in rvas): + related.add(t) + print("related fields:", {hex(t): names[t] for t in sorted(related)}) + + from dncil.cil.body.reader import read_method_body_from_bytes + maps = {} + for i, row in enumerate(pe.net.mdtables.MethodDef.rows): + maps[0x06000000 | (i + 1)] = str(row.Name) + for i, row in enumerate(pe.net.mdtables.MemberRef.rows): + maps[0x0A000000 | (i + 1)] = str(row.Name) + + for i, row in enumerate(pe.net.mdtables.MethodDef.rows): + try: + raw = pe.get_data(row.Rva, 12 + 65536) + body = read_method_body_from_bytes(raw) + except Exception: + continue + insns = body.instructions + for j, ins in enumerate(insns): + op = getattr(ins.opcode, "name", str(ins.opcode)).lower() + if op not in CALLISH: + continue + val = getattr(ins.operand, "value", ins.operand) + if val in related: + print(f"\n{str(row.Name)} @ +{ins.offset}: {op} {names.get(val, val)}") + for k in insns[max(0, j - 6):j + 10]: + kop = getattr(k.opcode, "name", "?").lower() + kval = getattr(k.operand, "value", k.operand) + txt = maps.get(kval, kval) if isinstance(kval, int) and kval > 0x02000000 else (kval if kval is not None else "") + mark = " <<<" if k is ins else "" + print(f" +{k.offset:6} {kop:14} {txt}{mark}") + + +if __name__ == "__main__": + main()