108 lines
4.9 KiB
C++
108 lines
4.9 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;
|
|
};
|
|
|
|
// One value the host declared and the firmware should be holding. Used for the
|
|
// parameters the config handshake added, where "not declared" and "not echoed"
|
|
// both mean the check does not apply rather than that it failed.
|
|
struct DeclaredValue {
|
|
const char* name = "";
|
|
bool want = false; // hardware.ini declares it
|
|
long value = 0;
|
|
long got = -1; // as DUMP echoed it; -1 = absent
|
|
};
|
|
|
|
// Does the firmware hold what hardware.ini says? This is the generalisation of
|
|
// the old "did CENTER land?" check: with the drivetrain owned by the host, every
|
|
// declared value is one the firmware can be silently wrong about, and a tower
|
|
// running on stale or defaulted values looks identical to a correct one from the
|
|
// outside.
|
|
//
|
|
// `values` may be empty, which is how an axis with nothing declared reports
|
|
// "not checked" rather than passing.
|
|
CheckResult checkDeclaredValues(const std::string& axis, const DeclaredValue* values, int count);
|
|
|
|
// 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);
|
|
|
|
// Does the homed travel fit entirely in positive counts?
|
|
//
|
|
// `center_count` defines where the middle of the found travel sits, so the range
|
|
// is center +/- half the travel. A center smaller than half the travel puts the
|
|
// negative end below zero. The 500000 default was sized for the Delta, whose
|
|
// half-travel is ~89k; a drivetrain geared up by 7x has ~605k and crosses zero.
|
|
//
|
|
// Whether the TMC5160 actually misbehaves there is NOT established - XACTUAL is
|
|
// a signed 32-bit register and the firmware round-trips the sign correctly - but
|
|
// homing is the only thing that has ever driven that far, so the region is
|
|
// untested in normal operation. The cheap fix is to not be there.
|
|
//
|
|
// `center` and `half_travel` are in counts. A non-positive half_travel means the
|
|
// axis has not homed, and nothing is checked.
|
|
CheckResult checkTravelFitsPositive(const std::string& axis, long center, long half_travel);
|
|
|
|
} // namespace fgc
|