fwt_software/include/fgc/HardwareChecks.h

72 lines
3.0 KiB
C++

#pragma once
#include <string>
namespace fgc {
// The decisions behind `test hardware`, separated from the I/O that feeds them.
//
// Each function takes what was read - a sysfs string, an ioctl bitmask, a DUMP
// echo - and returns a verdict with the sentence an operator needs. Keeping them
// pure is what lets the thresholds be tested without a rig, which matters because
// several of them encode traps that cost real debugging time (known-issues #2
// and #19) and must not drift silently.
struct CheckResult {
bool ran = true; // false => nothing was declared, so nothing was checked
bool pass = true;
std::string detail; // one line; names the fix when it failed
};
// /sys/module/usbcore/parameters/usbfs_memory_mb.
//
// Reverts to 16 on every reboot unless persisted on the kernel cmdline, and
// frame delivery stalls below ~1000 regardless of application code
// (known-issues #19). A value that will not parse is a failure, not a pass:
// an unreadable node means the check did not happen.
CheckResult checkUsbfsMemory(const std::string& sysfs_value, int min_mb);
// A usb3_lpm_permit node. U1/U2 link power management must be OFF on the
// camera's port or the camera logs frame drops under load; the per-device
// usb3_hardware_lpm_u* files are read-only, so this port-level node is the one
// that can actually be set (known-issues #19).
CheckResult checkUsb3Lpm(const std::string& permit_value);
// The I2C_FUNCS ioctl bitmask for the bus the SHT41 is on.
//
// An SMBus-only adapter opens, binds its slave address, and then fails every
// transaction - which reads as a dead sensor rather than as the wrong bus
// (known-issues #2). `i2cdetect -F <n>` is the manual form of this check.
//
// The bit is spelled out rather than pulled from <linux/i2c.h> so this stays a
// pure module: I2C_FUNC_I2C is 0x00000001 and is ABI-stable.
constexpr unsigned long kI2cFuncI2c = 0x00000001UL;
CheckResult checkI2cFunctionality(unsigned long funcs);
// What the host computed from hardware.ini for one axis.
struct DrivetrainExpectation {
bool declared = false; // hardware.ini carries a current for this axis
int global_scaler = 0;
int run_irun = 0;
int homing_irun = 0;
};
// What DUMP echoed back. -1 means the field was absent, which is a firmware
// predating the CURRENT command - a version skew, not a current of zero, and
// the two must stay distinguishable.
struct DrivetrainEcho {
long global_scaler = -1;
long run_irun = -1;
long homing_irun = -1;
bool absent() const { return global_scaler < 0 && run_irun < 0 && homing_irun < 0; }
};
// Did the firmware adopt what the host sent? Both registers are write-only on
// the TMC5160, so this echo is the only confirmation available - and without it
// a tower can run its whole life on limp-home defaults while reporting healthy.
CheckResult checkDrivetrainAdopted(const std::string& axis, const DrivetrainExpectation& want,
const DrivetrainEcho& got);
} // namespace fgc