v1.9.2: PPS CLK upshift + exact CLK-edge projection (new reader fixture)
- handle_pps(): flag the first post-PPS character; _read_byte_clk() re-measures the CLK period there and accounts the measurement's 16 edges. The Alcor reader upclocks 4.0 -> 4.8 MHz at PPS (FI/DI still 512/32), so the ATR measurement was stale: 64 vs 53.33 samples/ETU, no post-PPS APDU framed. - _wait_clk_rising(): project to the n-th edge (skip to target - half a period, take one edge) instead of "skip n-2 cycles + 2 edges", which lost ~1 edge per call on fractional periods and slid the samples ~0.5 ETU early by the parity bit. xiaomi 7698 -> 2, 4gmodem 7218 -> 0, S21p_sim2 394 -> 0 CHKSUM lines (previously misread as dirty-wire noise). - CONCAT gate: EMBEDDED_CLA excludes the structural 0x4x/0x5x classes (payload false hit on the Alcor secured packet); mirrored in tools/vs_reader.py and covered by a new vector in tests/test_gsmtap.py. - tools/capture_baseline.sh: add the alcor_reader_sample fixture; baseline regenerated (APDU counts and RESULT: OK unchanged everywhere, 0 CONCAT). - 75/75 unit tests. README/AGENTS updated.
This commit is contained in:
1 parent
18ee720fda
commit
3bf5cee222
7 files changed
+184
-104
No files matched your search
@@ -18,6 +18,7 @@ Every change to `pd.py` must be followed by running the full test suite:
|
||||
for trace in test_8_raw16 test_7_raw16 xiaomi_phone_sample \
|
||||
samsung_phone_sample \
|
||||
xiaomi_mi_a1_coldboot_sample 4gmodem_coldboot_sample \
|
||||
alcor_reader_sample \
|
||||
samsung_A55_coldboot_new_cable samsung_A55_coldboot_new_cable_sim2 \
|
||||
samsung_S21p_coldboot_new_cable samsung_S21p_coldboot_new_cable_sim2; do
|
||||
# Run sigrok-cli and vs_reader as shown below
|
||||
@@ -308,6 +309,54 @@ Known limitation: no on-disk fixture reproduces the exact live failure (all
|
||||
real captures contain a 372 ATR), so end-to-end proof needs a re-captured
|
||||
`.sr` from the failing phone; the unit tests cover the loop-escape logic.
|
||||
|
||||
### v1.9.2: PPS CLK upshift + exact CLK-edge projection (new reader support)
|
||||
|
||||
Two timing bugs surfaced by `examples/alcor_reader_sample.sr`, a PC/SC reader
|
||||
that changes the CLK frequency at PPS: 4.0 MHz at the ATR, 4.8 MHz after
|
||||
(raise-to-raise 4.000 -> 3.333 samples at 16 MHz), with FI/DI still 512/32 =
|
||||
16 CLK/bit. Before the fix the whole post-PPS session framed nothing.
|
||||
|
||||
- **Stale samples-per-clock after PPS.** The native/CLK-sync path assumed
|
||||
"the CLK period is unchanged by PPS" and kept the period measured at the
|
||||
ATR, so the post-PPS ETU was 16 x 4.0 = 64 samples instead of the real
|
||||
16 x 3.333 = 53.33 -- every byte was mis-sampled. `handle_pps()` now sets
|
||||
`_clk_remeasure_pending`; `_read_byte_clk()` consumes it in the first
|
||||
post-PPS character (CLK is guaranteed to be running inside a frame),
|
||||
re-runs `_measure_clock_period()` and accounts the measurement's 16 edges
|
||||
as the first edges of the frame (`bit_samples` refreshed).
|
||||
- **Edge-skip deficit on fractional periods.** `_wait_clk_rising()` used to
|
||||
"skip (n - 2) cycles by samples, then take 2 edges". With a period that is
|
||||
a fraction of a sample the skip under-covers by ~1 edge per call: simulated
|
||||
against the real trace, 144 edges were consumed where 152 were requested,
|
||||
so the samples slid ~0.5 ETU early by the parity bit -- in 513/513 CHKSUM
|
||||
cases the "parity" sample read the last data bit. It now projects n
|
||||
periods ahead of the edge it is sitting on, skips to (target - half a
|
||||
period) and takes one edge: exact for any period, non-accumulating, one
|
||||
wait() per call. Without a period estimate it waits each edge exactly.
|
||||
- **CONCAT detector precision.** The Alcor GET RESPONSE payload (a
|
||||
secured-packet byte run "40 70 70 61 15" + an SW-like byte 21 later)
|
||||
false-hit the embedded-exchange scan through the structural 0x4x CLA that
|
||||
`plausible_cla()` tolerates for resync robustness. The detector's CLA set
|
||||
now excludes 0x4x/0x5x (no CAT traffic uses them; every tuned
|
||||
true-positive vector uses 0x00/0x01/0x08/0x80), mirrored in
|
||||
`tools/vs_reader.py` with a regression vector in `tests/test_gsmtap.py`.
|
||||
|
||||
Effect on the suite (baseline regenerated; APDU counts and `RESULT: OK`
|
||||
unchanged everywhere, 0 CONCAT):
|
||||
|
||||
| trace | CHKSUM lines before | after |
|
||||
|---|---|---|
|
||||
| alcor_reader_sample (new fixture) | no framing at all (0 APDUs) | 2 (1 idle artifact), 48 APDUs |
|
||||
| xiaomi_phone_sample | 7698 | 2 (1 event) |
|
||||
| 4gmodem_coldboot | 7218 | 0 |
|
||||
| samsung_S21p_coldboot_new_cable_sim2 | 394 | 0 |
|
||||
| test_8 / test_7 / others | 0 | 0 |
|
||||
|
||||
The xiaomi/4gmodem/S21p_sim2 counts had been read as dirty-wire parity
|
||||
noise -- they were this decoder bug. `tools/capture_baseline.sh` gains the
|
||||
alcor fixture (local-only, like every `examples/` trace). 75/75 unit tests.
|
||||
VERSION -> 1.9.2.
|
||||
|
||||
### v1.9.1: T=0 NULL is not an SW1 (fixes bogus "60 61" APDU endings)
|
||||
|
||||
The "scan for SW1" loops accepted any byte with high nibble `0x6` as a
|
||||
@@ -704,7 +753,7 @@ append the measured CLK frequency when known
|
||||
|
||||
### Versioning
|
||||
|
||||
The decoder version is defined in `pd.py` as `VERSION = '1.9.1'`.
|
||||
The decoder version is defined in `pd.py` as `VERSION = '1.9.2'`.
|
||||
The version is printed to the log on decoder startup.
|
||||
|
||||
### Testing after decoder changes
|
||||
|
||||
Reference in new issue
Block a user