From 5d520a1ff9637750643fe1b546db1b26ff5106b7 Mon Sep 17 00:00:00 2001 From: BlackMark Date: Fri, 31 Jul 2026 13:25:46 +0200 Subject: [PATCH] pbhw: --one-wire never reached the suite's own sessions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The flag was plumbed through pbrig.Deployment to the host-tool subprocess calls and nowhere else, so identity() and scan() opened a raw port and drove a shared line as though it were two wires. On real one-wire hardware the adapter's echo answers the knock before the device does, so the suite would have died at its very first check — "the loader never answered; nothing below can be trusted" — for the one deployment the flag exists to test, and every result after it is gated on that check passing. Both now open through pbrig.Rig.open_port(), which applies the deployment's link mode. The gap underneath was that only the subprocess path could reach those facts at all; anything driving the protocol in-process had to restate them, and did not. Co-Authored-By: Claude Opus 5 --- tools/pbhw.py | 7 +++++-- tools/pbrig.py | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/tools/pbhw.py b/tools/pbhw.py index 270358d..2976130 100755 --- a/tools/pbhw.py +++ b/tools/pbhw.py @@ -53,7 +53,7 @@ class Suite: """The info block, which every later check takes its bounds from.""" module = pbrig.load_pureboot(self.rig.d.pureboot) self.rig.reset() - port = module.Port(self.rig.d.port, self.rig.d.baud) + port = self.rig.open_port() # wrapped for the echo where the line is shared try: loader = module.Loader(port) if self.rig.d.autobaud: @@ -87,7 +87,10 @@ class Suite: rate = module.scan_rate(self.rig.d.baud, pct) self.rig.reset() try: - port = module.Port(self.rig.d.port, rate) + # Same wrap as identity(): on a shared line an undiscarded + # echo answers every rate a scan probes, so the walk would + # report the first one it tried. + port = self.rig.open_port(rate) except module.Error as error: self.check("scan opens every probe rate", False, f"{rate} Bd: {error}") return diff --git a/tools/pbrig.py b/tools/pbrig.py index fa0e4b9..fc65fae 100755 --- a/tools/pbrig.py +++ b/tools/pbrig.py @@ -281,6 +281,22 @@ class Rig: return 99, f"TIMEOUT after {timeout}s\n{expired.stdout or ''}{expired.stderr or ''}" return result.returncode, (result.stdout or "") + (result.stderr or "") + def open_port(self, baud: int | None = None): + """A port opened the way this deployment says to speak to the board. + + Everything the rig runs as a *subprocess* gets its flags from + `pureboot()` above; anything that drives the protocol in-process has + to reach the same facts, and until this existed only the subprocess + path could. A shared line is the one where that gap is fatal rather + than untidy: the host reads back every byte it writes, so an + undiscarded echo answers the knock before the device does. Open + through here and a one-wire deployment cannot be silently driven as + a two-wire one. + """ + module = load_pureboot(self.d.pureboot) + port = module.Port(self.d.port, self.d.baud if baud is None else baud) + return module.OneWirePort(port) if self.d.one_wire else port + def capture(self, seconds: float = 2.0, baud: int | None = None) -> bytes: """Listen to whatever the board is saying, at an arbitrary rate.