Skip to content

hid: add opt-in standard-transport CapImg multitouch - #87

Merged
Syax89 merged 26 commits into
Syax89:mainfrom
avgbob:upstream/std-capimg-mt
Oct 18, 2026
Merged

Syax89 merged 26 commits into
Syax89:mainfrom
avgbob:upstream/std-capimg-mt

Conversation

@avgbob

@avgbob avgbob commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Focused extraction of the Gate5 standard-transport work, based directly on current upstream main / v1.7.1 (72b3492).

This adds an opt-in, default-off standard-transport CapImg multitouch path for the exact hardware ID currently qualified by the field work: MSHW0231.

normal HID-over-SPI discovery + HID registration
  -> write GET_FEATURE(6), do not synchronously read its reply
  -> wait ~4.5–5.5 ms
  -> SET_FEATURE(5) = 1
  -> DONE / 0x0c CapImg frames
  -> existing in-kernel CapImg tracker

Activation requires all three conditions:

  • ACPI ID is exactly MSHW0231
  • std_raw_transition=1
  • raw_input_beta=1

Otherwise the bridge stays disabled. Existing raw mode remains intact, and ordinary standard mode is unchanged.

Why this transaction order

Controlled A/B testing on my physical SL4 AMD / MSHW0231 unit found:

  • SET5 only -> CapImg
  • write GET6 -> ~5 ms -> SET5 -> CapImg
  • full synchronous GET6 reply read -> SET5 -> controller reset

So this path deliberately writes GET6 without consuming the response body before SET5. That is separate from issue #4's generic HID GET_REPORT path, where standard-mode report 6 is now correctly suppressed by default upstream.

Early-DATA lifecycle fix

SET5 can make the first ~4.3 KiB CapImg DATA frame arrive during HID registration.

The old path could consume the DATA header and then return while hid_add_device() was still running, leaving the body queued. On my unit that produced a repeatable warm-reload reset roughly 0.5 s later.

This PR therefore separates two policies:

  • body ownership: a completed HID client drains DATA as before; the explicitly registered CapImg tracker additionally owns DATA across the HID-registration window;
  • HID publication: call hid_input_report() only after HID creation completes.

The tracker-specific ownership closes the smaller window where the bridge device exists but hid_creating has not flipped true yet, while plain/default standard HID keeps upstream creation-time behavior.

Hardware scope

The standard-transport bridge is intentionally narrower than the general SL4 device match.

  • MSHW0231: eligible when the two opt-in parameters above are set.
  • MSHW0230: remains supported by the general driver, but this bridge is not enabled.
  • MSHW0162: bridge is not enabled.
  • DT/unknown fallback matches: bridge is not enabled.

This avoids extending one-unit hardware evidence to unqualified panels.

Prior hardware evidence

The corresponding Gate5 path was qualified on one physical Surface Laptop 4 AMD / MSHW0231 unit:

  • true cold power-on + touch: PASS
  • warm module reload + touch: 3/3 PASS
  • s2idle suspend/resume + touch: 2/2 PASS
  • zero observed frame drops in those qualification captures
  • zero unexpected post-DONE resets in those captures
  • Secure Boot/DKMS lifecycle also passed in the fork, but those installer changes are not part of this PR

Qualification record:
https://github.com/avgbob/SL4A_TouchScreen/blob/main/docs/GATE5-QUALIFICATION.md

That evidence predates this clean rebase. I am not claiming fresh physical qualification of this exact rebased branch yet, so the PR remains draft.

Regression coverage

The PR adds three source-contract tests plus one compiled lifecycle behavior test:

  • std_capimg_activation_source_test.py

    • pins write-only GET6 -> ~5 ms -> SET5 ordering
    • rejects a synchronous GET6 read
    • pins exact MSHW0231 + mode-1 + raw_input_beta qualification
  • std_capimg_input_source_test.py

    • pins tracker registration/0x0c consumption through the qualified gate
    • keeps the raw-mode path intact
  • std_capimg_data_drain_source_test.py

    • pins use of the DATA lifecycle policy in seq_handle_data()
  • std_capimg_data_policy_test.c

    • exercises the HID-creation race behavior
    • requires the full ~4304-byte body to be consumed
    • verifies no premature HID publication
    • verifies the next frame remains aligned
    • covers the pre-hid_creating window when the tracker already owns DATA

The new compiled test is wired into make -C tests test.

Deliberately not included

