Skip to content

Releases: encomjp/Lenovo-Legion-Control

v0.2.15

Choose a tag to compare

@github-actions github-actions released this 29 Sep 22:29

Changelog - 0.2.15 (2026-09-30)

AppImage Runs on Older Distros (glibc 2.35+)

  • Built on Ubuntu 22.04: the AppImage is now built on the oldest supported Ubuntu LTS, so it only needs glibc 2.35 on the host (Ubuntu 22.04+, Debian 12+, Fedora 36+, and similar). 0.2.14 required glibc 2.39.
  • GTK 4.14 / libadwaita 1.5 bundled from source: GLib 2.80, Wayland 1.23, GTK 4.14 and libadwaita 1.5 (plus AppStream 1.0 / libxmlb) are built from source in CI and bundled, since the 22.04 system versions are too old. The build is cached, so later builds stay fast.
  • SVG icons: the librsvg pixbuf loader is now bundled so SVG icons render on systems without it.
  • CI check on 22.04: the self-contained check now runs in a clean Ubuntu 22.04 container and also fails on missing glibc symbols.

No functional changes to the daemon, CLI or GUI compared to 0.2.14.

v0.2.14

Choose a tag to compare

@github-actions github-actions released this 29 Sep 21:27

Changelog - 0.2.14 (2026-09-29)

AppImage Is Now Self-Contained

  • Bundled GTK4 / libadwaita: the AppImage now ships GTK4, libadwaita and their dependencies (via linuxdeploy + the GTK plugin). Previously legion-settings failed to start on systems without libadwaita-1.so.0 installed (error while loading shared libraries). Only base host libraries (glibc, X11/GL, fonts) are taken from the system, as usual for AppImages.
  • CI check: the release workflow now extracts the AppImage in a clean Ubuntu container without GTK/libadwaita and fails if any bundled binary has unresolved libraries.

No functional changes to the daemon, CLI or GUI compared to 0.2.13.

v0.2.13

Choose a tag to compare

@encomjp encomjp released this 03 Sep 18:49

Changelog - 0.2.13 (2026-09-03)

Fixes GitHub Issue #3 (reported by @Konnor378 on Legion Y7000P 16IRX9 / 83DG).

White Keyboard Backlight Slider (Lighting)

  • Daemon-routed writes: the white-backlight slider in build_simple_backlight_page no longer calls keyboard::set_brightness() directly from the user-space GTK process (which failed silently with EACCES on /sys/class/leds/.../brightness). Writes now go through run_daemon_command_async(DaemonCommand::SetKbdBrightness(v)) and surface failures via toast_error.
  • 50% steps: the gtk::Scale snaps to integer steps (increment 1.0, set_digits(0), round-on-drag with recursion guard, duplicate-write suppression) with marks at Off / 50% / 100% for the typical max_brightness == 2 board; the value label shows "Off", "50%", "100%" (generic percent math for other maxima, u32 to avoid u8 overflow).

Manual Fan Control on EC-Owned Models (Cooling)

  • Read-only fan cards: when fans::control_backend_name() is None (e.g. Y7000P 16IRX9 / 83DG, no fan-target write path), fan_card renders read-only — live RPM plus an "Auto (EC controlled)" row and a "Manual fan control is not supported on this model (managed by Lenovo EC firmware)" note. The manual switch and target-RPM slider are hidden so users can no longer trigger the no fan backend/device for target write error toast.
  • Reset gating: the "All fans automatic" reset group is replaced with the same EC-managed note on models without a write backend.

Custom / User Mode Power Sliders (CPU + Home)

  • CPU → Power is live in Custom mode: build_cpu_power_page no longer hardcodes preview.set_sensitive(false). When the current profile is custom, the Custom-watts sliders are sensitive and each drag routes through ensure_custom_then_ppt (same Custom-gate Home uses, with direct queued-write fallback); guide text tells the user the sliders are active. Outside Custom mode they stay greyed out with the "Switch to Custom & edit" path.
  • Fn+Q sync on Home: the Home dashboard poll now sets ppt_box.set_visible(firmware_mode == "custom" && !ppt_scales.borrow().is_empty()) whenever the firmware mode changes, so Fn+Q directly into Custom mode immediately reveals the sliders without touching the GUI dropdown.

