Compare commits

...
5 Commits
Author SHA1 Message Date
catarrh 847b49ec12 README: drop the FX2 8-bit/24 MHz samplerate explanation 2026-10-27 11:20:31 +03:00
catarrh a385648a80 README: install/start first, remove history-heavy sections
- Move installation/startup to the top (after a short intro): download
  (Linux tar.gz / Windows zip) and source checkout, each ending with the
  setup/start commands.
- Usage (start options, wiring, pin mapping, clock modes, troubleshooting,
  raw sigrok-cli) follows the install section instead of preceding it.
- Remove "Robustness against noisy signals" (decoder internals, not
  end-user information).
- Remove historical explanations (early-version failures, "used to",
  before/after fix counts) from troubleshooting, clock modes, capture
  scenarios, cold-boot, validation and data-rate notes.
- Rewrite live-capture troubleshooting: early stopping (especially on
  Windows) is commonly the wrong USB driver - the Saleae Logic driver
  works only with Saleae Logic software, sigrok needs WinUSB (Zadig) -
  with links to sigrok's Windows/FX2 documentation; keep the current
  device-not-found, USB-bandwidth and auto-restart guidance.
- Move the tap photos below Usage; features/reference/development sections
  follow.  Russian README mirrors the same structure and edits.

Docs only; no decoder or release change.
2026-10-27 10:48:42 +03:00
catarrh 8e36419143 README: add the project website next to the Telegram channel 2026-10-26 22:11:37 +03:00
catarrh 50fe1bc51b README: add the project Telegram channel link 2026-10-23 21:43:36 +03:00
catarrh 2e3a563824 Release notes: prepend both install ways to generated notes
The release page now leads with the two supported installation paths —
release package (Linux tar.gz / Windows zip, setup/start, SHA256SUMS) and
source checkout for development — before GitHub's generated changelog.
The block is written by the workflow (`--notes-file` + `--generate-notes`),
so every future v* release carries it.  The v1.9.7 release body is updated
manually to the same text; no code or version change.
2026-10-21 00:04:19 +03:00
4 changed files with 641 additions and 882 deletions

No files matched your search