To keep this review independent, this PR does not include:

  • Gate5 installer/default-profile promotion
  • Secure Boot installer changes
  • tracker/coalescing algorithm changes
  • Windows capture tooling
  • userspace sl4a-heat
  • MSHW0230 enablement for this path
  • any default change to upstream standard mode

Those can be reviewed separately if useful.

This is the standard-transport piece I mentioned in issue #4.

Windows reverse-engineering provenance

This path was not derived from Linux-side trial-and-error alone. The standard-transport work grew out of a Windows reverse-engineering campaign on the same MSHW0231 hardware:

  • Gate 2 Windows lifecycle capture — defines the accepted ETL questions around _PS0/_PS3/_RST, post-report-descriptor feature traffic, and live input.
  • Windows golden state machine — records the decoded Windows lifecycle and transport observations, including the real 936-byte descriptor and post-RDESC feature sequence.
  • Surface MSI mining report — proves the Windows binding HID\\MSHW0231&Col02 -> TouchPenProcessor0C19.dll and identifies the Heat processor used for this panel.
  • Windows detector alignment — maps recovered TouchPenProcessor0C19 detector constants/behavior against the Linux CapImg tracker.
  • Windows source hashes — provenance hashes for the recovered Microsoft INF/evidence sources used in that analysis.

That Windows evidence is what pushed the project toward preserving the real HID transport, reproducing the observed lifecycle/report sequence, and treating 0x0c as the Heat/CapImg data path rather than replacing the transport wholesale.

Review follow-up

After Syax89's first review:

  • the runtime stream_watchdog arm inside the DATA path is gated back to raw_mode_active; standard-transport bridge traffic does not arm raw recovery/logging when std_liveness_ms=0;
  • a new host regression extracts and compiles the real production seq_handle_data() body with counted SPI/tracker/HID/workqueue endpoints, and compiles the exact DATA lifecycle helpers from spi-hid-protocol.h;
  • the test covers the HID-creation drain, pre-HID tracker ownership, post-create HID publication, raw-watchdog positive control, and a default-standard negative control;
  • early-DATA ownership was narrowed so hid_creating alone does not change default standard-HID behavior.

Historical Gate5 evidence was on 58f023102679ab0156ce95210abe7e3e3e6ac412, not this rebased head. That campaign already used retained SET_FEATURE/5 request context after activation and passed cold boot, 3/3 warm reloads, and 2/2 s2idle resumes with zero observed frame drops/unexpected post-DONE resets. I am intentionally not presenting that as exact-head acceptance evidence.

Still required before this draft is marked ready: physical qualification of the exact PR head, including the requested cold boot/reloads/resume/real gestures/counters/default-standard control. A spontaneous post-DONE reset that would test whether the one-shot activation must be re-armed in-place was not observed in the historical campaign and remains an open targeted hardware question.

@Syax89

Syax89 commented Oct 16, 2026

Copy link
Copy Markdown
Owner

Hi @avgbob, thanks for splitting this out and being precise about what has and has not been qualified on hardware. The narrow scope and default-off activation are appreciated.

I reviewed eea64ecab652696d4ea82512f432354e0bcfd3ea against upstream 72b3492, including two independent reads and follow-up executable probes. Overall this looks like a good direction. I did not establish a high/medium-severity blocker, but found one small runtime issue and a regression-test gap worth addressing before taking this out of draft.

1. Small runtime issue: the bridge repeatedly arms standard-liveness logging even when it is disabled

At driver/spi-hid-core.c:3835–3840, expanding the CapImg consumer branch to standard transport also exposes its raw-runtime watchdog arm to that path.

The worker still selects its policy using raw_mode_active. With the bridge enabled, default stream_watchdog_ms=2000, and std_liveness_ms=0, it therefore runs the standard-liveness branch, logs a result, and clears stream_watchdog_active. The next CapImg frame arms it again.

An actual-handler/worker host probe with counted kernel endpoints reproduced three successive schedules and three messages:

standard-mode liveness: 1 IRQ(s) within 0ms of DONE
standard-mode liveness: 2 IRQ(s) within 0ms of DONE
standard-mode liveness: 3 IRQ(s) within 0ms of DONE

This is misleading repeated logging and unnecessary work, not a demonstrated reset storm or broken touch input. The IRQ baseline is also not initialized by the disabled startup-liveness arm, so those counts do not represent the advertised window.

The smallest change seems to be keeping this particular runtime-watchdog arm gated by shid->raw_mode_active, while leaving the explicit standard startup-liveness arm controlled by std_liveness_ms alone. If bridge runtime recovery is wanted later, it should have an explicitly tested policy rather than accidentally entering the standard startup logger.

