Skip to content

1.6.1 — Review-campaign fixes (transport, raw pipeline, installer)

Choose a tag to compare

@Syax89 Syax89 released this 15 Sep 13:38
· 312 commits to main since this release

1.6.1 — Review-campaign fixes (transport, raw pipeline, installer)

Every change in this release comes from an independent, double-blind review
campaign over 1.6.0 and was verified line by line against the source before being
acted on. Twenty-eight findings across three reviewers (different agent+model each,
no access to each other's reports); three round-one reports presented with high
confidence turned out to be false positives and are deliberately not "fixed".
Every fix then went through an adversarial pass of its own, which refuted four of
them — those are corrected here too, and the two behaviour bugs the pass caught in
my own fixes would have been shipped otherwise.

Raw pipeline (raw_mode=1)

  • The heatmap baseline can decay again. It was monotone non-decreasing
    (acquisition kept the per-cell maximum, the update only recovered upward) while
    its own comment promised a slow downward drift: once the resting level drifted
    down, rise stayed positive across whole areas and the pipeline published
    phantom contacts until a reload. One count per HEATMAP_DRIFT_DIV frames
    (~2.5 s at 100 Hz), checked by the real pipeline in raw_pipeline_replay_test
    (falsified: neutralising the branch fails the test).
  • A single dropped frame no longer becomes a real release. Re-acquisition
    while the lift was pending restarted the debounce, so one peak-free frame —
    which puts every finger into lift — released and re-pressed all contacts,
    aborting pinches, scrolls and drags. The recovery guard compares the
    pre-penalty weight, so bottom-row contacts (23% of their weight after the edge
    penalty) are recoverable too.
  • The lift-lookback can no longer report another contact's position: the slot
    history is cleared when a contact starts or frees, instead of being reused
    across contacts on the same slot.
  • grid_cols/grid_rows work: they were unreachable on every boot (the
    geometry cache is filled from the per-device config, which is never NULL).
    dfa_data_offset no longer disables touch input while flooding the log and
    resetting the pipeline 100 times a second.
  • Split sub-blobs are edge-penalised by their own window; the ghost merge is
    strict (<) as in Windows and the in-tree oracle; input_allocate_device()
    failure is reported instead of returning success; the CALIB:/CALIB_REF:
    diagnostics print correct numbers.

Raw handshake and re-discovery

  • The delayed handshake sends the same vendor init -> GET_FEATURE sequence as
    the immediate one (it used to send a bare GET_FEATURE, so the experiment
    could not reproduce what it exists to test).
  • setfeat_speed_hz / setfeat_no_double are honoured on every SET_FEATURE
    path; under the default skip_getfeat=1 they were silently dead.
  • Stream-watchdog recovery uses the same restart as the handshake watchdog (D2/D0
    vendor init, fresh DESCREQ, timer re-armed) instead of a DESCREQ-only sequence.
  • Every re-discovery clears ready so HID clients cannot interleave sync
    requests with the sequencer — and the raw→standard fallback restores it, or the
    re-created standard HID device would have answered -ENODEV forever.
  • The fallback no longer creates a standard HID device in raw mode; a negative
    getfeat_delay_ms is clamped instead of wrapping the handshake watchdog into
    the far future.

Standard mode

  • Opt-in backstop for a device that answers power-up or resume with nothing at
    all: wait_reset_kick_ms (0 = off, the default) sends one DESCREQ after that
    many milliseconds without a single IRQ edge, once per entry into WAIT_RESET,
    and the descriptor poller keeps reading until the device answers. It never
    reads the input buffer, and performs no power sequencing. The default is off
    because the safe interval is measured, not known — this is the switch for the
    cold-boot shape of issue #4.

Installer

  • logs no longer truncates its own diagnostic bundle (a root-run git in a
    user-owned checkout, an inactive unit and an empty dmesg | grep each aborted
    collection under set -e -o pipefail).
  • Upgrades remove the previous DKMS registration instead of leaving both —
    two registered versions built the same module names and dkms autoinstall
    picked whichever ran last on the next kernel update.
  • Interrupted staging is recoverable; logs -o is validated before root uses it
    in a redirect; the boot unit quotes its ExecStart; activate honours
    SL4A_SYSFS_ROOT; the systemd unit gets the same ownership guard as the
    modprobe config.
  • Docs corrected: install binds the modules itself (Step 7) and the boot unit
    repeats it after multi-user.target; four documents still described the old
    manual-activation contract.

Verification

  • Host suite: 92 420 protocol assertions, 61 raw-pipeline math, 51 real-pipeline
    replay, 73/33/55 decoder and math checks, all contract suites; SANITIZE=1
    (ASan + UBSan) clean on the merged tree.
  • CI: whitespace, host-tests, kernel-build green on every PR and on main.
  • Not hardware-tested: the raw-mode behaviour changes and the new backstop
    need field data. A normal cold boot with wait_reset_kick_ms enabled must show
    no kick line; the raw pipeline changes need fingers on a panel. Reports in
    issue #4 are welcome — that is what the switches are for.

Full details: CHANGELOG.md under 1.6.1.