Also in This Release

  • Telemetry schema version 4 support (power/charging, CPU EPP/governor/boost, profile choices, display/VRR, amp health, dGPU limits); collector accepts schemas 1–4.
  • KDE widget redesign.

v0.2.12

Choose a tag to compare

@github-actions github-actions released this 03 Sep 04:22

Changelog - 0.2.12 (2026-09-03)

Telemetry Schema v4 & Expanded Fleet Insights

  • Schema v4 Reports: Diagnostics reports now carry schema_version: 4 (REPORT_SCHEMA_VERSION in src/diagnostics.rs); the collector accepts schemas 1–4 so older clients keep flowing during rollout.
  • Live Power & Charging Info: New power block with AC adapter status (ac_online, ac_type), live charge_rate_w, charge_state, and voltage_v for fleet-wide charging-behavior triage.
  • CPU Frequency Policy: New hardware.cpu fields capture governor, energy_performance_preference, scaling_driver, pstate_mode, and boost_enabled alongside core counts and clocks.
  • Platform Profile Choices: Reports now include the full platform-profile choices plus ACPI acpi_choices and the current profile, so unsupported-profile fleets are visible server-side.
  • Display & Audio Health: New hardware.display connector and vrr_capable fields; new audio block records speaker amp health (amp_present, amp_bound, firmware_ok, health, mute/sink state) for the AW88399 fleet check.
  • dGPU Power Envelope: New hardware.gpu fields record power_limit_w, power_max_w, power_default_w, dynamic_boost_headroom_w, and pstate for NVIDIA power-triage without touching nvidia-smi -q on minute pushes.

Collector Unification & Security Hardening

  • Single Canonical Collector: server/collector.py and lenovo-legion-tool/server/collector.py are unified to one implementation — one FastAPI app with a lifespan manager (init_db + hourly retention worker), per-request connections instead of a shared write handle.
  • Streaming Gzip with Bomb Guard: Content-Encoding: gzip / x-gzip bodies are decompressed via streaming gunzip_capped() capped at MAX_BODY_BYTES = 512 KiB; over-cap returns 413, corrupt/truncated streams return 400, unknown encodings return 415.
  • Shared-Secret Auth: Optional X-Legion-Telemetry-Key header validated with constant-time hmac.compare_digest when LEGION_TELEMETRY_KEY is set (401 on mismatch).
  • Rate Limiting & Retention: Sliding-window per-IP limit (LEGION_TELEMETRY_RATE_PER_MIN, default 30/min, 429 beyond) and hourly pruning of reports older than RETENTION_DAYS (default 90).
  • SQLite Hardening: WAL mode with busy_timeout=5000 and 5 s connect timeout for concurrent daemon/GUI-adjacent writes; GET /health now returns {ok, count, last_id}.

Privacy Enforcement & Hardware De-identification

  • Battery Serials Excluded: The deep power dump skips any *serial* sysfs file and raw uevent snapshots — battery serial numbers never leave the machine.
  • GPU Identifiers Redacted: The nvidia-smi -q deep dump redacts GPU UUID, Serial Number, GPU Part Number, and GPU PDI lines to [REDACTED] (cap raised to 32 KB for the sanitized dump).
  • SMBIOS UUID Pseudonymization: The DMI product-UUID machine-ID fallback is no longer stored raw; a salted 128-bit FNV-1a hash_to_pseudonym() mints a deterministic UUIDv4-shaped pseudonym that survives wipes without exposing the factory UUID.

Hardware & Daemon Fixes

  • Dynamic CPU Frequency Bounds: The thermal governor replaces the hardcoded MAX_FULL/MIN clamp with live cpuinfo_max/min_freq sysfs bounds (compute_target_dynamic, read_cpu_freq_bounds, restore_full_speed) — throttle floors and restore caps now match the actual SKU instead of assuming the 9955HX3D envelope. Shutdown and governor-disable paths restore the real full speed.
  • Yogafan Initialization Order: The daemon probes and auto-loads yogafan before device detection so the fan-backend OnceLock binds to the working tachometer on LOQ 83JG/R8CN instead of locking onto the all-zero lenovo_wmi_other reading.
  • Limiter Bracket Parser: The charge-types anomaly message parses […] selections via split(']').next() instead of trim_end_matches(']'), so trailing content after the bracket no longer leaks into fault text.
  • Sensor Caching: The hwmon lookup cache gains a 5-second TTL with negative-lookup caching — hot paths avoid rescan storms while freshly appearing devices are still picked up within seconds.