2. The new lifecycle tests do not yet exercise the complete DATA path

The helper C test usefully checks the boolean policies, but its cursor increment models the read rather than executing seq_handle_data(). The source checks verify recognizable code fragments, not that the tracker is actually called with a fully drained body.

Two mutation checks made that distinction concrete:

  • Truncating the actual DATA read to 64 bytes still passed all three new source tests and the new C policy test. An actual-handler probe instead reported read=64, consume=0, drops=1 and failed.
  • Disabling the entire CapImg consume branch with if (0 && ...) still passed all three source checks. The actual-handler probe rejected it specifically because no tracker consumption occurred.

Could we add a small behavioral test around the production DATA handler with counted SPI/HID/tracker endpoints? Useful assertions would be:

  • the full body is read and passed to the tracker during hid_creating;
  • no HID publication happens until creation completes;
  • a registered tracker owns the pre-HID-object drain window;
  • normal HID publication still works afterward;
  • bridge traffic does not schedule the standard-liveness callback when std_liveness_ms=0.

That would protect the lifecycle fix much better than adding more source strings.

What checked out locally

  • make -C tests test: passed.
  • Clean build followed by make -C tests SANITIZE=1 test: passed, within the Makefile's existing sanitizer coverage (not every separate replay/raw object uses those flags).
  • Both kernel modules compiled against Debian Linux 6.12.111 headers. BTF generation was disabled because this host lacks pahole; no modules were loaded.
  • An extracted-production-handler probe read the full 4309-byte frame, passed 4304 bytes to the tracker, and suppressed premature HID publication.
  • Activation probes covered 16 combinations of transition value/beta/qualification and checked write-only GET6 → 4500–5500 µs pause → SET5, plus one-shot behavior.
  • The exact-ID opt-in, registration cleanup, and suspend/remove ordering did not reveal a new defect in this review.

I also checked the new HID fall-through: report 0x0c is declared in the shipped descriptor, so forwarding it is not, by itself, evidence of an unknown-report failure. I am not asking to change that based on speculation.

Remaining acceptance checks

As you already note, the earlier Gate5 results should not be treated as physical qualification of this exact extracted revision. Before merge, it would be useful to have the exact tested SHA and results for true cold boot, repeated warm reloads, suspend/resume, and real multitouch/gestures, with frame-drop and unexpected-reset counters. Please also confirm that the default standard profile remains unaffected.

The CI run for this head is currently waiting for approval (action_required), rather than failing; the GitHub host/sanitizer and kernel-build jobs still need to run. Local results above do not replace those checks or hardware evidence.

One non-blocking hardware question to retain for a labelled run: the old transition cleared read_resp_type/content_id afterward, whereas this version retains SET_FEATURE/5. That is invisible to the default legacy read encoding, so I have not classified it as a bug; the nondefault reference encoding does carry that context. Likewise, I am treating the inherited one-shot behavior across spontaneous resets as intentional unless a targeted hardware result shows otherwise.

Thanks again — this is a focused and reviewable contribution. The small watchdog correction, a real-handler regression test, and exact-revision hardware results would make the acceptance evidence much stronger.

avgbob commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review — I audited this against both the rebased branch and the original Gate5 qualification data and pushed the code/test fixes.

Current head: 458e6844fb9cb9916649624ac8ad5864bb402317.

Changes made:

  • The DATA-path runtime stream_watchdog arm is raw-only again (shid->raw_mode_active). Standard-transport CapImg no longer arms that inherited raw recovery/logging path when std_liveness_ms=0.
  • Added std_capimg_data_handler_test.py, which extracts and compiles the real production seq_handle_data() body with counted SPI/tracker/HID/workqueue endpoints. It also compiles the exact lifecycle policy helpers from spi-hid-protocol.h, rather than reimplementing those helpers in the harness.
  • The behavioral cases cover full 4309-byte read / 4304-byte tracker delivery during HID creation, no early HID publication, tracker ownership before the HID object exists, normal HID publication after creation, no standard-bridge watchdog scheduling, and a raw-mode positive watchdog control.
  • I found one extra scope issue during the audit: my first extraction let hid_creating itself acquire DATA ownership even with the bridge disabled. I narrowed that. Early drain is now extended only by the registered CapImg tracker; plain/default standard HID retains upstream creation-time behavior. Both the helper test and production-handler test have an explicit negative control for this.

