Commit Graph
10 Commits
Author SHA1 Message Date
catarrh 9f42a88c01 v1.9.3: extended-channel CLA classes + defined odd INS in the acceptance gates 2026-10-17 23:29:09 +03:00
catarrh 3bf5cee222 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.
2026-09-27 23:52:40 +03:00
catarrh 18ee720fda docs: finish rename sweep — no more 'pysniff' shorthand
Follow-up to ad3ff6b: the two remaining prose mentions of the old
short name become SIMtrace Analyser (AGENTS.md v1.9.0 note, test
comment).  Upstream 'simtrace2-sniff'/'simtrace2' references stay --
those are the Osmocom tool/hardware, not the renamed project.
2026-09-19 12:50:26 +03:00
catarrh 250c09c9b7 v1.9.0: CLK rate in RST events; v1.9.1: T=0 NULL is not an SW1
v1.9.0 -- CLK frequency in RST events:
- RST events (sub_type 0x10) append the measured CLK frequency when known:
  [direction, level, flags, clk_hz_be32], flags bit 0 = rate present; the
  3-byte form is kept when the rate is not yet measured.  Value is
  samplerate / _samples_per_clock from the existing 16-edge measurement (PPS
  changes F/D, not the CLK rate).  VCC events unchanged.  Backward
  compatible (old consumers read the first two bytes only); consumers can
  compute data_rate = clk_hz x D / F from the ATR/PPS Fi/Di.
- Unit tests for the payload codec; README/README_RUS/AGENTS updated.

v1.9.1 -- T=0 NULL is not an SW1:
- The 'scan for SW1' loops accepted any 0x6X byte, including the NULL
  procedure byte 0x60 (card busy), so 'NULL + real SW1' was mis-framed as
  the status word: the phone traces' SELECT MF came out as ...3f00 6061 —
  real SW1 0x61 eaten as SW2, real SW2 0x29 left on the wire and discarded
  as a suspicious CLA (desync cascade).
- plausible_sw() now accepts 0x61-0x6F and 0x90-0x9F only, per
  ISO 7816-3:2006 10.3.3 Table 11 ('6X' or '9X', EXCEPT '60'; ISO 7816-4
  enforces '60' as an invalid SW1) and UICC_SPECS.md 1.8.  All seven
  SW1-detection sites use plausible_sw(); NULLs met while scanning are
  logged as rate-limited wait extensions (_note_pre_sw) instead of
  suspicious bytes.
- tools/vs_reader.py::_plausible_sw() mirrors the fix; regression vector
  for the 00a40004023f006061 artifact.

Validation: 74/74 unit tests; baseline regenerated and IDENTICAL (the SW
fix is count-neutral -- only the SW bytes change); all 9 example pcaps
regenerated -- vs_reader OK, zero APDUs ending in 60 61, SELECT MF now
61 29 / 61 25.
2026-09-19 00:55:33 +03:00
catarrh e5a2b7c83b v1.8.0: PPS as standard request/response packets; fix res-byte flag docs
- Split the PPS exchange into the two standard GSMTAP-SIM subtypes:
  0x02 (PPS_REQ, raw request bytes, span ss..es_req) and 0x03 (PPS_RSP,
  raw response bytes, span es_req..end), replacing the single 0x02 packet
  with concatenated request+response that deviated from libosmocore's
  gsmtap.h.  Wireshark now dissects both halves; simtrace2-pysniff needs
  no change (its importer already maps 0x03 to 'pps' and _decode_pps()
  parses the 0xFF-leading response frame).  PPS annotation/log unchanged.
- gsmtap_stream.py: GSMTAP_SIM_PPS_REQ/RSP constants; header field labels
  aligned with libosmocore's struct (signal_dbm/snr_db).
