Files
phantomptrandClaude Opus 5.5 52f8375353 Fan: write the whole servo profile, guard the target every 2 s
The helper wrote 0xC01C8F07 from a zero-filled 28-byte buffer with only
the target at byte 5, but SET forwards bytes 2..27 to the controller, and
re-sent that blind write every 15 s. Every write is now GET, change byte
5, SET, GET again and compare (fan_servo.c); a failed GET writes nothing
and a profile change beyond the target is logged once.

The watcher reads the target every tick (default 2 s, was 15) and writes
only when the system put its own back (a fan-pattern switch on game start
or exit), counting restores; after 5 failed writes in a row it stops and
reports fan_guard=failing until the next set. An old fan_reapply.conf
(its bare number was never read back) that says 15 moves to 2 once.

Targets go up to 85 C (fan_map too); a target above the console's own is
refused (fan_above_stock). HW_TEMPS adds fan_restores,
fan_last_restore_s, fan_guard, fan_filtered_c (8F09), fan_min_c/max_c and
the profile as hex; fan duty is read as Q10 from 8F02 (it was scaled as
0..255).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JoFXdUvVCDAG8xRjtp52qt
2026-10-22 05:59:41 -07:00

30 lines
1.4 KiB
C

#ifndef PS5UPLOAD_FAN_MAP_H
#define PS5UPLOAD_FAN_MAP_H
/* Pure curve -> temperature mapping (no hardware, no Sony API), kept apart from
* fan_curve.c so the host-built ava1-ctest suite can pin it.
*
* What /dev/icc_fan ioctl 0xC01C8F07 takes is ONE temperature: the one the
* firmware's own fan control works to hold. It is not a curve. Lower means
* louder: under load the fans run as hard as it takes to stay there.
*
* The console's own value is NOT 60 C, as this file said until it was read
* back: it is 91 C on FW 13.60 (CFI-1115A and CFI-7019, ioctl 0xC01C8F08). So a
* curve "capped at stock 60" ran the fans far harder than the console does by
* itself, whatever the curve looked like (#400, after #354). */
/* The most we set (HW_FAN_THRESHOLD_MAX, checked in fan_curve.c). */
#define FAN_MAP_MAX_C 85
/* Floor, equal to HW_FAN_THRESHOLD_MIN (checked in fan_curve.c). */
#define FAN_MAP_MIN_C 45
/* "Leave it to the console": restore its own value and stop overriding it. */
#define FAN_MAP_CONSOLE_OWN 0
/* The temperature (C) for `{"points":[{"temp_c":N,"duty_pct":N},...]}`: the
* lowest one at which the user asked for 100% duty, floored at FAN_MAP_MIN_C.
* A curve that never asks for 100%, or only above FAN_MAP_MAX_C, maps to
* FAN_MAP_CONSOLE_OWN. Returns -1 when the body has no readable point. */
int fan_map_threshold(const char *points_json);
#endif