Two hardware/provenance points from the older qualified Gate5 branch are worth recording, but I am not using them as acceptance evidence for this rebased head:

  1. The qualified Gate5 commit was 58f023102679ab0156ce95210abe7e3e3e6ac412. It intentionally retained the final SET_FEATURE/5 request context after the write-only GET6 -> ~5 ms -> SET5 transition. That exact behavior was present for the cold-boot, 3/3 warm-reload and 2/2 s2idle qualification runs, with zero observed frame drops and zero unexpected post-DONE resets.
  2. A normal suspend/resume explicitly clears transition_done, so the activation is re-run on resume. A spontaneous post-DONE reset in the same probe does not clear it. The qualification runs observed zero such resets, so I do not have hardware evidence for that specific case and have left the one-shot semantics unchanged.

The exact-head physical acceptance items you requested are still genuinely pending: cold boot, repeated reloads, suspend/resume, real multitouch/gestures, drop/reset counters, and a default-standard control on this exact SHA. I’ll keep the PR draft rather than relabel the historical Gate5 run as current evidence.

CI is also still action_required on the fork PR, so I’m not claiming a fresh green aggregate run yet.

@Syax89

Syax89 commented Oct 16, 2026

Copy link
Copy Markdown
Owner

Thanks for the update — I rechecked head 458e6844fb9cb9916649624ac8ad5864bb402317 with two blind review passes and executed follow-up probes. The raw-only watchdog gate and narrowed early-DATA ownership are effective, including the default-standard negative control. The original runtime finding is resolved.

One test-only issue remains:

Medium: the new production-handler harness fails to compile

tests/std_capimg_data_handler_test.py:290–295 uses cc -Wall -Wextra -Werror. On GCC 14.2.0 it fails with:

unused parameter 's' [-Werror=unused-parameter]
comparison of integer expressions of different signedness [-Werror=sign-compare]
unused variable 'hy' / 'hx' / 'dev' [-Werror=unused-variable]

The stub does not use s, logging macros discard the production variables, and the extracted rl - 3 comparisons encounter unsigned avail. Reproduce with python3 tests/std_capimg_data_handler_test.py; the clean default and sanitizer aggregates both exit 2 at this test. The base suites pass.

Could you reconcile the harness-only diagnostics with the existing host kernel-translation-unit conventions while retaining real production extraction? This is a test-build problem, not evidence of a new device runtime failure.

In a separate generated probe relaxing only host warning diagnostics, the actual handler and exact lifecycle helpers pass ASan/UBSan: 4309-byte read, 4304-byte tracker delivery, early ownership/publication controls, no standard-bridge watchdog, and raw watchdog positive control. Six independent behavior mutations are rejected (short read, disabled consumption, missing raw-only gate, lost early ownership, broadened default-standard ownership, premature publication). This supports the logic correction but does not make the shipped failing gate pass.

Both modules compile against Debian 6.12.111 headers, BTF disabled; explicit replay target compilation passes. No modules loaded. Exact-head cold boot/reloads/resume/gestures/drop-reset/default-standard checks remain open. The retained SET5 context and spontaneous-reset latch remain hardware questions, not new confirmed defects. CI snapshot is action_required, not a successful run. No source changes made during review.

avgbob commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

@Syax89 Follow-up to your GCC 14 production-handler harness review: fixed in fork head 2bf81e8. The extracted seq_handle_data() test still compiles the actual production handler and lifecycle helpers under -Werror; only mock-kernel-specific unused-parameter, unused-variable (logging stubs), and sign-compare diagnostics are exempted. No production driver change in this follow-up.

Fork CI run 38925909979 is green: normal and SANITIZE=1 host gates, whitespace, both kernel builds. Exact-head physical cold boot / warm reload / s2idle / gestures / default-standard negative control remain pending. Keeping this draft.

@Syax89

Syax89 commented Oct 16, 2026

Copy link
Copy Markdown
Owner

Thanks again for the fixes. Here is the focused follow-up verification.

Reviewed exact head 2bf81e8871068f9f72a2b7d88f33330fecf79e98 against base 72b3492ba08fdee481b5dd1fa5781025264583f9.

The corrected extracted-handler test passes unchanged. The default-standard creation-time drain/publication policy remains equivalent to base, and the opt-in tracker/watchdog gates remain scoped as intended. There is, however, a distinct steady-state difference worth stating explicitly: after HID creation, a valid unsolicited DATA report 0x0c is held by the base IRQ handler but forwarded to hid_input_report() by this PR, even with std_raw_transition=0 and raw_input_beta=0.