- Docs: GSMTAP event tables (EN/RU) updated, PPS deviation note removed;
  corrected the res-byte flag attribution -- upstream simtrace2 never
  sets res, so the GSMTAP_FLAG_BAD_FCS carriage is this decoder's own
  extension (semantics mirror simtrace2's USB data flags).
- Tests: assert the PPS subtype values; baseline regenerated (only the
  version line and test listing differed -- no decode-metric changes).
  68/68 unit tests.
2026-09-17 23:01:40 +03:00
Трошин Антон Валерьевич 7db29e3ce2 v1.7.1: accept EOFError as clean end-of-stream (newer libsigrokdecode)
Newer libsigrokdecode signals end-of-capture from wait() by raising
EOFError("samples exhausted"); Linux 0.5.3 instead returns None / raises
SystemError, so this only reproduced on Windows.  The framework explicitly
accepts EOFError out of decode() as normal termination, but decode() caught
it in the generic except Exception handler -- printing a traceback, logging
DECODE ERROR, and resyncing up to 50 times, which flooded the log at the end
of every capture.

- decode() and the five "except SystemError: raise" guards now use
  "except (SystemError, EOFError): raise", letting the end-of-stream signal
  propagate for a clean exit.  The critical guard is
  _measure_clock_period(), whose try wraps a wait() loop.
- 2 new unit tests assert decode() re-raises EOFError and SystemError.
- 67/67 unit tests; test_8/test_7/xiaomi_phone unchanged (Linux path).
  VERSION -> 1.7.1.
2026-09-11 18:12:03 +03:00
Трошин Антон Валерьевич 690cc132ca v1.7.0: spurious end-of-decode hardening + session-resilient start.sh
The decoder could end decode() early on an idle/busy live line; the frontend
symptom was a flood of "sr_session_stop: session was NULL" after the session
stopped.  Harden the EOF detection and stop the capture from dropping.

pd.py:
- _at_eof(): a step that consumes only queued bytes (_replay / peeked_byte,
  e.g. the invalid-INS re-frame) no longer counts as end-of-capture; bounded
  to 64 consecutive no-advance steps.
- _stall_check(track=False): the idle-LEVEL wait in wait_data_falling returns
  immediately at the same sample on an idle line -- not EOF.  Only "pins is
  None" ends the wait there; sample-stall detection is kept for the edge wait.
- resync_idle(): guard wait()==None (was an unguarded pins[...] TypeError at
  stream end).

Effect: samsung_phone_sample.sr had halted at ~21.9M/320M samples with 1 APDU;
it now decodes through ~293M to a true end (939 APDUs, CHKSUM 176).  The 6
CONCAT packets are real mis-framed STK bursts now reachable (known Samsung
de-concatenation family).  All other traces unchanged.

start.sh:
- Auto-restart is now the default (--no-loop disables) so an intermittent
  FX2 USB stop reconnects instead of ending the session.
- Per-session pcap suffix (FILE.N.ext) so a restart never overwrites the
  previous capture.
- Filter the repetitive "sr_session_stop: session was NULL" teardown line
  from stderr (real decoder errors still pass).

Validation: test_8 56/0/OK, test_7 65/0/OK, xiaomi_phone 640, xiaomi_cold
473, 4gmodem 327, A55 407/395, S21p 399/375, target S21p 369; 0 CONCAT;
65/65 unit tests (10 new).  VERSION -> 1.7.0.
2026-09-11 17:55:56 +03:00
Трошин Антон Валерьевич bca1b85b94 v1.6.0: ATR-hunt deadlock + idle-loop trap fixes
Add hunt-side live ETU recovery so a card already at a non-default F/D
(e.g. Samsung F=512/D=32 -> 16 CLK/bit) can be decoded without a 372-rate
ATR, and bound the all-0xFF hunt so an idle/unsyncable line can never loop
forever.

- _recover_etu_in_hunt(): measure the live ETU from DATA edges while still
  in FIND START, then re-derive clock_skip; reuses _confirm_etu validation.
- _atr_hunt_failure_action(): pure recover/retry/resume_data decision, with
  ATR_HUNT_ETU_ATTEMPTS=3 / ATR_HUNT_IDLE_RESETS=3 / ATR_HUNT_FAIL_LIMIT=12.
- Persistent counters reset only on a successful ATR parse (not RST re-arm),
  so RST-cycling phones cannot starve the escape.
- 8 new unit tests (55 total).

Validated on the full trace suite (test_8 56/0/OK, test_7 65/0/OK, xiaomi
640, xiaomi_cold 473, 4gmodem 327, A55 407/395, S21p 399/375, target S21p
369; 0 CONCAT, RESULT: OK) with no regressions.
2026-09-11 17:45:54 +03:00
catarrh e1903649a7 Hygiene: drop dead code, re-raise SystemError, resource+doc cleanup, add LICENSE
- pd.py: remove _lock_etu_from_edges (long-disabled) and the no-op
  while-True FIND START wrapper.
- pd.py: re-raise SystemError (libsigrokdecode's clean EOF signal) in the
  six 'except Exception: pass' guards so put()/wait() at end-of-capture
  exits cleanly instead of being swallowed.
- pd.py: fix _measure_clock_period docstring (averages, not robust-min);
  drop stale 'line 1633' comment; document the synthetic pcap UDP header
  (zero IP checksum / fixed loopback+ports are intentional).
- signal_diagnostic.py: add --max-samples cap + document whole-capture
  RAM cost; fix stale '--rst/--vcc=ignore' guidance (-> --no-rst/--no-vcc).
- tests: make test_valid_cla_interindustry_classes use subTest (was a
  no-op tuple expression).
- start.sh/start.bat: note the -A multi-spec form is sigrok-cli 0.7.x.
- Remove stale tests/baseline_new.txt (v1.1.3-era, ATR-included mode).
- Add top-level LICENSE (GPL-2.0-or-later).
2026-09-11 01:33:12 +03:00
catarrh d3715c9385 v1.5.0: invalid-INS one-byte re-frame + explicit discard logging
Residual CONCAT mis-frames (4gmodem/A55_sim2/S21p_sim2) traced to a silent
5-byte drop at an invalid-INS T=0 header (0x0f 00 a4 08 04). Drop only the
stray leading byte and re-frame the remaining four via _replay so the real
command (00 a4 08 04 02 2f 00 -> 61 1c) is recovered.

- _note_discard()/_consume_first(): every consumed-but-unemitted byte is
  now logged; idle 0x00/0xFF discards are rate-limited, real data always
  gets an ANN_WARN annotation.
- All read-until-SW loops log skipped non-SW bytes.
- All traces: CONCAT 0; BAD_FCS/GARBAGE 0; test_8/test_7 RESULT OK;
  47/47 unit tests; baseline byte-identical.

History rewritten to a single root commit so no example trace is stored
in the repo (fixtures are local-only, gitignored). README keeps only
generic <trace>.sr placeholders; AGENTS.md retains the fixture names.
2026-09-09 15:51:09 +03:00