v0.2.11

Choose a tag to compare

@github-actions github-actions released this 02 Sep 19:58

Changelog - 0.2.11 (2026-09-02)

Fixes

  • AppImage Staging Skew & Daemon Update: Fixed an issue where running from an AppImage would execute stale previously-staged helper binaries without updating /usr/local/bin/legion-daemon, causing the daemon to remain stuck on older versions (e.g. v0.2.8). The setup workflow now always restages bundled daemon, helper, Polkit policy, and systemd units.
  • Daemon Socket Permissions & IPC Connection: Bound /run/legion-control.socket with mode 0666 and automatic legion group creation in setup-helper, preventing client Permission denied (os error 13) for non-root desktop users.
  • IPC Error Transparency: Fixed error masking in send_command where PermissionDenied on the root socket was masked by NotFound (os error 2) from fallback socket paths.
  • Model Detection (Legion Y7000P IRX9): Added official model profile for 83DG (Legion Y7000P IRX9, NMCN BIOS) with dual Coldfront fans and WMI3 platform profiles.
  • Intel & AMD Capability Gating: Hid AMD Curve Optimizer UI on Intel laptops (including Y7000P i7-14700HX) and unsupported AMD processors (Cezanne / Zen 2).
  • Fan Layout Corrections: Corrected Legion Pro 7 16IRX8H fan layout from three fans to two fans (Coldfront 5.0).
  • Battery EC State: Cleared rapid charge mode before enabling battery conservation mode on Lenovo EC.
  • Sensor Robustness: Added fallback support for zenpower k10temp drivers and multiline output handling in nvidia-smi.

Telemetry & Fleet Visibility

  • Motherboard & EC Firmware: Telemetry now captures motherboard DMI identifiers (product_family, product_sku, board_name, board_version) and ec_firmware_release to accelerate bring-up of new chassis revisions.
  • Keyboard Lighting Classification: Explicitly records lighting type (Spectrum, FourZone, White) to distinguish monochrome backlights from multi-zone RGB.
  • Extended Hardware Inventory: Deep diagnostics now include safe DMI sysfs dump, complete HID controller enumeration, ACPI thermal zones (name (type) -> temperature), and platform profile choices.
  • Uncapped Fleet Retention: Server-side telemetry retention cap lifted from 5,000 to unlimited in ClickHouse.

v0.2.10

Choose a tag to compare

@github-actions github-actions released this 01 Sep 20:23

Changelog - 0.2.10 (2026-09-01)

Fixes

  • Fix Intel coretemp CPU temperature handling, including Package/Core readings and thermal-zone fallback.
  • Gate speaker troubleshooting on NotApplicable for models without the AW88399 smart amp.
  • Collapse lighting controls to white-only mode on hardware that exposes only white backlighting.
  • Add catalog coverage for Legion 82GN/81Y8/82B3 and 82K2/82MJ, plus broader Legion hardware research.

v0.2.8

Choose a tag to compare

@github-actions github-actions released this 31 Aug 19:37
v0.2.8: disable Speaker fix when no AW88399 (fleet 83JG/83DG NotAppli…

v0.2.7

Choose a tag to compare

@github-actions github-actions released this 31 Aug 16:43
v0.2.7: Intel coretemp CPU temp (Y7000P 83DG 0°C) + daemon AppImage s…

v0.2.6 - x86-64-v3 + service fix

Choose a tag to compare

@encomjp encomjp released this 30 Aug 21:49

v0.2.6

v0.2.5 - LOQ fan unlock

Choose a tag to compare

@encomjp encomjp released this 30 Aug 20:53

v0.2.5 — LOQ 15AHP10 (83JG/R8CN) fan unlock + update UX

  • Auto-detects locked WMI tach and auto-loads yogafan (daemon + pkexec Unlock fans). Gray locked Cooling gate.
  • Diagnostics: yogafan_loaded, fan_detail captures yogafan, sensors reconciled via fans backend; EC garbage guard.
  • Update: Build bar pulses continuously with live cargo tail (Compiling…); Source installs can pick Build from source (2-4 min) vs Use AppImage (10s).
  • Docs: upstream yogafan DMI quirk patch for 83JG/R8CN.
  • Portal legacy filter (<0.2.0 hidden) ready — deploy to IONOS next.

Full diff: v0.2.4...v0.2.5