An executable comparison of the exact base/prior/head handlers records HID dispatcher calls 0 / 1 / 1, with no tracker consumption, for that bounded input. Positive report-0x40, insufficient-capacity and HID-creation negative controls behave as expected. This is not caused by the latest test-only correction.

Report12 is present in both the captured and hardcoded report descriptors: 16-bit SurfaceSwitch plus 4297 constant bytes. It must not be dismissed as an unknown report, nor equated with an MT contact report. Linux HID can expose such a report through its bound-driver/HIDRAW path; actual userspace effects depend on the live descriptor, binding, claims and readers. The sibling poller already has a forwarding branch, but its activation is raw-mode-only at both pins, so it does not establish unchanged pure-default runtime behavior.

I do not have evidence of a clean, no-transition default controller actually emitting this report or of a user-visible hardware regression. Please clarify whether forwarding unsolicited 0x0c on the default IRQ path is an intentional policy expansion. Until that scope decision is explicit, “ordinary standard mode unchanged” is too broad if read as byte-for-byte dispatcher behavior; it is accurate for the retained creation-time negative control, not this conditional steady-state case.

Exact-head hardware qualification remains pending: cold first probe, three warm reloads, two s2idle cycles, real gestures/contact lifecycle, drop/reset deltas and ordinary-standard control. Spontaneous post-DONE reset/re-arm remains NOT EXERCISED unless such a reset actually occurs; reloading the module cannot answer it. Historical Gate5 or experimental mode4 results are not substituted for these checks.

avgbob commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

@Syax89 Thank you for the exact-head 0x0c default-mode dispatch comparison. You're right: “ordinary standard mode unchanged” must also cover the post-HID-creation IRQ path, not just the creation-time drain policy.

Decision: forwarding unsolicited Report 12 / 0x0c in default standard mode was not intentional. Report 12 is present in the descriptor (SurfaceSwitch + constant bytes), but CapImg frames should remain held for observation/tracker rather than being newly published as ordinary HID input.

I've changed the PR head to 18f0fe79623e6de4fdf1ae493f82a7048397386a:

  • seq_handle_data() now holds report 0x0c in all standard-transport modes, preserving the upstream post-create HID-dispatch policy (including the opt-out std_raw_transition=0 raw_input_beta=0 case).
  • With the bridge enabled, the existing registered CapImg tracker still consumes that same report; no duplicate hid_input_report() publication.
  • Raw mode with a tracker likewise retains base handling; raw without a tracker and unrelated HID reports still reach the ordinary dispatcher, as before.
  • Extended the compiled actual production-handler behavioral test: post-create default-standard 0x0c dispatch 0, opt-in tracker consumption 1 / HID dispatch 0, report 0x40 dispatcher 1, raw tracker dispatch 0, raw no-tracker dispatcher 1. Existing pre-HID creation, full-body drain, and raw-watchdog controls remain covered.

All four fork CI jobs passed on this exact head, including the host tests and kernel builds. No physical test or broad compatibility claim is implied by green CI.

The prior independent GET6-free mode4 did pass a true cold-power-on + real-gesture + rollback test on kernel 7.0.0-34, but that sequence is not this PR's GET6(write-only) path, so I am not counting it toward PR #87 acceptance. The separate exact-head physical test harness is ready to begin 3/3 warm reloads, followed by s2idle, true cold boot, and default-standard controls; I will report actual recorded results, keeping this PR draft in the meantime.

avgbob commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

@Syax89 Exact-head physical acceptance update for 18f0fe79623e6de4fdf1ae493f82a7048397386a: 3/3 warm activations PASSED on my SL4 AMD MSHW0231, Ubuntu 7.0.0-34-generic.

All three cycles used the same existing-MOK-signed module, SHA256 61ec6f796d60b6e50d1c1888dc693e6cd135d08a023f1bccb0fc5ade15054d8e, loaded srcversion=65F0D14FBDFB5E84748373E (distinct from installed Gate5 3326E559A916BE5CB52375D). For each cycle the spoken/event-gated physical capture passed one-finger movement and release, two-finger pinch→expansion continuity and sequential release, with no new reset/frame-drop failures reported by the capture harness; source identity and evidence checksums passed. The installed Gate5 driver was restored and verified bound after every cycle.

