Skip to content

Add safe Automatic and Max Cooling fan control - #28

Open
LeonidasZhak wants to merge 2 commits into
ryyansafar:mainfrom
LeonidasZhak:codex/fan-max-control
Open

Add safe Automatic and Max Cooling fan control#28
LeonidasZhak wants to merge 2 commits into
ryyansafar:mainfrom
LeonidasZhak:codex/fan-max-control

Conversation

@LeonidasZhak

@LeonidasZhak LeonidasZhak commented Aug 14, 2026

Copy link
Copy Markdown

Summary

Adds a deliberately constrained fan control to the existing Fan card:

  • Automatic returns fan arbitration to macOS
  • Max Cooling requests every detected fan's hardware-reported maximum

The UI does not accept arbitrary RPM values, so it cannot request a lower-than-normal cooling target.

Safety behavior

  • fan capability is detected with FNum, so a fan-bearing Mac at 0 RPM still shows the controls while fanless Macs do not
  • Max Cooling requires confirmation and changes every detected fan together
  • hardware maximums are read from each F*Mx key, bounded to a plausible 1,000–20,000 RPM range, encoded according to the key's actual SMC data type, written, and read back for verification
  • a partial failure requests automatic mode for all fans
  • normal app termination restores automatic mode
  • after a completed request, an abnormal app crash can leave maximum cooling active (noisy but thermally conservative); normal termination restores automatic mode
  • both Apple Silicon per-fan mode keys (F*md / F*Md, with Ftst arbitration) and the legacy FS! mask are handled

Privilege hardening

The existing helper receives two exact commands: --fan-max and --fan-auto. Every other argument is rejected.

Before invoking sudo, MacMonitor now requires both the helper and its parent directory to be root-owned, non-symlinked, and not group/other-writable. The sudoers entry is migrated from an unrestricted helper command to three exact command lines: no-argument sampling, Max Cooling, and Automatic.

Verification

  • Swift response/protocol, legacy-helper rejection, and helper-ownership tests pass
  • C SMC flt , fpe2, ui8 , and ui16 numeric round-trip tests pass
  • helper compiles with -Wall -Wextra -Werror
  • helper rejects fan writes when not privileged and rejects unknown arguments
  • Clang static analysis reports no findings
  • Debug and Release app builds pass, including the embedded Widget
  • git diff --check passes

Hardware-validation note

The repository's documented test Mac and the machine available for this patch are fanless. No write command was run against physical fan hardware. The PR is implementation-complete and thermally conservative, but actual fan actuation and automatic-mode restoration should be confirmed on a fan-bearing Apple Silicon Mac before merge.

Closes #27

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add constrained Automatic / Max Cooling fan control

1 participant