+32 -2
View File
@@ -45,6 +45,33 @@ jobs:
- name: Build release archives - name: Build release archives
run: ./tools/build_release.sh "$GITHUB_REF_NAME" run: ./tools/build_release.sh "$GITHUB_REF_NAME"
- name: Write the install notes
shell: bash
run: |
set -euo pipefail
version=$(sed -n "s/^VERSION = '\([0-9][0-9.]*\)'.*/\1/p" pd.py)
notes="$RUNNER_TEMP/release-notes.md"
cat > "$notes" <<'EOF'
Runtime release - the decoder, setup/start scripts, docs and README
images; no git history and no development files.
**Install - release package (recommended)**
- Linux: `sigrok_iso7816_stream-<VERSION>.tar.gz`
- Windows: `sigrok_iso7816_stream-<VERSION>.zip`
Extract the archive, then run `./setup.sh` + `./start.sh` (Linux) or
`setup.bat` + `start.bat` (Windows). `SHA256SUMS` (attached) verifies
both downloads. Requires sigrok-cli and the FX2 firmware; see the
README *Installation* section for the full prerequisites.
**Install - source checkout (development)**
`git clone https://github.com/anttro/sigrok_iso7816_stream.git`, then
the same setup/start scripts. The clone adds `tests/`, the baseline
tools and the (local-only) example traces; the release package is the
runtime tree.
EOF
sed -i "s/<VERSION>/$version/g" "$notes"
- name: Create or update the GitHub release - name: Create or update the GitHub release
shell: bash shell: bash
env: env:
@@ -52,12 +79,15 @@ jobs:
run: | run: |
set -euo pipefail set -euo pipefail
version=$(sed -n "s/^VERSION = '\([0-9][0-9.]*\)'.*/\1/p" pd.py) version=$(sed -n "s/^VERSION = '\([0-9][0-9.]*\)'.*/\1/p" pd.py)
notes="$RUNNER_TEMP/release-notes.md"
# Upload into an existing release first. If the release does not # Upload into an existing release first. If the release does not
# exist yet, create it as a draft so the published release never # exist yet, create it as a draft so the published release never
# appears with a partial asset set. # appears with a partial asset set. The install notes are prepended
# to GitHub's generated changelog.
if ! gh release upload "$GITHUB_REF_NAME" dist/* --clobber; then if ! gh release upload "$GITHUB_REF_NAME" dist/* --clobber; then
gh release create "$GITHUB_REF_NAME" dist/* --draft \ gh release create "$GITHUB_REF_NAME" dist/* --draft \
--title "sigrok_iso7816_stream $version" --generate-notes --title "sigrok_iso7816_stream $version" \
--notes-file "$notes" --generate-notes
fi fi
# Publish a new draft and re-publish an existing one. # Publish a new draft and re-publish an existing one.
gh release edit "$GITHUB_REF_NAME" --draft=false gh release edit "$GITHUB_REF_NAME" --draft=false
+8 -5
View File
@@ -1050,11 +1050,14 @@ untouched, and `gh release upload dist/*` can never attach a stale version).
(`tests/test_gsmtap.py`), tag == `pd.py` VERSION, the build script, then (`tests/test_gsmtap.py`), tag == `pd.py` VERSION, the build script, then
`gh release upload --clobber` (or `gh release create --draft` when there is `gh release upload --clobber` (or `gh release create --draft` when there is
no release yet) followed by `gh release edit --draft=false`, with no release yet) followed by `gh release edit --draft=false`, with
`release-<tag>` concurrency. **Release process:** commit the docs, workflow `release-<tag>` concurrency. The workflow prepends a standard install block
and scripts first, then tag `v1.9.7` and push the tag (with user approval) - to the generated notes: release package (recommended; Linux tar.gz / Windows
the workflow must exist in the tagged commit, and the archive ships the zip, setup/start, SHA256SUMS) and source checkout (development). **Release
committed READMEs. Release notes are GitHub's auto-generated notes from the process:** commit the docs, workflow and scripts first, then tag `v1.9.7` and
commits; `AGENTS.md` and `tests/` are not in the archive. Packaging/docs push the tag (with user approval) - the workflow must exist in the tagged
commit, and the archive ships the committed READMEs. The changelog itself is
GitHub's auto-generated notes from the commits; `AGENTS.md` and `tests/` are
not in the archive. Packaging/docs
only - no decoder behavior change, and `VERSION` is unchanged. only - no decoder behavior change, and `VERSION` is unchanged.
### Testing after decoder changes ### Testing after decoder changes
+294 -429
View File
@@ -1,5 +1,7 @@
# sigrok_iso7816_stream # sigrok_iso7816_stream
📢 Project news and updates: [Website](https://atroshin.ru) · [Telegram channel](https://t.me/youeyeseesee)
Fork of [svenso/sigrok_iso7816](https://github.com/svenso/sigrok_iso7816) with Fork of [svenso/sigrok_iso7816](https://github.com/svenso/sigrok_iso7816) with
**live GSMTAP UDP streaming**, making a cheap FX2 logic analyzer (Saleae clone) **live GSMTAP UDP streaming**, making a cheap FX2 logic analyzer (Saleae clone)
behave like a SIMtrace2 sniffer: behave like a SIMtrace2 sniffer:
@@ -16,6 +18,252 @@ recommended tool for visualising live traces and viewing saved captures —
it can also import/export GSMTAP pcap files (including the PCAP written by it can also import/export GSMTAP pcap files (including the PCAP written by
this decoder's `pcap_file=<path>` option). this decoder's `pcap_file=<path>` option).
## Install and start
Both ways install the same decoder — pick one:
- **Download (recommended)** — a release archive. Nothing to clone and no git
history: extract it, run `setup`, then `start`. Best if you only want to
capture.
- **Source checkout** — a `git clone`. The same runtime plus the development
material: `tests/` and the trace/baseline tools (`tools/capture_baseline.sh`,
`tools/compare_baseline.sh`, `tools/vs_reader.py`). Example traces
(`examples/`) are gitignored and stay local in either case. Release archives
do not contain `tests/`, the dev tools or `examples/`.
### Download (recommended)
Grab the latest archive from
[Releases](https://github.com/anttro/sigrok_iso7816_stream/releases/latest):
- `sigrok_iso7816_stream-<version>.tar.gz` — Linux
- `sigrok_iso7816_stream-<version>.zip` — Windows
Each release also publishes `SHA256SUMS`, which lists **both** archives; keep
it next to the file you downloaded and verify:
```bash
sha256sum -c --ignore-missing SHA256SUMS # GNU coreutils (Linux)
```
On Windows run `certutil -hashfile sigrok_iso7816_stream-<version>.zip SHA256`
and compare the output with the `.zip` line in `SHA256SUMS`.
#### Linux (download)
```bash
tar xzf sigrok_iso7816_stream-<version>.tar.gz
cd sigrok_iso7816_stream-<version>
./setup.sh
./start.sh
```
`setup.sh` verifies sigrok-cli and the FX2 firmware package
(`sigrok-firmware-fx2lafw`) are installed, symlinks the project directory into
`~/.local/share/libsigrokdecode/decoders/iso7816` (user-local decoders shadow
system-wide ones), and probes the connected device for its maximum supported
samplerate.
#### Windows (download)
Prerequisites:
1. **sigrok-cli** Windows installer (0.7.2 x86_64) from
[sigrok.org/wiki/Downloads](https://sigrok.org/wiki/Downloads) — the tested
release. Nightly Windows installers are also published on that page; they
may change the sigrok-cli syntax or the decoder API, so the 0.7.2 release
installer remains the supported version.
If sigrok-cli fails to start with error `0xc0150002`, install the
[Visual C++ 2010 Redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=26999)
(`msvcr100.dll` is required by the bundled Python runtime).
2. fx2lafw firmware ships bundled with the installer — no separate download.
Driver setup (FX2 dongles need WinUSB, the vendor driver won't work):
- Run **Zadig**, which ships *inside* the sigrok-cli installation directory
(also reachable from the Start menu). Select the FX2 device in its dropdown
and install the **WinUSB** driver.
- After firmware upload the device re-enumerates with a different VID/PID —
if it still isn't found, run Zadig a **second time** for the re-enumerated
entry.
- Windows binds drivers per USB port when no serial number is present:
moving the dongle to another port may require repeating Zadig.
Then extract the release `.zip` (right-click → Extract All in Explorer) and
run, inside the extracted folder:
```bat
setup.bat
start.bat
```
`setup.bat` verifies sigrok-cli and bundled firmware, registers this project's
decoder via a junction into `%LOCALAPPDATA%\libsigrokdecode\decoders\iso7816`
(confirmed by `sigrok-cli -L` listing `iso7816`), and probes the device's
accepted samplerates. The release zip ships the batch files with CRLF line
endings, so no conversion is needed. `start.bat --help` lists its options
(the core subset of `start.sh`: channels, samplerate, clock, host/port, pcap,
protocol, debug).
### Source checkout
#### Linux (source checkout)
```bash
git clone git@github.com:anttro/sigrok_iso7816_stream.git
cd sigrok_iso7816_stream
./setup.sh
./start.sh
```
`setup.sh` performs the same checks and symlink as above.
#### Windows (source checkout)
The Windows prerequisites (sigrok-cli + the Visual C++ 2010 Redistributable,
the bundled fx2lafw firmware, and the Zadig/WinUSB driver setup) are the same
as in [Windows (download)](#windows-download) above.
```bat
git clone git@github.com:anttro/sigrok_iso7816_stream.git
cd sigrok_iso7816_stream
setup.bat
start.bat
```
`setup.bat` performs the same checks and junction registration as above.
`start.bat` supports the core option subset; the space form is the primary
one, and `--clk=CH` also works (`start.bat --help` lists them):
```bat
start.bat --clk D1 --data D6
```
Note: batch files need CRLF line endings; the repo enforces this via
`.gitattributes`, so a fresh clone on Windows is already correct (the release
zip ships the same CRLF files).
## Usage
`start.sh` captures continuously at 16 MHz until Ctrl+C (`rc=130`) and streams
GSMTAP to 127.0.0.1:4729. Defaults: pins D5=CLK, D0=I/O, D4=RST, D2=VCC.
Override via args:
```bash
./start.sh --clk=D1 --data=D6 # different wiring
./start.sh --no-rst --no-vcc # CLK+I/O only
./start.sh --host=10.0.28.7 # stream to a remote analyser
./start.sh --pcap=session.pcap # also record decoded events to PCAP
./start.sh --debug # full decoder + sigrok output (all
# annotation rows + libsigrok -l 4);
# by default only decoded APDUs and
# decoder warnings/errors are shown
```
On Windows, `start.bat` takes the same core options (space form; the
`--opt=value` form also works) — see the Windows install notes above.
### Wiring
The recommended tap is the short cable with external pull resistors (see
*The tap in practice* below): 10 kΩ to GND on VCC (pulls low when off) and
47 kΩ to VCC on DATA (faster rise to high). Its pin mapping is **fixed and
known in advance** — see the "Pin mapping" table below — and is exactly what
`start.sh` defaults to (`D5`=CLK, `D0`=I/O, `D4`=RST, `D2`=VCC). No wiring
auto-detection is needed; the pins never move.
> **GND first.** Plug GND first and verify it manually (continuity meter
> or known-good contact) — a missing or loose ground masquerades as every
> other fault at once: floating lines, phantom start bits, all-zero frames.
### Pin mapping
The FX2 clone channels are assigned via `-P iso7816:clk=N:data=N:rst=N:vcc=N`.
The recommended short-cable tap (external pull resistors) uses fixed pins that
are exactly `start.sh`'s defaults; `--clk`/`--data`/`--rst`/`--vcc` remap them
if you wire differently:
| FX2 channel | SIM contact | Signal |
|-------------|-------------|--------|
| D0 | C7 | I/O |
| D2 | C1 | VCC (digital level only!) |
| D4 | C2 | RST |
| D5 | C3 | CLK |
| GND | C5 | GND |
FX2 input threshold is TTL-ish (~1.4V): 1.8V-class cards may read unreliably;
3V/5V classes are fine.
### Clock modes
- `native` (default) — live captures. The decoder follows the PPS speed
switch and re-arms on RST, so warm resets and post-PPS traffic decode
correctly.
- `detect` — for offline experiments or captures without PPS. It does not
follow the PPS switch, so post-PPS traffic can be misread.
- `sample_as_clock` — experimental upstream mode; not recommended for SIM
captures.
### Troubleshooting live capture
**The capture stops early (especially on Windows).** A common cause is the
wrong USB driver. The Saleae Logic driver works only with Saleae Logic
software; sigrok needs the **WinUSB** driver. Install it with **Zadig**
(bundled with the sigrok-cli installer) and repeat the assignment after the
device re-enumerates with the firmware's VID/PID. See the sigrok documentation:
- https://sigrok.org/wiki/Windows#Drivers
- https://sigrok.org/wiki/Fx2lafw
**Device not found / no signal.** Check the WinUSB driver (Windows), the
fx2lafw firmware, the wiring and GND (see Wiring), and try another USB port or
a known-good cable. Cheap USB cables and hubs are common causes of stalls.
**The capture ends by itself (`rc=0`).** The FX2 is at its USB bandwidth limit
at high samplerates. Lower `--samplerate`, avoid hubs, and close other USB
traffic. `start.sh` automatically restarts the capture on `rc=0` (default 20
restarts, 2 s apart; `--no-loop`, `--max-restarts=N`, `--restart-delay=S`).
With `--pcap=FILE`, each restart writes `FILE.<N>.<ext>`.
`start.sh` runs until Ctrl+C; keystrokes do not stop it (the "press any key"
prompt is disabled). Useful options:
```bash
./start.sh --pcap=s.pcap --log=s.log # record events and the rc= verdict
./start.sh ... --samplerate=24M # more timing headroom if needed
./start.sh ... --klog # also record the kernel journal
./start.sh ... --debug # full decoder + sigrok output
```
- `--log` records the session-end `rc=` line.
- The decoder logs `SIGNAL INTEGRITY WARNING` when ≥ 8 of the last 64 frames
fail parity.
- Desynced packets are kept and flagged `GSMTAP_FLAG_BAD_FCS` in the GSMTAP
header `res` byte — visible in Wireshark as a BAD-FCS warning.
### Raw sigrok-cli
Equivalent commands without the wrapper scripts:
```bash
# Minimal: CLK+I/O only, live stream to localhost:4729
sigrok-cli -d fx2lafw --config samplerate=12M --continuous \
-P iso7816:clk=D0:data=D1:clock_option=detect -A iso7816
# Full wiring: CLK + I/O + RST + VCC with line event tracking
sigrok-cli -d fx2lafw --config samplerate=12M --continuous \
-P iso7816:clk=D5:data=D0:rst=D4:vcc=D2:clock_option=native:rst_detect=true:vcc_detect=true \
-A iso7816
# Stream to a remote analyser / disable streaming / write PCAP file
... -P iso7816:...:gsmtap_host=10.0.28.7 ...
... -P iso7816:...:gsmtap_enable=false ...
... -P iso7816:...:pcap_file=trace.pcap ...
# Classic upstream mode: binary PCAP to stdout
sigrok-cli -i capture.sr -P iso7816:clk=2:data=0 -B iso7816=pcap > out.pcap
```
## The tap in practice ## The tap in practice
![Components](resources/components.jpg) ![Components](resources/components.jpg)
@@ -45,23 +293,23 @@ this decoder's `pcap_file=<path>` option).
![Short cable pull resistors](resources/short_cable_pull_resistors.jpg) ![Short cable pull resistors](resources/short_cable_pull_resistors.jpg)
*Short cable with external pull resistors — 10 kΩ to GND on VCC (pulls low when off), 47 kΩ to VCC on DATA (faster rise to high)* *Short cable with external pull resistors — 10 kΩ to GND on VCC (pulls low when off), 47 kΩ to VCC on DATA (faster rise to high)*
## What was added on top of upstream ## Features
| Feature | Description | | Feature | Description |
|---------|-------------| |---------|-------------|
| Live GSMTAP stream | Every decoded event is sent as a GSMTAP-SIM UDP packet (default on, mimics simtrace2-sniff) | | Live GSMTAP stream | Every decoded event is sent as a GSMTAP-SIM UDP packet (default on, mimics simtrace2-sniff) |
| Correct sub_types | ATR=0x01 and PPS=0x02 now tagged properly in PCAP output (upstream hardcoded everything to APDU=0x00) | | Correct sub_types | ATR=0x01 and PPS=0x02 are tagged properly in PCAP output |
| ATR/PPS in PCAP | ATR and combined PPS request+response are emitted as PCAP packets | | ATR/PPS in PCAP | ATR and combined PPS request+response are emitted as PCAP packets |
| RST tracking (optional) | `rst_detect=true`: emits reset assert/deassert events (sub_type 0x10) | | RST tracking (optional) | `rst_detect=true`: emits reset assert/deassert events (sub_type 0x10) |
| VCC tracking (optional) | `vcc_detect=true`: emits power on/off events (sub_type 0x11) | | VCC tracking (optional) | `vcc_detect=true`: emits power on/off events (sub_type 0x11) |
| Direct PCAP file | `pcap_file=<path>` writes PCAP without shell redirection | | Direct PCAP file | `pcap_file=<path>` writes PCAP without shell redirection |
| Start-bit deglitch | Deglitch in the start-bit detector (2 samples at 16 MHz, scaled from the sample rate since v1.9.7) eliminates sub-ETU LOW glitches from FX2LP pull-up artifacts, preventing byte misalignment on fast phone traces | | Start-bit deglitch | Suppresses sub-ETU LOW glitches (2 samples at 16 MHz, scaled to the samplerate) |
| Mid-session ETU lock | The DATA-edge ETU estimator rejects guard-only (all-zero) and single-spacing bursts and invalidates a rate that fails parity, so a capture at a non-default F/D locks safely | | Mid-session ETU lock | Recovers the ETU from DATA for captures without a usable CLK; a rate that fails parity is re-measured |
| ATR / resync guards | A DATA-state `0x3B`/`0x3F` is an ATR candidate only before the first APDU; parity-dirty or bare (TS+T0) frames are ignored, and `resync_idle` really waits for the idle level | | ATR / resync guards | Validates the ATR, ignores mis-framed ATR candidates, and re-aligns after a desync |
| Inverse convention | TS=0x3F ATRs follow ISO 7816-3 7.1: inverted data, msb first, start bit still LOW from an idle-HIGH line | | Inverse convention | Supports direct (TS=0x3B) and inverse (TS=0x3F) cards |
| T=1 blocks | NAD/PCB/LEN/INF/LRC decode with M-bit chaining; the I-block INF is emitted as the APDU, R/S blocks are not; a truncated capture ends cleanly | | T=1 blocks | Decodes NAD/PCB/LEN/INF/LRC with M-bit chaining; the I-block INF is emitted as the APDU |
| Parity flag | A packet containing a parity-error byte is emitted with the GSMTAP BAD_FCS flag (not just an annotation) | | Parity flag | Packets containing a parity-error byte are flagged `GSMTAP_FLAG_BAD_FCS` |
| Rate-aware thresholds | Start-bit deglitch, guard floors and the ETU glitch floor scale from the capture sample rate instead of assuming 16 MHz | | Rate-aware thresholds | Deglitch, guard and ETU floors scale with the capture samplerate |
## Decoder options ## Decoder options
@@ -115,344 +363,6 @@ This carriage is this decoder's own extension (upstream simtrace2-sniff
never sets `res`); the flag semantics mirror simtrace2's per-message USB never sets `res`); the flag semantics mirror simtrace2's per-message USB
data flags and are not part of the libosmocore spec. data flags and are not part of the libosmocore spec.
## Usage
Quick start (after installing — release download or source checkout; see
Installation below):
```bash
./setup.sh # check sigrok-cli, register decoder symlink
./start.sh # capture + GSMTAP stream to 127.0.0.1:4729
```
On Windows the same two steps are `setup.bat` then `start.bat` (see
Installation below).
`start.sh` defaults: pins D5=CLK, D0=I/O, D4=RST, D2=VCC, 16 MHz samplerate.
Override via args:
```bash
./start.sh --clk=D1 --data=D6 # different wiring
./start.sh --no-rst --no-vcc # CLK+I/O only
./start.sh --host=10.0.28.7 # stream to a remote analyser
./start.sh --pcap=session.pcap # also record decoded events to PCAP
./start.sh --debug # full decoder + sigrok output (all
# annotation rows + libsigrok -l 4);
# by default only decoded APDUs and
# decoder warnings/errors are shown
```
### Wiring
The recommended tap is the short cable with external pull resistors (see
the photos above): 10 kΩ to GND on VCC (pulls low when off) and 47 kΩ to
VCC on DATA (faster rise to high). Its pin mapping is **fixed and known
in advance** — see the "Pin mapping" table below — and is exactly what
`start.sh` defaults to (`D5`=CLK, `D0`=I/O, `D4`=RST, `D2`=VCC). No
wiring auto-detection is needed; the pins never move.
> **GND first.** Plug GND first and verify it manually (continuity meter
> or known-good contact) — a missing or loose ground masquerades as every
> other fault at once: floating lines, phantom start bits, all-zero frames.
### Robustness against noisy signals
Live captures can glitch (a phantom start bit during power-up used to
shift the whole ATR parse off-by-one). The decoder now:
- validates the ATR's TS byte (`0x3B`/`0x3F` per TS 102 221 §5.2.2) and
resyncs on the next real falling edge if it is bogus;
- never lets a decode exception kill the capture — errors are logged,
annotated, and the state machine resyncs (end-of-stream still exits
cleanly);
- decodes T=1 blocks (NAD/PCB/LEN/INF/LRC) and bounds the M-bit chain so garbage
cannot loop forever.
After an accepted PPS the decoder **follows the speed switch**: in
native CLK mode `clock_skip` becomes F/D CLK cycles per bit (e.g.
512/16 = 32), matching both sides' new UART rate. Live capture
confirmed that keeping 372 after PPS aliases all subsequent traffic.
A **warm reset** (the reader re-asserts RST every ~1.6 s) makes the card
answer with a fresh ATR at the default 372 cycles/bit. The decoder
**re-arms the ATR hunt on RST deassert**: state back to `FIND START`,
native skip reset to 372, hunt count cleared — so the re-ATR parses as
an ATR instead of being mis-read as TPDU traffic at the PPS-negotiated
rate. A **half-ETU start-bit guard** (edge reader) additionally rejects the phantom
`0x00` an idle glitch can insert before that ATR. Requires
`rst_detect=true` (the `rst` channel assigned); without it a mid-session
reset is still mis-read.
### Troubleshooting live capture
`start.sh` runs a single `--continuous` capture until you press **Ctrl+C**
(`rc=130`). stdin is detached from sigrok-cli, so pressing keys/Enter in
the terminal does **not** stop it (sigrok's "press any key to stop
acquisition" prompt is disabled) — that keypress was previously
mis-read as a "premature abort", but there was never a device fault.
Most of the early "noise" seen in captures (parity errors, mis-framed
garbage, a bouncing VCC line) was a badly-decoded state machine, not the
hardware: re-seating the tap did nothing, while the decoder rewrite fixed
it completely (warm-reset re-arm, half-ETU start-bit guard, 10 ms VCC
debounce, T=0 exchange reassembly). A clean capture now decodes to zero
garbage — see the `vs_reader.py` validation below.
If a capture *does* end on its own (`rc=0`), the device genuinely stopped
streaming; the FX2's USB bandwidth ceiling at sustained high sample rates
is the usual suspect.
```bash
./start.sh --pcap=s.pcap --log=s.log # also record decoded events, log rc=
./start.sh ... --samplerate=24M # more timing headroom if needed
./start.sh ... --klog # also record kernel journal
./start.sh ... --debug # full output: all annotation rows
# + libsigrok internals at -l 4
# (default: APDUs + warnings only)
```
`start.sh` captures a continuous stream at the configured rate (default 16
MHz) until Ctrl+C (`rc=130`). A healthy capture never ends by itself; if the
FX2 drops the USB transfer mid-session (a flaky device, `rc=0` "device
stopped streaming"), the capture auto-restarts so the session is not lost —
it re-launches on every `rc=0` until you press Ctrl+C or hit
`--max-restarts=N` (default 20; `0` = unlimited), with a `--restart-delay=S`
gap (default 2 s). When restarting with `--pcap=FILE`, each session's capture
is written to `FILE.<N>.<ext>` so a restart never overwrites the previous one,
and the repetitive `sr_session_stop: session was NULL` teardown line is
filtered from stderr.
- `--no-loop` disables auto-restart (single capture only).
- `--loop` forces auto-restart on (this is the default).
- `--max-restarts=N` caps restarts (default 20; `0` = unlimited).
- `--restart-delay=S` seconds to wait between restarts (default 2).
- `--log` captures the `rc=` verdict line for the session end.
- The decoder logs `SIGNAL INTEGRITY WARNING` when >= 8 of the last
64 frames fail parity.
- Desynced TPDUs (mis-framed exchanges) are kept but flagged with
`GSMTAP_FLAG_BAD_FCS` in the GSMTAP header `res` byte — visible in
Wireshark as a BAD-FCS warning.
- A T=0 header with a structurally invalid INS (ISO 7816-4 §5.1.2:
`0x00` or `0x6x`/`0x9x`) is almost always a one-byte shift from
a stray leading byte (e.g. a leftover SW2 read after a PACKETEND).
Instead of silently dropping the whole 5-byte window (which let the next
byte become a bogus CLA and swallow the remaining dialog into one CONCAT
packet), the decoder drops only the leading byte and re-frames the rest,
recovering the real command. Every consumed-but-unemitted byte is
explicitly logged (`discarded byte 0x…: reason`); idle 0x00/0xFF discards
are rate-limited, non-idle discards always produce a decoder annotation.
- A card may finish a command with SW1 SW2 at the first procedure byte
(ISO 7816-3 §10.3.3), including a case-2 command with P3 > 0: the SW is
framed as the status word, not read as command data. A response
**shorter than Le** is split at the status word and the packet is
flagged `BAD_FCS` (the following exchanges stay intact), and `P3=0`
(Le=256) response data is kept.
Performance: in native CLK mode the decoder calibrates samples per CLK
edge once from the ATR's first frame, then advances bit timing with
single sample-skip waits instead of one wait per CLK edge. The PPS speed
switch is followed via `clock_skip = F/D`; there is no post-PPS or
parity-triggered recalibration.
### Mode comparison on FX2 hardware (A/B result)
- `native` decoded real traffic (ATR, PPS switch, 100+ valid APDUs in a
12 s window); the one persistent artifact was the VCC sense line
"bouncing" — the ~1 kHz ringing the 10 ms debounce now suppresses.
- `detect` never produced a usable session on this rig: it missed the
PPS speed switch entirely (no PPS handling fired), aliasing all
post-PPS traffic; a second attempt caught a dead I/O line.
`native` stays the default. Use `--clock=detect` only for offline
experiments without PPS. A run full of all-zero frames means the tap
lost contact with a line.
Parity is **even** per TS 102 221 ("an even number of bits set to '1'
including the parity bit"); frames failing the check are flagged as
`CHKSUM ERROR` but still decoded.
Equivalent raw sigrok-cli commands:
```bash
# Minimal: CLK+I/O only, live stream to localhost:4729
sigrok-cli -d fx2lafw --config samplerate=12M --continuous \
-P iso7816:clk=D0:data=D1:clock_option=detect -A iso7816
# Full wiring: CLK + I/O + RST + VCC with line event tracking
sigrok-cli -d fx2lafw --config samplerate=12M --continuous \
-P iso7816:clk=D5:data=D0:rst=D4:vcc=D2:clock_option=native:rst_detect=true:vcc_detect=true \
-A iso7816
# Stream to a remote analyser / disable streaming / write PCAP file
... -P iso7816:...:gsmtap_host=10.0.28.7 ...
... -P iso7816:...:gsmtap_enable=false ...
... -P iso7816:...:pcap_file=trace.pcap ...
# Classic upstream mode: binary PCAP to stdout
sigrok-cli -i capture.sr -P iso7816:clk=2:data=0 -B iso7816=pcap > out.pcap
```
### Pin mapping
The FX2 clone channels are assigned via `-P iso7816:clk=N:data=N:rst=N:vcc=N`.
The recommended short-cable tap (external pull resistors) uses fixed pins that
are exactly `start.sh`'s defaults; `--clk`/`--data`/`--rst`/`--vcc` remap them
if you wire differently:
| FX2 channel | SIM contact | Signal |
|-------------|-------------|--------|
| D0 | C7 | I/O |
| D2 | C1 | VCC (digital level only!) |
| D4 | C2 | RST |
| D5 | C3 | CLK |
| GND | C5 | GND |
FX2 input threshold is TTL-ish (~1.4V): 1.8V-class cards may read unreliably;
3V/5V classes are fine.
**Samplerate and 8-bit mode (important):** the FX2's nominal 24 MHz is only
available when sampling in 8-bit mode, i.e. when **only channels D0–D7 are
enabled**. Enabling the 9th channel (A0/analog on CWAV AX clones) or any
analog input forces 16-bit collection, which libsigrok caps at 12 MHz.
`start.sh`/`start.bat` therefore pass `-C D0,D1,D2,D3,D4,D5,D6,D7`
explicitly and default to **16 MHz** (comfortably under the 24 MHz USB
bandwidth ceiling; ~3.3 samples per 4.8 MHz clock cycle). `setup.sh`/
`setup.bat` probe and report your hardware's actual maximum under the
same restriction.
## Installation
Both ways install the same decoder — pick one:
- **Download (recommended)** — a release archive. Nothing to clone and no git
history: extract it, run `setup`, run `start`. Best if you only want to
capture.
- **Source checkout** — a `git clone`. The same runtime plus the development
material: `tests/` and the trace/baseline tools (`tools/capture_baseline.sh`,
`tools/compare_baseline.sh`, `tools/vs_reader.py`). The example traces
(`examples/`) are gitignored and stay local in either case. The release
archives intentionally do not contain `tests/`, the dev tools or
`examples/`.
### Download (recommended)
Grab the latest archive from
[Releases](https://github.com/anttro/sigrok_iso7816_stream/releases/latest):
- `sigrok_iso7816_stream-<version>.tar.gz` — Linux
- `sigrok_iso7816_stream-<version>.zip` — Windows
Each release also publishes `SHA256SUMS`, which lists **both** archives; keep
it next to the file you downloaded and verify:
```bash
sha256sum -c --ignore-missing SHA256SUMS # GNU coreutils (Linux)
```
On Windows run `certutil -hashfile sigrok_iso7816_stream-<version>.zip SHA256`
and compare the output with the `.zip` line in `SHA256SUMS`.
#### Linux (download)
```bash
tar xzf sigrok_iso7816_stream-<version>.tar.gz
cd sigrok_iso7816_stream-<version>
./setup.sh
./start.sh
```
`setup.sh` verifies sigrok-cli and the FX2 firmware package
(`sigrok-firmware-fx2lafw`) are installed, symlinks the project directory into
`~/.local/share/libsigrokdecode/decoders/iso7816` (user-local decoders shadow
system-wide ones), and probes the connected device for its maximum supported
samplerate.
#### Windows (download)
Prerequisites:
1. **sigrok-cli** Windows installer (0.7.2 x86_64) from
[sigrok.org/wiki/Downloads](https://sigrok.org/wiki/Downloads) — the tested
release. Nightly Windows installers are also published on that page; they
may change the sigrok-cli syntax or the decoder API, so the 0.7.2
release installer remains the supported version.
If sigrok-cli fails to start with error `0xc0150002`, install the
[Visual C++ 2010 Redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=26999)
(`msvcr100.dll` is required by the bundled Python runtime).
2. fx2lafw firmware ships bundled with the installer — no separate download.
Driver setup (FX2 dongles need WinUSB, the vendor driver won't work):
- Run **Zadig**, which ships *inside* the sigrok-cli installation directory
(also reachable from the Start menu). Select the FX2 device in its dropdown
and install the **WinUSB** driver.
- After firmware upload the device re-enumerates with a different VID/PID —
if it still isn't found, run Zadig a **second time** for the re-enumerated
entry.
- Windows binds drivers per USB port when no serial number is present:
moving the dongle to another port may require repeating Zadig.
Then extract the release `.zip` (right-click → Extract All in Explorer) and
run, inside the extracted folder:
```bat
setup.bat
start.bat
```
`setup.bat` verifies sigrok-cli and bundled firmware, registers this project's
decoder via a junction into `%LOCALAPPDATA%\libsigrokdecode\decoders\iso7816`
(confirmed by `sigrok-cli -L` listing `iso7816`), and probes the device's
accepted samplerates. The release zip ships the batch files with CRLF line
endings, so no conversion is needed. `start.bat --help` lists its options
(the core subset of `start.sh`: channels, samplerate, clock, host/port, pcap,
protocol, debug).
### Linux (source checkout)
```bash
git clone git@github.com:anttro/sigrok_iso7816_stream.git
cd sigrok_iso7816_stream
./setup.sh
```
A fresh clone needs the same `./setup.sh` checks and symlink as above: it
verifies sigrok-cli and the FX2 firmware package, symlinks the project
directory into `~/.local/share/libsigrokdecode/decoders/iso7816` and probes
the device's maximum samplerate.
### Windows (source checkout)
The Windows prerequisites (sigrok-cli + the Visual C++ 2010 Redistributable,
the bundled fx2lafw firmware, and the Zadig/WinUSB driver setup) are the same
as in [Windows (download)](#windows-download) above.
```bat
git clone git@github.com:anttro/sigrok_iso7816_stream.git
cd sigrok_iso7816_stream
setup.bat
```
`setup.bat` performs the same checks and junction registration as above.
`start.bat` supports the core option subset (channels, samplerate, clock,
host/port, pcap, protocol, debug; `start.sh` has the full set) — the space
form is the primary one, and `--clk=CH` also works:
```bat
start.bat --clk D1 --data D6
start.bat --help
```
Capture works the same as on Linux:
```bat
start.bat rem capture + GSMTAP stream
```
Note: batch files need CRLF line endings; the repo enforces this via
`.gitattributes`, so a fresh clone on Windows is already correct (the release
zip ships the same CRLF files).
## RST/VCC detection notes and limitations ## RST/VCC detection notes and limitations
- Events are detected **asynchronously before the first ATR** (power-on / - Events are detected **asynchronously before the first ATR** (power-on /
@@ -463,13 +373,9 @@ zip ships the same CRLF files).
- VCC is digital-only: the decoder sees powered/not-powered, never the - VCC is digital-only: the decoder sees powered/not-powered, never the
voltage class (1.8/3/5V). voltage class (1.8/3/5V).
- **RST and VCC use level-stability hysteresis at 10 ms** (samplerate-scaled): - **RST and VCC use level-stability hysteresis at 10 ms** (samplerate-scaled):
a new level is reported only once it has been continuously stable for ≥ 10 ms a new level is reported only once it has been continuously stable for ≥ 10 ms.
— either because it persists that long, or because it ends after being stable This makes power-up and power-down symmetric and suppresses ringing and
that long. This makes power-up and power-down *symmetric*: a VCC sense line short glitches.
that **rings on the rising edge** (noisy/floating tap) no longer loses its
"VCC on" event — it fires once the line settles HIGH, instead of being eaten
by edge debounce. RST uses the same scheme, so a brief RST glitch no longer
triggers a phantom warm-reset re-arm.
- **VCC events are generally unreliable — prefer not to track VCC.** A floating - **VCC events are generally unreliable — prefer not to track VCC.** A floating
or unconnected VCC sense pin reads HIGH at all times (logic-high with no load), or unconnected VCC sense pin reads HIGH at all times (logic-high with no load),
so the decoder sees "powered" constantly and emits spurious power events on so the decoder sees "powered" constantly and emits spurious power events on
@@ -480,23 +386,14 @@ zip ships the same CRLF files).
- Unassigned optional channels are ignored even if `rst_detect`/`vcc_detect` - Unassigned optional channels are ignored even if `rst_detect`/`vcc_detect`
is enabled (guarded via `has_channel()`). is enabled (guarded via `has_channel()`).
## Testing ## Development and testing
Verified against the upstream example captures: The decoder is validated against example captures with `tools/vs_reader.py`.
Trace fixtures are kept locally and are not part of the repository.
```bash
# ATR+PPS+54 APDUs from the test_8 reader capture (~19s decode)
# GSMTAP stream verified with tshark (ATR/APDU dissected natively),
# custom 0x10/0x11 events verified with a UDP listener, and end-to-end
# into the SIMtrace Analyser server (POST /api/capture/start → decode → stop).
```
A synthetic VCD generator covering RST/VCC edge cases lives in the project
notes (`projects/SIGROK_ISO7816.md` in the parent workspace).
### Validation against the reader SDK (`tools/vs_reader.py`) ### Validation against the reader SDK (`tools/vs_reader.py`)
On a controlled rig (PCSC reader driven by software) the reference APDU log On a controlled rig (PC/SC reader driven by software) the reference APDU log
from the reader SDK can be diffed against the decoded PCAP: from the reader SDK can be diffed against the decoded PCAP:
```bash ```bash
@@ -509,32 +406,12 @@ python3 tools/vs_reader.py <reader-log>.log out.pcap
`vs_reader.py` aligns each reader-log exchange to the capture APDUs `vs_reader.py` aligns each reader-log exchange to the capture APDUs
(byte-exact LCS match) and classifies the leftovers as proactive/CAT (byte-exact LCS match) and classifies the leftovers as proactive/CAT
(unseen by the reader SDK), pre-capture/dropped, or garbage. (unseen by the reader SDK), pre-capture/dropped, or garbage.
The mid-session capture whose warm resets previously produced 4 garbage
events — with the re-arm + start-bit guard it decodes to **0 garbage**
(`RESULT: OK - capture fully explained`).
test_7 (4 ATR resets fragmenting the session) now captures all 37/37 reader
exchanges (up from 10/37 before the deglitch fix). Samsung phone traces with
16 CLK/ETU (F=512/D=32) now de-concatenate to 924 individual T=0 exchanges
(previously merged into 52 oversized APDUs).
Replayable trace fixtures (kept locally, outside the repo) cover
controlled-rig reader sessions (with their reader-SDK ground-truth logs),
phone captures with gated CLK, and **cold-boot captures** that start
*before* power-up (VCC/RST low at t=0). The four Samsung fixtures are
cold boots taken with a new short cable (30 mm wires, external pull
resistors GND→VCC and VCC→DATA), named channels `DATA/VCC/RST/CLK` on bits
0/2/4/5; the `sim2` variants are cropped to the power-on window.
### Cold-boot captures (capture starts before power-up) ### Cold-boot captures (capture starts before power-up)
When the capture starts pre-power-up, the decoder must arm the ATR When the capture starts before power-up, RST is still low at sample 0. Use
hunt because RST is still low at sample 0: it primes the initial `rst_detect=true` and `protocol=T=0`; the decoder arms the ATR hunt on the
VCC/RST levels on the first step (instead of defaulting them to deasserted), initial RST level and decodes the full ATR. Example:
and on an RST-low-at-start it enters `FIND START` with a cleared ETU, so the
pre-ATR power-up DATA transitions cannot lock a bogus bit rate. It then
decodes the full ATR (`3b9f96801fc78031e073fe2117574a3382033339001e`) with
0 garbage:
```bash ```bash
sigrok-cli -i <coldboot>.sr \ sigrok-cli -i <coldboot>.sr \
@@ -542,48 +419,16 @@ sigrok-cli -i <coldboot>.sr \
-A iso7816 -A iso7816
``` ```
An RST deassert that lands while an ATR parse is already in progress no longer
re-arms the hunt mid-read — it logs `RST deasserted (hunt/ATR already in
progress)` and leaves the in-flight ATR alone (test_8/test_7 CHKSUM 18→0).
### Capture scenarios: reader (constant CLK) and phone (Clock Stop Mode) ### Capture scenarios: reader (constant CLK) and phone (Clock Stop Mode)
The decoder handles the two physically different SIM sniffing setups:
- **Reader / constant-CLK capture** — the reader drives a steady CLK for the - **Reader / constant-CLK capture** — the reader drives a steady CLK for the
whole session. In mid-session mode the capture whole session. Validate it against the reader SDK with
decodes to **0 garbage** (`RESULT: OK`) against the reader-SDK `tools/vs_reader.py <reader-log>.log out.pcap`.
ground truth (`tools/vs_reader.py <reader-log>.log out.pcap`). - **Phone / gated or stopped-CLK capture** — the phone gates or stops CLK
Warm-reset reader captures use the synthetic-T=0-ATR fallback. between transfers (Clock Stop Mode), so the ETU cannot be derived from CLK.
Run with `protocol=T=0`; the decoder recovers the ETU from the DATA line and
- **Phone / stopped-CLK capture** — the phone gates or stops CLK between decodes with the edge-list reader. T=0 case 3/4 commands (e.g. `80 12`/`80 14`
transfers (Clock Stop Mode), so the ETU is not the 372-clock default and STK envelopes) are consolidated into one command→response APDU.
cannot be inferred from CLK. Run with `protocol=T=0`; the decoder recovers the ETU from the DATA line via edge
counting, locks it, and decodes with the drift-immune edge-list bit reader.
T=0 case 3/4 commands (e.g. `80 12`/`80 14` STK envelope) are consolidated
into a single command→response APDU. A 2-sample start-bit deglitch eliminates
sub-ETU LOW glitches caused by FX2LP internal pull-up artifacts, preventing
byte misalignment on fast phone traces.
### Proven data rates and ETUs
All traces decoded at **16 MHz sample rate**, 0 garbage, RESULT: OK.
Since v1.5.0 every example trace also reports **0 CONCAT** (the invalid-INS
re-frame eliminated the last multi-exchange swallow family on
4gmodem/A55_sim2/S21p_sim2).
| Trace | CLK mode | ETU (samples) | CLK/ETU | Convention | Notes |
|-------|----------|---------------|---------|------------|-------|
| test_8 | constant | ~43 | 372 (standard) | Direct | PC/SC reader, ATR+PPS+APDUs |
| test_7 | constant | ~43 | 372 (standard) | Direct | PC/SC reader, warm resets |
| xiaomi | gated/stopped | ~53 | recovered from DATA | Direct | Phone, mid-session |
| samsung | gated/stopped | ~72 | 16 (F=512/D=32) | Direct | Phone, non-standard F/D, STK menu |
| alcor_reader | constant | ~53 | 16 (F=512/D=32) | Direct | PC/SC reader, CLK 4.0 MHz at ATR -> 4.8 MHz after PPS |
The decoder auto-detects the ETU from the trace and selects the appropriate
bit reader (CLK-sync for constant CLK, edge-list for gated/stopped CLK).
No manual configuration is needed beyond `clock_option=native` and
`protocol=T=0` for phone captures.
Recommended invocations: Recommended invocations:
@@ -600,6 +445,26 @@ sigrok-cli -i <phone>.sr \
-A iso7816 -A iso7816
``` ```
### Data rates and ETUs
Reference values observed on the example captures at a 16 MHz samplerate:
| Trace | CLK mode | ETU (samples) | CLK/ETU | Convention | Notes |
|-------|----------|---------------|---------|------------|-------|
| test_8 | constant | ~43 | 372 (standard) | Direct | PC/SC reader, ATR+PPS+APDUs |
| test_7 | constant | ~43 | 372 (standard) | Direct | PC/SC reader, warm resets |
| xiaomi | gated/stopped | ~53 | recovered from DATA | Direct | Phone, mid-session |
| samsung | gated/stopped | ~72 | 16 (F=512/D=32) | Direct | Phone, non-standard F/D, STK menu |
| alcor_reader | constant | ~53 | 16 (F=512/D=32) | Direct | PC/SC reader, CLK 4.0 MHz at ATR -> 4.8 MHz after PPS |
The decoder auto-detects the ETU and selects the bit reader (CLK-sync for
constant CLK, edge-list for gated/stopped CLK). No manual configuration is
needed beyond `clock_option=native` and `protocol=T=0` for phone captures.
Parity is **even** per TS 102 221 ("an even number of bits set to '1'
including the parity bit"); frames failing the check are flagged as
`CHKSUM ERROR` but still decoded.
## License ## License
GPL-2.0+, same as upstream. GPL-2.0+, same as upstream.
+307 -446
View File
@@ -2,6 +2,8 @@
# sigrok_iso7816_stream # sigrok_iso7816_stream
📢 Новости и обновления проекта: [Сайт](https://atroshin.ru) · [Telegram-канал](https://t.me/youeyeseesee)
Форк [svenso/sigrok_iso7816](https://github.com/svenso/sigrok_iso7816) с Форк [svenso/sigrok_iso7816](https://github.com/svenso/sigrok_iso7816) с
**живым GSMTAP-UDP-стримингом**: дешёвый логический анализатор FX2 (клон **живым GSMTAP-UDP-стримингом**: дешёвый логический анализатор FX2 (клон
Saleae) ведёт себя как сниффер SIMtrace2: Saleae) ведёт себя как сниффер SIMtrace2:
@@ -19,6 +21,262 @@ SIM-карта ⇄ ридер (пассивный съём с контактов
GSMTAP pcap-файлы (включая PCAP, который этот декодер пишет через опцию GSMTAP pcap-файлы (включая PCAP, который этот декодер пишет через опцию
`pcap_file=<path>`). `pcap_file=<path>`).
## Установка и запуск
Оба способа ставят один и тот же декодер — выберите один:
- **Скачать (рекомендуется)** — архив релиза. Не нужно ничего клонировать и
нет истории git: распакуйте, запустите `setup`, затем `start`. Лучший
вариант, если нужен только съём.
- **Из исходников** — `git clone`. Тот же рантайм плюс материал для
разработки: `tests/` и инструменты трасс и базовой линии
(`tools/capture_baseline.sh`, `tools/compare_baseline.sh`,
`tools/vs_reader.py`). Трассы примеров (`examples/`) исключены из git и
остаются локальными. В архивах релиза нет `tests/`, dev-инструментов и
`examples/`.
### Скачать (рекомендуется)
Скачайте последний архив со страницы
[Releases](https://github.com/anttro/sigrok_iso7816_stream/releases/latest):
- `sigrok_iso7816_stream-<version>.tar.gz` — Linux
- `sigrok_iso7816_stream-<version>.zip` — Windows
К каждому релизу прилагается `SHA256SUMS` — в нём **оба** архива.
Положите файл рядом со скачанным архивом и проверьте:
```bash
sha256sum -c --ignore-missing SHA256SUMS # GNU coreutils (Linux)
```
В Windows выполните `certutil -hashfile sigrok_iso7816_stream-<version>.zip SHA256`
и сравните вывод со строкой `.zip` в `SHA256SUMS`.
#### Linux (скачать)
```bash
tar xzf sigrok_iso7816_stream-<version>.tar.gz
cd sigrok_iso7816_stream-<version>
./setup.sh
./start.sh
```
`setup.sh` проверяет, что установлены sigrok-cli и пакет прошивки FX2
(`sigrok-firmware-fx2lafw`), создаёт симлинк каталога проекта в
`~/.local/share/libsigrokdecode/decoders/iso7816` (пользовательские
декодеры перекрывают системные) и опрашивает подключённое устройство на
предмет максимальной поддерживаемой частоты дискретизации.
#### Windows (скачать)
Предварительные требования:
1. **sigrok-cli** — установщик для Windows (0.7.2 x86_64) с
[sigrok.org/wiki/Downloads](https://sigrok.org/wiki/Downloads) —
протестированная версия. На этой же странице публикуются ночные сборки
для Windows; они могут менять синтаксис sigrok-cli или API декодеров,
поэтому поддерживаемой остаётся версия из релизного установщика 0.7.2.
Если sigrok-cli не запускается с ошибкой `0xc0150002`, установите
[Visual C++ 2010 Redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=26999)
(`msvcr100.dll` требуется встроенному Python-рантайму).
2. Прошивка fx2lafw поставляется вместе с установщиком — отдельно скачивать не нужно.
Настройка драйвера (донглам FX2 нужен WinUSB, вендорский драйвер не подойдёт):
- Запустите **Zadig**, который лежит *внутри* каталога установки sigrok-cli
(также доступен из меню «Пуск»). Выберите устройство FX2 в выпадающем
списке и установите драйвер **WinUSB**.
- После загрузки прошивки устройство переподключается с другим VID/PID —
если оно всё ещё не находится, запустите Zadig **второй раз** для
переподключившегося устройства.
- Windows привязывает драйверы к USB-порту, когда нет серийного номера:
перенос донгла в другой порт может потребовать повторить Zadig.
Затем распакуйте архив `.zip` (в Проводнике: правой кнопкой → «Извлечь все»)
и запустите в распакованном каталоге:
```bat
setup.bat
start.bat
```
`setup.bat` проверяет sigrok-cli и встроенную прошивку, регистрирует декодер
этого проекта через junction в
`%LOCALAPPDATA%\libsigrokdecode\decoders\iso7816` (подтверждается тем, что
`sigrok-cli -L` показывает `iso7816`), и опрашивает устройство на предмет
поддерживаемых частот дискретизации. В zip-архиве релиза bat-файлы уже с
переводами строк CRLF, поэтому преобразование не требуется.
`start.bat --help` перечисляет его опции (основное подмножество `start.sh`:
каналы, частота дискретизации, clock, host/port, pcap, protocol, debug).
### Из исходников
#### Linux (из исходников)
```bash
git clone git@github.com:anttro/sigrok_iso7816_stream.git
cd sigrok_iso7816_stream
./setup.sh
./start.sh
```
`setup.sh` выполняет те же проверки и создаёт тот же симлинк, что и выше.
#### Windows (из исходников)
Предварительные требования Windows (sigrok-cli и Visual C++ 2010
Redistributable, встроенная прошивка fx2lafw и настройка драйвера
Zadig/WinUSB) — те же, что в разделе
[Windows (скачать)](#windows-скачать) выше.
```bat
git clone git@github.com:anttro/sigrok_iso7816_stream.git
cd sigrok_iso7816_stream
setup.bat
start.bat
```
`setup.bat` выполняет те же проверки и регистрацию junction, что и выше.
`start.bat` поддерживает основное подмножество опций; основной формат — с
пробелом, `--clk=CH` тоже работает (`start.bat --help` перечисляет опции):
```bat
start.bat --clk D1 --data D6
```
Примечание: bat-файлы требуют переводов строк CRLF; репозиторий следит за
этим через `.gitattributes`, поэтому свежий клон в Windows уже корректен
(zip-архив релиза содержит те же файлы с CRLF).
## Использование
`start.sh` пишет непрерывный поток на частоте 16 МГц до Ctrl+C (`rc=130`) и
стримит GSMTAP на 127.0.0.1:4729. Умолчания: выводы D5=CLK, D0=I/O,
D4=RST, D2=VCC. Переопределяются аргументами:
```bash
./start.sh --clk=D1 --data=D6 # другое подключение
./start.sh --no-rst --no-vcc # только CLK+I/O
./start.sh --host=10.0.28.7 # стримить на удалённый анализатор
./start.sh --pcap=session.pcap # также записать декодированные события в PCAP
./start.sh --debug # полный вывод декодера и sigrok (все
# строки аннотаций + libsigrok -l 4);
# по умолчанию показываются только
# декодированные APDU и предупреждения/ошибки
```
В Windows `start.bat` принимает то же основное подмножество опций (форма с
пробелом; форма `--opt=value` тоже работает) — см. заметки по установке
Windows выше.
### Подключение
Рекомендуемый способ съёма — короткий кабель с внешними подтягивающими
резисторами (см. раздел «Съём на практике» ниже): 10 кОм к GND на VCC
(тянет вниз без питания) и 47 кОм к VCC на DATA (быстрее фронт вверх).
Его распиновка **фиксирована и известна заранее** — см. таблицу
«Распиновка» ниже — и в точности совпадает с умолчаниями `start.sh`
(`D5`=CLK, `D0`=I/O, `D4`=RST, `D2`=VCC). Автодетект подключения не нужен;
выводы не меняются.
> **Сначала GND.** Сначала подключите GND и проверьте его вручную
> (мультиметром или заведомо исправным контактом) — отсутствующий или
> плохой контакт земли маскируется под все остальные неисправности сразу:
> плавающие линии, фантомные стартовые биты, кадры из одних нулей.
### Распиновка
Каналы клона FX2 назначаются через `-P iso7816:clk=N:data=N:rst=N:vcc=N`.
Рекомендуемый съём коротким кабелем (с внешними подтягивающими резисторами)
использует фиксированные выводы, которые в точности совпадают с умолчаниями
`start.sh`; `--clk`/`--data`/`--rst`/`--vcc` переназначают их, если вы
подключили иначе:
| Канал FX2 | Контакт SIM | Сигнал |
|-------------|-------------|--------|
| D0 | C7 | I/O |
| D2 | C1 | VCC (только цифровой уровень!) |
| D4 | C2 | RST |
| D5 | C3 | CLK |
| GND | C5 | GND |
Входной порог FX2 близок к TTL (~1.4 В): карты класса 1.8 В могут читаться
нестабильно; классы 3 В/5 В — нормально.
### Режимы CLK
- `native` (по умолчанию) — живые записи. Декодер отслеживает переключение
скорости по PPS и заново взводится по RST, поэтому тёплые сбросы и трафик
после PPS разбираются корректно.
- `detect` — для офлайн-экспериментов или записей без PPS. Он не отслеживает
переключение по PPS, поэтому трафик после PPS может читаться неверно.
- `sample_as_clock` — экспериментальный режим upstream; для съёма SIM не
рекомендуется.
### Решение проблем при живой записи
**Запись обрывается рано (особенно в Windows).** Частая причина —
неподходящий драйвер USB. Драйвер Saleae Logic работает только с Saleae
Logic software; sigrok нужен драйвер **WinUSB**. Установите его через
**Zadig** (входит в установщик sigrok-cli) и повторите назначение после
переподключения устройства с VID/PID прошивки. Подробности в документации
sigrok:
- https://sigrok.org/wiki/Windows#Drivers
- https://sigrok.org/wiki/Fx2lafw
**Устройство не найдено / нет сигнала.** Проверьте драйвер WinUSB (Windows),
прошивку fx2lafw, подключение и GND (см. «Подключение»), попробуйте другой
USB-порт и заведомо исправный кабель. Дешёвые USB-кабели и хабы — частая
причина остановок.
**Запись завершается сама (`rc=0`).** FX2 упирается в потолок пропускной
способности USB на высокой частоте дискретизации. Снизьте `--samplerate`,
избегайте хабов, закройте другой USB-трафик. `start.sh` автоматически
перезапускает запись при `rc=0` (по умолчанию 20 перезапусков с паузой 2 с;
`--no-loop`, `--max-restarts=N`, `--restart-delay=S`). При `--pcap=FILE`
каждый перезапуск пишет `FILE.<N>.<ext>`.
`start.sh` работает до Ctrl+C; нажатия клавиш его не останавливают
(приглашение «нажмите любую клавишу» отключено). Полезные опции:
```bash
./start.sh --pcap=s.pcap --log=s.log # записать события и вердикт rc=
./start.sh ... --samplerate=24M # больше запаса по таймингу при необходимости
./start.sh ... --klog # также записать журнал ядра
./start.sh ... --debug # полный вывод декодера и sigrok
```
- `--log` сохраняет строку вердикта `rc=` в конце сессии.
- Декодер пишет `SIGNAL INTEGRITY WARNING`, когда ≥ 8 из последних 64 кадров
не проходят проверку чётности.
- Десинхронизированные пакеты сохраняются с флагом `GSMTAP_FLAG_BAD_FCS` в
байте `res` заголовка GSMTAP — видно в Wireshark как предупреждение BAD-FCS.
### Сырые команды sigrok-cli
Эквивалентные команды без скриптов-обёрток:
```bash
# Минимум: только CLK+I/O, живой поток на localhost:4729
sigrok-cli -d fx2lafw --config samplerate=12M --continuous \
-P iso7816:clk=D0:data=D1:clock_option=detect -A iso7816
# Полное подключение: CLK + I/O + RST + VCC с отслеживанием событий линий
sigrok-cli -d fx2lafw --config samplerate=12M --continuous \
-P iso7816:clk=D5:data=D0:rst=D4:vcc=D2:clock_option=native:rst_detect=true:vcc_detect=true \
-A iso7816
# Поток на удалённый анализатор / отключить стриминг / писать PCAP-файл
... -P iso7816:...:gsmtap_host=10.0.28.7 ...
... -P iso7816:...:gsmtap_enable=false ...
... -P iso7816:...:pcap_file=trace.pcap ...
# Классический режим upstream: бинарный PCAP в stdout
sigrok-cli -i capture.sr -P iso7816:clk=2:data=0 -B iso7816=pcap > out.pcap
```
## Съём на практике ## Съём на практике
![Компоненты](resources/components.jpg) ![Компоненты](resources/components.jpg)
@@ -48,23 +306,23 @@ GSMTAP pcap-файлы (включая PCAP, который этот декод
![Подтягивающие резисторы](resources/short_cable_pull_resistors.jpg) ![Подтягивающие резисторы](resources/short_cable_pull_resistors.jpg)
*Короткий кабель с внешними подтягивающими резисторами — 10 кОм к GND на VCC (тянет вниз, когда питания нет), 47 кОм к VCC на DATA (быстрее фронт вверх)* *Короткий кабель с внешними подтягивающими резисторами — 10 кОм к GND на VCC (тянет вниз, когда питания нет), 47 кОм к VCC на DATA (быстрее фронт вверх)*
## Что добавлено поверх upstream ## Возможности
| Возможность | Описание | | Возможность | Описание |
|---------|-------------| |---------|-------------|
| Живой поток GSMTAP | Каждое декодированное событие отправляется как GSMTAP-SIM UDP-пакет (включено по умолчанию, повторяет поведение simtrace2-sniff) | | Живой поток GSMTAP | Каждое декодированное событие отправляется как GSMTAP-SIM UDP-пакет (включено по умолчанию, повторяет поведение simtrace2-sniff) |
| Правильные sub_types | ATR=0x01 и PPS=0x02 теперь корректно помечаются в PCAP (в upstream всё писалось как APDU=0x00) | | Правильные sub_types | ATR=0x01 и PPS=0x02 корректно помечаются в PCAP |
| ATR/PPS в PCAP | ATR и объединённые запрос+ответ PPS выводятся как PCAP-пакеты | | ATR/PPS в PCAP | ATR и объединённые запрос+ответ PPS выводятся как PCAP-пакеты |
| Отслеживание RST (опционально) | `rst_detect=true`: события assert/deassert сброса (sub_type 0x10) | | Отслеживание RST (опционально) | `rst_detect=true`: события assert/deassert сброса (sub_type 0x10) |
| Отслеживание VCC (опционально) | `vcc_detect=true`: события включения/выключения питания (sub_type 0x11) | | Отслеживание VCC (опционально) | `vcc_detect=true`: события включения/выключения питания (sub_type 0x11) |
| PCAP сразу в файл | `pcap_file=<path>` пишет PCAP без перенаправления вывода оболочки | | PCAP сразу в файл | `pcap_file=<path>` пишет PCAP без перенаправления вывода оболочки |
| Деглитч стартового бита | Деглитч в детекторе стартового бита (2 отсчёта при 16 МГц, с v1.9.7 масштабируется от частоты дискретизации) убирает LOW-глитчи короче ETU от артефактов подтяжки FX2LP и предотвращает смещение байтов на быстрых телефонных трассах | | Деглитч стартового бита | Подавляет LOW-глитчи короче ETU (2 отсчёта при 16 МГц, масштабируется от частоты дискретизации) |
| Захват ETU в середине сессии | Оценщик ETU по фронтам DATA отбрасывает пачки только со сторожевым интервалом (нулевые данные) и одиночные интервалы, а также сбрасывает скорость, не прошедшую проверку чётности, поэтому трасса с нестандартным F/D захватывается надёжно | | Захват ETU в середине сессии | Восстанавливает ETU по линии DATA, когда CLK непригоден; скорость, не прошедшая проверку чётности, измеряется заново |
| Защита ATR / ресинхронизации | `0x3B`/`0x3F` в состоянии DATA считается кандидатом в ATR только до первого APDU; кадры с ошибкой чётности или голый TS+T0 игнорируются, а `resync_idle` действительно ждёт уровень простоя | | Защита ATR / ресинхронизации | Проверяет ATR, игнорирует неверно кадрированные кандидаты и выравнивается после десинхронизации |
| Инверсная конвенция | ATR с TS=0x3F разбирается по ISO 7816-3 7.1: инверсные данные, msb первым, стартовый бит по-прежнему LOW при простое линии HIGH | | Инверсная конвенция | Поддерживает прямую (TS=0x3B) и инверсную (TS=0x3F) карты |
| Блоки T=1 | Разбор NAD/PCB/LEN/INF/LRC с цепочкой по биту M; INF I-блока выдаётся как APDU, R/S-блоки не выдаются; обрезанная запись завершается чисто | | Блоки T=1 | Разбирает NAD/PCB/LEN/INF/LRC с цепочкой по биту M; INF I-блока выдаётся как APDU |
| Флаг чётности | Пакет с байтом с ошибкой чётности выдаётся с флагом GSMTAP BAD_FCS (не только аннотацией) | | Флаг чётности | Пакеты с ошибкой чётности помечаются `GSMTAP_FLAG_BAD_FCS` |
| Пороги от частоты | Деглитч стартового бита, пороги защиты и порог глитча ETU масштабируются от частоты дискретизации, а не считаются от 16 МГц | | Пороги от частоты | Пороги деглитча, защиты и ETU масштабируются от частоты дискретизации |
## Опции декодера ## Опции декодера
@@ -119,354 +377,6 @@ uint32 в герцах (полезная нагрузка 7 байт). Пока
никогда не заполняет `res`); семантика флагов повторяет флаги данных (data никогда не заполняет `res`); семантика флагов повторяет флаги данных (data
flags) USB-протокола simtrace2 и не является частью спецификации libosmocore. flags) USB-протокола simtrace2 и не является частью спецификации libosmocore.
## Использование
Быстрый старт (после установки — скачанный архив или клон репозитория;
см. «Установка» ниже):
```bash
./setup.sh # проверить sigrok-cli, зарегистрировать симлинк декодера
./start.sh # запись + поток GSMTAP на 127.0.0.1:4729
```
В Windows те же два шага — `setup.bat`, затем `start.bat` (см. «Установка»
ниже).
Умолчания `start.sh`: выводы D5=CLK, D0=I/O, D4=RST, D2=VCC, частота
дискретизации 16 МГц. Переопределяются аргументами:
```bash
./start.sh --clk=D1 --data=D6 # другое подключение
./start.sh --no-rst --no-vcc # только CLK+I/O
./start.sh --host=10.0.28.7 # стримить на удалённый анализатор
./start.sh --pcap=session.pcap # также записать декодированные события в PCAP
./start.sh --debug # полный вывод декодера и sigrok (все
# строки аннотаций + libsigrok -l 4);
# по умолчанию показываются только
# декодированные APDU и предупреждения/ошибки
```
### Подключение
Рекомендуемый способ съёма — короткий кабель с внешними подтягивающими
резисторами (см. фото выше): 10 кОм к GND на VCC (тянет вниз без питания)
и 47 кОм к VCC на DATA (быстрее фронт вверх). Его распиновка **фиксирована
и известна заранее** — см. таблицу «Распиновка» ниже — и в точности
совпадает с умолчаниями `start.sh` (`D5`=CLK, `D0`=I/O, `D4`=RST,
`D2`=VCC). Автодетект подключения не нужен; выводы не меняются.
> **Сначала GND.** Сначала подключите GND и проверьте его вручную
> (мультиметром или заведомо исправным контактом) — отсутствующий или
> плохой контакт земли маскируется под все остальные неисправности сразу:
> плавающие линии, фантомные стартовые биты, кадры из одних нулей.
### Устойчивость к шумным сигналам
Живые записи могут глитчить (фантомный стартовый бит при включении питания
раньше сдвигал весь разбор ATR на единицу). Теперь декодер:
- проверяет байт TS в ATR (`0x3B`/`0x3F` по TS 102 221 §5.2.2) и
ресинхронизируется на следующем настоящем спаде, если он неверен;
- никогда не даёт исключению при декодировании убить запись — ошибки
логируются, аннотируются, а конечный автомат ресинхронизируется
(конец потока по-прежнему завершается чисто);
- разбирает блоки T=1 (NAD/PCB/LEN/INF/LRC) и ограничивает цепочку по биту M,
чтобы мусор не мог зациклиться навсегда.
После принятого PPS декодер **следует переключению скорости**: в режиме
native CLK `clock_skip` становится равным F/D тактов CLK на бит (например,
512/16 = 32), что соответствует новой скорости UART у обеих сторон. Живая
запись подтвердила, что сохранение 372 после PPS алиасит весь последующий
трафик.
**Тёплый сброс** (ридер заново подаёт RST примерно каждые ~1.6 с) заставляет
карту ответить свежим ATR на стандартных 372 тактах/бит. Декодер
**заново взводит охоту за ATR по deassert RST**: состояние возвращается в
`FIND START`, native-пропуск сбрасывается в 372, счётчик охоты очищается —
поэтому повторный ATR разбирается как ATR, а не ошибочно читается как
TPDU-трафик на скорости, согласованной PPS. **Защита стартового бита в
0.5 ETU** (edge-ридер) дополнительно отбрасывает фантомный `0x00`, который глитч на
холостом ходу может вставить перед этим ATR. Требуется `rst_detect=true`
(назначенный канал `rst`); без него сброс в середине сессии всё равно
будет прочитан неверно.
### Решение проблем при живой записи
`start.sh` запускает одну `--continuous` запись, пока вы не нажмёте
**Ctrl+C** (`rc=130`). stdin отвязан от sigrok-cli, поэтому нажатия
клавиш/Enter в терминале **не** останавливают запись (приглашение sigrok
«нажмите любую клавишу для остановки» отключено) — раньше это нажатие
ошибочно трактовалось как «преждевременный обрыв», хотя никакой
неисправности устройства не было.
Большая часть раннего «шума» в записях (ошибки чётности, мусор из-за
неверного кадрирования, дребезг линии VCC) была следствием плохо
декодированного конечного автомата, а не железа: переподключение съёма
ничего не давало, а переписанный декодер полностью это вылечил (re-arm по
тёплому сбросу, защита стартового бита 0.5 ETU, антидребезг VCC 10 мс,
сборка обмена T=0). Чистая запись теперь декодируется с нулём мусора —
см. проверку `vs_reader.py` ниже.
Если запись *всё-таки* завершается сама (`rc=0`), устройство действительно
перестало стримить; обычный подозреваемый — потолок пропускной способности
USB у FX2 при длительной высокой частоте дискретизации.
```bash
./start.sh --pcap=s.pcap --log=s.log # также записать события и лог rc=
./start.sh ... --samplerate=24M # больше запаса по таймингу при необходимости
./start.sh ... --klog # также записать журнал ядра
./start.sh ... --debug # полный вывод: все строки аннотаций
# + внутренности libsigrok на -l 4
# (по умолчанию: только APDU + предупреждения)
```
`start.sh` пишет непрерывный поток на настроенной частоте (по умолчанию
16 МГц) до Ctrl+C (`rc=130`). Здоровая запись никогда не завершается
сама; если FX2 роняет USB-передачу в середине сессии (нестабильное
устройство, `rc=0` «device stopped streaming»), запись автоматически
перезапускается, чтобы не потерять сессию — она перезапускается при каждом
`rc=0`, пока вы не нажмёте Ctrl+C или не сработает `--max-restarts=N`
(по умолчанию 20; `0` = без ограничения), с паузой `--restart-delay=S`
(по умолчанию 2 с). При перезапуске с `--pcap=FILE` запись каждой сессии
пишется в `FILE.<N>.<ext>`, поэтому перезапуск никогда не перезаписывает
предыдущую, а повторяющаяся строка завершения
`sr_session_stop: session was NULL` фильтруется из stderr.
- `--no-loop` отключает авто-перезапуск (только одна запись).
- `--loop` принудительно включает авто-перезапуск (это поведение по умолчанию).
- `--max-restarts=N` ограничивает число перезапусков (по умолчанию 20; `0` = без ограничения).
- `--restart-delay=S` — секунды ожидания между перезапусками (по умолчанию 2).
- `--log` сохраняет строку вердикта `rc=` для завершения сессии.
- Декодер пишет `SIGNAL INTEGRITY WARNING`, когда ≥ 8 из последних
64 кадров не проходят проверку чётности.
- Десинхронизированные TPDU (обмены с ошибкой кадрирования) сохраняются,
но помечаются `GSMTAP_FLAG_BAD_FCS` в байте `res` заголовка GSMTAP —
видно в Wireshark как предупреждение BAD-FCS.
- Заголовок T=0 со структурно некорректным INS (ISO 7816-4 §5.1.2:
`0x00` или `0x6x`/`0x9x`) почти всегда сдвинут на
один байт из-за лишнего ведущего байта (например, дочитанного остатка
SW2 после PACKETEND). Вместо молчаливого отбрасывания всего 5-байтового
окна (из-за чего следующий байт становился фиктивным CLA и проглатывал
остаток диалога в один CONCAT-пакет) декодер отбрасывает только ведущий
байт и перекадрирует остальные, восстанавливая настоящую команду.
Каждый потреблённый, но не выведенный байт явно логируется
(`discarded byte 0x…: reason`); отбрасывания холостых 0x00/0xFF
ограничены по частоте, отбрасывания не-холостых байтов всегда дают
аннотацию декодера.
- Карта может завершить команду словами SW1 SW2 на первом процедурном
байте (ISO 7816-3 §10.3.3), в том числе для case-2 команды с P3 > 0:
SW оформляется как статусное слово, а не читается как данные. Ответ
**короче Le** разделяется по статусному слову и пакет помечается
`BAD_FCS` (следующие обмены сохраняются); данные ответа при `P3=0`
(Le=256) сохраняются.
Производительность: в режиме native CLK декодер один раз калибрует число
отсчётов на фронт CLK по первому кадру ATR, а затем продвигает битовую
синхронизацию одиночными пропусками отсчётов вместо ожидания на каждый
фронт CLK. Переключение скорости по PPS отслеживается через
`clock_skip = F/D`; никакой перекалибровки после PPS или по чётности нет.
### Сравнение режимов на железе FX2 (результат A/B)
- `native` декодировал реальный трафик (ATR, переключение PPS, 100+ валидных
APDU за 12-секундное окно); единственным устойчивым артефактом был
«дребезг» линии VCC — звон ~1 кГц, который теперь подавляет антидребезг 10 мс.
- `detect` ни разу не дал пригодной сессии на этом стенде: он полностью
пропускал переключение скорости по PPS (обработка PPS не срабатывала) и
алиасил весь трафик после PPS; вторая попытка поймала мёртвую линию I/O.
`native` остаётся режимом по умолчанию. Используйте `--clock=detect`
только для офлайн-экспериментов без PPS. Запись, целиком состоящая из
нулевых кадров, означает, что съём потерял контакт с линией.
Чётность — **чётная** по TS 102 221 («чётное число битов, установленных в
'1', включая бит чётности»); кадры, не прошедшие проверку, помечаются
`CHKSUM ERROR`, но всё равно декодируются.
Эквивалентные «сырые» команды sigrok-cli:
```bash
# Минимум: только CLK+I/O, живой поток на localhost:4729
sigrok-cli -d fx2lafw --config samplerate=12M --continuous \
-P iso7816:clk=D0:data=D1:clock_option=detect -A iso7816
# Полное подключение: CLK + I/O + RST + VCC с отслеживанием событий линий
sigrok-cli -d fx2lafw --config samplerate=12M --continuous \
-P iso7816:clk=D5:data=D0:rst=D4:vcc=D2:clock_option=native:rst_detect=true:vcc_detect=true \
-A iso7816
# Поток на удалённый анализатор / отключить стриминг / писать PCAP-файл
... -P iso7816:...:gsmtap_host=10.0.28.7 ...
... -P iso7816:...:gsmtap_enable=false ...
... -P iso7816:...:pcap_file=trace.pcap ...
# Классический режим upstream: бинарный PCAP в stdout
sigrok-cli -i capture.sr -P iso7816:clk=2:data=0 -B iso7816=pcap > out.pcap
```
### Распиновка
Каналы клона FX2 назначаются через `-P iso7816:clk=N:data=N:rst=N:vcc=N`.
Рекомендуемый съём коротким кабелем (с внешними подтягивающими резисторами)
использует фиксированные выводы, которые в точности совпадают с умолчаниями
`start.sh`; `--clk`/`--data`/`--rst`/`--vcc` переназначают их, если вы
подключили иначе:
| Канал FX2 | Контакт SIM | Сигнал |
|-------------|-------------|--------|
| D0 | C7 | I/O |
| D2 | C1 | VCC (только цифровой уровень!) |
| D4 | C2 | RST |
| D5 | C3 | CLK |
| GND | C5 | GND |
Входной порог FX2 близок к TTL (~1.4 В): карты класса 1.8 В могут читаться
нестабильно; классы 3 В/5 В — нормально.
**Частота дискретизации и 8-битный режим (важно):** номинальные 24 МГц FX2
доступны только при дискретизации в 8-битном режиме, т.е. когда **включены
только каналы D0–D7**. Включение 9-го канала (A0/аналоговый на клонах CWAV
AX) или любого аналогового входа переводит сбор в 16-битный, который
libsigrok ограничивает 12 МГц. Поэтому `start.sh`/`start.bat` явно
передают `-C D0,D1,D2,D3,D4,D5,D6,D7` и по умолчанию используют **16 МГц**
(с комфортным запасом под потолком USB 24 МГц; ~3.3 отсчёта на такт CLK
4.8 МГц). `setup.sh`/`setup.bat` проверяют и сообщают фактический максимум
вашего железа при том же ограничении.
## Установка
Оба способа ставят один и тот же декодер — выберите один:
- **Скачать (рекомендуется)** — архив релиза. Не нужно ничего клонировать и
нет истории git: распакуйте, запустите `setup`, затем `start`. Лучший
вариант, если нужен только съём.
- **Из исходников** — `git clone`. Тот же рантайм плюс материал для
разработки: `tests/` и инструменты трасс и базовой линии
(`tools/capture_baseline.sh`, `tools/compare_baseline.sh`,
`tools/vs_reader.py`). Трассы примеров (`examples/`) исключены из git и в
любом случае остаются локальными. В архивах релиза намеренно нет `tests/`,
dev-инструментов и `examples/`.
### Скачать (рекомендуется)
Скачайте последний архив со страницы
[Releases](https://github.com/anttro/sigrok_iso7816_stream/releases/latest):
- `sigrok_iso7816_stream-<version>.tar.gz` — Linux
- `sigrok_iso7816_stream-<version>.zip` — Windows
К каждому релизу прилагается `SHA256SUMS` — в нём **оба** архива.
Положите файл рядом со скачанным архивом и проверьте:
```bash
sha256sum -c --ignore-missing SHA256SUMS # GNU coreutils (Linux)
```
В Windows выполните `certutil -hashfile sigrok_iso7816_stream-<version>.zip SHA256`
и сравните вывод со строкой `.zip` в `SHA256SUMS`.
#### Linux (скачать)
```bash
tar xzf sigrok_iso7816_stream-<version>.tar.gz
cd sigrok_iso7816_stream-<version>
./setup.sh
./start.sh
```
`setup.sh` проверяет, что установлены sigrok-cli и пакет прошивки FX2
(`sigrok-firmware-fx2lafw`), создаёт симлинк каталога проекта в
`~/.local/share/libsigrokdecode/decoders/iso7816` (пользовательские
декодеры перекрывают системные) и опрашивает подключённое устройство на
предмет максимальной поддерживаемой частоты дискретизации.
#### Windows (скачать)
Предварительные требования:
1. **sigrok-cli** — установщик для Windows (0.7.2 x86_64) с
[sigrok.org/wiki/Downloads](https://sigrok.org/wiki/Downloads) —
протестированная версия. На этой же странице публикуются ночные сборки
для Windows; они могут менять синтаксис sigrok-cli или API декодеров,
поэтому поддерживаемой остаётся версия из релизного установщика 0.7.2. Если sigrok-cli не запускается с ошибкой `0xc0150002`, установите
[Visual C++ 2010 Redistributable](https://www.microsoft.com/en-us/download/details.aspx?id=26999)
(`msvcr100.dll` требуется встроенному Python-рантайму).
2. Прошивка fx2lafw поставляется вместе с установщиком — отдельно скачивать не нужно.
Настройка драйвера (донглам FX2 нужен WinUSB, вендорский драйвер не подойдёт):
- Запустите **Zadig**, который лежит *внутри* каталога установки sigrok-cli
(также доступен из меню «Пуск»). Выберите устройство FX2 в выпадающем
списке и установите драйвер **WinUSB**.
- После загрузки прошивки устройство переподключается с другим VID/PID —
если оно всё ещё не находится, запустите Zadig **второй раз** для
переподключившегося устройства.
- Windows привязывает драйверы к USB-порту, когда нет серийного номера:
перенос донгла в другой порт может потребовать повторить Zadig.
Затем распакуйте архив `.zip` (в Проводнике: правой кнопкой → «Извлечь все»)
и запустите в распакованном каталоге:
```bat
setup.bat
start.bat
```
`setup.bat` проверяет sigrok-cli и встроенную прошивку, регистрирует декодер
этого проекта через junction в
`%LOCALAPPDATA%\libsigrokdecode\decoders\iso7816` (подтверждается тем, что
`sigrok-cli -L` показывает `iso7816`), и опрашивает устройство на предмет
поддерживаемых частот дискретизации. В zip-архиве релиза bat-файлы уже с
переводами строк CRLF, поэтому преобразование не требуется.
`start.bat --help` перечисляет его опции (основное подмножество `start.sh`:
каналы, частота дискретизации, clock, host/port, pcap, protocol, debug).
### Linux (из исходников)
```bash
git clone git@github.com:anttro/sigrok_iso7816_stream.git
cd sigrok_iso7816_stream
./setup.sh
```
Свежему клону нужны те же проверки и симлинк `./setup.sh`, что и выше: он
проверяет sigrok-cli и пакет прошивки FX2, создаёт симлинк каталога проекта
в `~/.local/share/libsigrokdecode/decoders/iso7816` и опрашивает устройство
на предмет максимальной частоты дискретизации.
### Windows (из исходников)
Предварительные требования Windows (sigrok-cli и Visual C++ 2010
Redistributable, встроенная прошивка fx2lafw и настройка драйвера
Zadig/WinUSB) — те же, что в разделе
[Windows (скачать)](#windows-скачать) выше.
```bat
git clone git@github.com:anttro/sigrok_iso7816_stream.git
cd sigrok_iso7816_stream
setup.bat
```
`setup.bat` выполняет те же проверки и регистрацию junction, что и выше.
`start.bat` поддерживает основное подмножество опций (каналы, частота
дискретизации, clock, host/port, pcap, protocol, debug; полный набор — в
`start.sh`) — основной формат с пробелом, а `--clk=CH` тоже работает:
```bat
start.bat --clk D1 --data D6
start.bat --help
```
Запись работает так же, как в Linux:
```bat
start.bat rem запись + поток GSMTAP
```
Примечание: bat-файлы требуют переводов строк CRLF; репозиторий следит за
этим через `.gitattributes`, поэтому свежий клон в Windows уже корректен
(zip-архив релиза содержит те же файлы с CRLF).
## Заметки и ограничения по детектированию RST/VCC ## Заметки и ограничения по детектированию RST/VCC
- События детектируются **асинхронно до первого ATR** (включение питания / - События детектируются **асинхронно до первого ATR** (включение питания /
@@ -477,16 +387,11 @@ start.bat rem запись + поток GSMTAP
пакета могут быть пропущены. пакета могут быть пропущены.
- VCC — только цифровой: декодер видит «питание есть/нет», но никогда - VCC — только цифровой: декодер видит «питание есть/нет», но никогда
не класс напряжения (1.8/3/5 В). не класс напряжения (1.8/3/5 В).
- **RST и VCC используют гистерезис стабильности уровня в 10 мс** - **RST и VCC используют гистерезис стабильности уровня 10 мс**
(масштабируется от частоты дискретизации): новый уровень сообщается (масштабируется от частоты дискретизации): новый уровень сообщается
только после того, как он непрерывно стабилен ≥ 10 мс — либо потому, что только после того, как он непрерывно стабилен ≥ 10 мс. Это делает
он держится так долго, либо потому, что он закончился, продержавшись включение и выключение питания *симметричными* и подавляет звон и
столько. Это делает включение и выключение питания *симметричными*: короткие глитчи.
линия VCC, которая **звенит на фронте** (шумный/плавающий съём), больше
не теряет событие «VCC on» — оно срабатывает, как только линия
устанавливается в HIGH, вместо того чтобы быть съеденным дребезгом
фронта. RST использует ту же схему, поэтому короткий глитч RST больше
не вызывает фантомный re-arm по тёплому сбросу.
- **События VCC в целом ненадёжны — лучше не отслеживать VCC.** Плавающий - **События VCC в целом ненадёжны — лучше не отслеживать VCC.** Плавающий
или неподключённый пин съёма VCC всегда читается как HIGH (логическая или неподключённый пин съёма VCC всегда читается как HIGH (логическая
единица без нагрузки), поэтому декодер постоянно видит «питание подано» единица без нагрузки), поэтому декодер постоянно видит «питание подано»
@@ -499,20 +404,10 @@ start.bat rem запись + поток GSMTAP
- Неназначенные опциональные каналы игнорируются, даже если - Неназначенные опциональные каналы игнорируются, даже если
`rst_detect`/`vcc_detect` включены (защита через `has_channel()`). `rst_detect`/`vcc_detect` включены (защита через `has_channel()`).
## Тестирование ## Разработка и тестирование
Проверено на примерах записей из upstream: Декодер проверяется на примерах записей с помощью `tools/vs_reader.py`.
Фикстуры трасс хранятся локально и не входят в репозиторий.
```bash
# ATR+PPS+54 APDU из записи ридера test_8 (~19 с декодирования)
# Поток GSMTAP проверен через tshark (ATR/APDU разбираются нативно),
# кастомные события 0x10/0x11 — через UDP-слушатель, и сквозным путём
# в сервер SIMtrace Analyser (POST /api/capture/start → decode → stop).
```
Синтетический генератор VCD, покрывающий краевые случаи RST/VCC, живёт в
заметках проекта (`projects/SIGROK_ISO7816.md` в родительском рабочем
пространстве).
### Проверка по SDK ридера (`tools/vs_reader.py`) ### Проверка по SDK ридера (`tools/vs_reader.py`)
@@ -529,33 +424,12 @@ python3 tools/vs_reader.py <reader-log>.log out.pcap
`vs_reader.py` выравнивает каждый обмен из журнала ридера с APDU из записи `vs_reader.py` выравнивает каждый обмен из журнала ридера с APDU из записи
(побайтовое LCS-совпадение) и классифицирует остатки как proactive/CAT (побайтовое LCS-совпадение) и классифицирует остатки как proactive/CAT
(невидимые для SDK ридера), pre-capture/потерянные или мусор. (невидимые для SDK ридера), pre-capture/потерянные или мусор.
Запись, начатая в середине сессии, тёплые сбросы которой раньше давали
4 мусорных события, с re-arm и защитой стартового бита декодируется в
**0 мусора** (`RESULT: OK - capture fully explained`).
test_7 (4 сброса ATR, фрагментирующих сессию) теперь захватывает все 37/37
обменов ридера (было 10/37 до исправления деглитча). Телефонные трассы
Samsung с 16 CLK/ETU (F=512/D=32) теперь разбираются на 924 отдельных
обмена T=0 (раньше сливались в 52 APDU завышенного размера).
Воспроизводимые фикстуры трасс (хранятся локально, вне репозитория)
покрывают сессии ридера с контролируемого стенда (с эталонными журналами
SDK ридера), телефонные записи с гейтированным CLK и **записи холодного
старта**, начинающиеся *до* включения питания (VCC/RST низкие при t=0).
Четыре фикстуры Samsung — холодные старты, снятые новым коротким кабелем
(провода 30 мм, внешние подтягивающие резисторы GND→VCC и VCC→DATA), с
каналами `DATA/VCC/RST/CLK` на битах 0/2/4/5; варианты `sim2` обрезаны до
окна включения питания.
### Записи холодного старта (запись начинается до включения питания) ### Записи холодного старта (запись начинается до включения питания)
Когда запись начинается до включения питания, декодер должен взвести охоту Когда запись начинается до включения питания, RST всё ещё низкий на
за ATR, потому что RST всё ещё низкий на отсчёте 0: он инициализирует отсчёте 0. Используйте `rst_detect=true` и `protocol=T=0`; декодер взводит
начальные уровни VCC/RST на первом шаге (вместо того чтобы по умолчанию охоту за ATR по начальному уровню RST и разбирает полный ATR. Пример:
считать их снятыми) и при низком RST на старте входит в `FIND START` с
очищенным ETU, поэтому переходы DATA при включении питания до ATR не могут
зафиксировать фиктивную битовую скорость. Затем он декодирует полный ATR
(`3b9f96801fc78031e073fe2117574a3382033339001e`) с 0 мусора:
```bash ```bash
sigrok-cli -i <coldboot>.sr \ sigrok-cli -i <coldboot>.sr \
@@ -563,52 +437,17 @@ sigrok-cli -i <coldboot>.sr \
-A iso7816 -A iso7816
``` ```
Снятие RST (deassert), которое приходит, пока разбор ATR уже идёт, больше не
перевзводит охоту посреди чтения — оно логирует `RST deasserted (hunt/ATR
already in progress)` и не трогает разбираемый ATR (test_8/test_7
CHKSUM 18→0).
### Сценарии записи: ридер (постоянный CLK) и телефон (Clock Stop Mode) ### Сценарии записи: ридер (постоянный CLK) и телефон (Clock Stop Mode)
Декодер обрабатывает две физически разные схемы съёма SIM:
- **Запись ридера / постоянный CLK** — ридер ведёт ровный CLK всю сессию. - **Запись ридера / постоянный CLK** — ридер ведёт ровный CLK всю сессию.
В режиме mid-session запись декодируется в **0 мусора** Проверяйте её по SDK ридера через
(`RESULT: OK`) относительно эталона из SDK ридера `tools/vs_reader.py <reader-log>.log out.pcap`.
(`tools/vs_reader.py <reader-log>.log out.pcap`). - **Запись телефона / гейтированный или остановленный CLK** — телефон
Записи ридера с тёплыми сбросами используют fallback с синтетическим гейтирует или останавливает CLK между передачами (Clock Stop Mode),
T=0-ATR. поэтому ETU нельзя вывести из CLK. Запускайте с `protocol=T=0`; декодер
восстанавливает ETU из линии DATA и декодирует edge-list читателем.
- **Запись телефона / остановленный CLK** — телефон гейтирует или Команды T=0 case 3/4 (например, `80 12`/`80 14` STK envelope) объединяются
останавливает CLK между передачами (Clock Stop Mode), поэтому ETU не в один APDU команда→ответ.
равен стандартным 372 тактам и не может быть выведен из CLK. Запускайте
с `protocol=T=0`; декодер восстанавливает ETU из линии DATA подсчётом
фронтов, фиксирует его и декодирует устойчивым к дрейфу edge-list
читателем битов. Команды T=0 case 3/4 (например, `80 12`/`80 14`
STK envelope) объединяются в один APDU команда→ответ. Деглитч стартового
бита в 2 отсчёта убирает LOW-глитчи короче ETU, вызванные артефактами
внутренней подтяжки FX2LP, и предотвращает смещение байтов на быстрых
телефонных трассах.
### Проверенные скорости данных и ETU
Все трассы декодированы на **частоте дискретизации 16 МГц**, 0 мусора,
RESULT: OK. Начиная с v1.5.0 каждая трасса из набора примеров также
сообщает **0 CONCAT** (перекадрирование по некорректному INS устранило
последнее семейство проглатывания нескольких обменов на
4gmodem/A55_sim2/S21p_sim2).
| Трасса | Режим CLK | ETU (отсчёты) | CLK/ETU | Конвенция | Примечания |
|-------|----------|---------------|---------|------------|-------|
| test_8 | постоянный | ~43 | 372 (стандарт) | Direct | PC/SC ридер, ATR+PPS+APDU |
| test_7 | постоянный | ~43 | 372 (стандарт) | Direct | PC/SC ридер, тёплые сбросы |
| xiaomi | гейтированный/остановленный | ~53 | восстановлен из DATA | Direct | Телефон, середина сессии |
| samsung | гейтированный/остановленный | ~72 | 16 (F=512/D=32) | Direct | Телефон, нестандартный F/D, меню STK |
Декодер автоопределяет ETU по трассе и выбирает подходящий читатель битов
(CLK-синхронный для постоянного CLK, edge-list для гейтированного/
остановленного CLK). Никакой ручной настройки не требуется, кроме
`clock_option=native` и `protocol=T=0` для телефонных записей.
Рекомендуемые вызовы: Рекомендуемые вызовы:
@@ -625,6 +464,28 @@ sigrok-cli -i <phone>.sr \
-A iso7816 -A iso7816
``` ```
### Скорости данных и ETU
Справочные значения, наблюдавшиеся на примерах записей при частоте
дискретизации 16 МГц:
| Трасса | Режим CLK | ETU (отсчёты) | CLK/ETU | Конвенция | Примечания |
|-------|----------|---------------|---------|------------|-------|
| test_8 | постоянный | ~43 | 372 (стандарт) | Direct | PC/SC ридер, ATR+PPS+APDU |
| test_7 | постоянный | ~43 | 372 (стандарт) | Direct | PC/SC ридер, тёплые сбросы |
| xiaomi | гейтированный/остановленный | ~53 | восстановлен из DATA | Direct | Телефон, середина сессии |
| samsung | гейтированный/остановленный | ~72 | 16 (F=512/D=32) | Direct | Телефон, нестандартный F/D, меню STK |
| alcor_reader | постоянный | ~53 | 16 (F=512/D=32) | Direct | PC/SC ридер, CLK 4.0 МГц на ATR -> 4.8 МГц после PPS |
Декодер автоопределяет ETU и выбирает подходящий читатель битов
(CLK-синхронный для постоянного CLK, edge-list для гейтированного/
остановленного CLK). Никакой ручной настройки не требуется, кроме
`clock_option=native` и `protocol=T=0` для телефонных записей.
Чётность — **чётная** по TS 102 221 («чётное число битов, установленных в
'1', включая бит чётности»); кадры, не прошедшие проверку, помечаются
`CHKSUM ERROR`, но всё равно декодируются.
## Лицензия ## Лицензия
GPL-2.0+, как и upstream. GPL-2.0+, как и upstream.