Local physical evidence: ~/sl4a-hardware-runs/pr87-exact-warm3-20261016T193705Z/{cycle-1-quick,cycle-2-quick,cycle-3-quick}. Full evdev files and individual counter snapshots remain on the physical tester, not attached to this PR. The reported runner verdict was PR87 WARM 3/3 PASS.

The first attempt was incomplete due to a set -u variable-order bug in the external test harness before gesture capture, then restored Gate5; the corrected harness completed the independent three cycles above. No runtime-driver failure was observed in that earlier aborted attempt.

Still pending for this exact PR SHA: full gesture matrix, two genuine s2idle/resumes, true cold first-HID activation, and default-standard negative control. Spontaneous post-DONE reset/re-arm remains unexercised. Keeping PR draft while these tests are completed. This should not be conflated with the separate GET6-free mode4 coldboot evidence.

avgbob commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

@Syax89 Follow-up on the same exact PR #87 source head 18f0fe79623e6de4fdf1ae493f82a7048397386a: the physical Surface Laptop 4 AMD / MSHW0231 now also passed 2/2 genuine s2idle sleep/resume cycles with post-wake verified multitouch on kernel 7.0.0-34-generic.

The two measured CLOCK_BOOTTIME - CLOCK_MONOTONIC sleep gaps were 158.454s and 324.521s. The harness checked the kernel PM: suspend entry (s2idle)/exit markers, retained the same signed PR module (srcversion=65F0D14FBDFB5E84748373E, SHA256 61ec6f796d60b6e50d1c1888dc693e6cd135d08a023f1bccb0fc5ade15054d8e), driver bindings, and postwake audio confirmation. Each wake was followed by an independent live event-gated single-finger movement and two-original-finger pinch→expand→release PASS, with reset/drop integrity checks. Production Gate5 restored and rebound at the end; harness verdict PR87 S2IDLE 2/2 PASS.

Local evidence (not yet uploaded): ~/sl4a-hardware-runs/pr87-exact-s2idle2-20261016T201323Z/ with per-cycle evdev/cue bundles and verified PM/clock/stat checksums.

One operator observation: the separate spoken test helper repeatedly said One original finger remains. Lift it now just before marking release PASS. I audited the helper: it emits this on a real intermediate {A,B}->{A} (or {B}) contact frame; the event gate does NOT pass until the contact set subsequently reaches zero. The voice statement can be stale by playback time. I've suppressed only that intermediate spoken instruction in the external evidence harness (retaining the cue and unchanged zero-contact validation), with behavioral regression coverage. This does not alter the tested PR driver or imply a sustained phantom touch; raw sub-second release latency has not yet been measured from the local trace.

Still pending before requesting upstream acceptance: exact-head true cold first-HID load, full gesture matrix, and default-standard/opt-out negative control. Previous separate GET6-free mode4 cold-start results are still not being counted as PR87 evidence.

avgbob commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor Author

@Syax89 Final exact-head PR #87 physical qualification update for 18f0fe79623e6de4fdf1ae493f82a7048397386a on my Surface Laptop 4 AMD / MSHW0231, Ubuntu 7.0.0-34-generic.

All five defined test categories completed on this one unit:

  • Warm activation: 3/3 PASS
  • Genuine s2idle with post-wake gesture capture: 2/2 PASS
  • Guided 1–5-contact gesture matrix: 16/16 PASS
  • Default-standard opt-out: PASS on retrospective correction of a field verifier bug (ready="ready" vs expected 1). The original INCONCLUSIVE verdict is preserved.
  • True first-HID cold power-on: PASS. The staging boot and test boot IDs differed; the test/current boot IDs matched. Following confirmed full poweroff/on, live one-finger and two-finger pinch/expand/release tests passed. Gate5 and both controller/HID bindings were restored; the saved cold-boot manifest verified 15/15 files.

The physical tests used the same signed exact-PR binary; the module source identity was distinct from installed Gate5. The original raw evdev/kernel journal evidence remains on the tester and has not been independently replayed or uploaded.

Full details, hashes, boot IDs, paths and limitations: hardware acceptance record and upstream handoff.

These results qualify one device/kernel/revision only, not spontaneous post-DONE reset/rearm, endurance, other hardware, or kernel-mainline integration. Would a particular additional failure-path test or sanitized log excerpt help before deciding whether to take the PR out of draft?

@Syax89
Syax89 marked this pull request as ready for review October 18, 2026 10:40
@Syax89
Syax89 merged commit f4beff0 into Syax89:main Oct 18, 2026
4 checks passed
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.

2 participants