Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b54e130c2 | ||
|
|
6e663dcdcb | ||
|
|
8214089b2d | ||
|
|
9112eafec0 | ||
|
|
847b49ec12 | ||
|
|
a385648a80 | ||
|
|
8e36419143 | ||
|
|
50fe1bc51b | ||
|
|
2e3a563824 |
No files matched your search
@@ -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 *Install and start* 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
|
||||||
@@ -1033,11 +1033,13 @@ pathspec, and also compared exactly against both archive listings (missing
|
|||||||
*and* unexpected entries fail): the decoder (`__init__.py`, `pd.py`,
|
*and* unexpected entries fail): the decoder (`__init__.py`, `pd.py`,
|
||||||
`gsmtap_stream.py`), the scripts (`setup.sh`/`start.sh`,
|
`gsmtap_stream.py`), the scripts (`setup.sh`/`start.sh`,
|
||||||
`setup.bat`/`start.bat`), `tools/vs_reader.py`, `README.md`, `README_RUS.md`,
|
`setup.bat`/`start.bat`), `tools/vs_reader.py`, `README.md`, `README_RUS.md`,
|
||||||
`LICENSE`, and every `resources/` image referenced from `README.md`. Tests,
|
`LICENSE`, every `resources/` photo referenced from both READMEs, and the two
|
||||||
`AGENTS.md`, the CI config, the development tools and the unreferenced
|
language variants of the pipeline diagram (`resources/diagram_en.svg`,
|
||||||
`resources/` images never enter the release. No `export-ignore` rules are
|
`resources/diagram_ru.svg`, added explicitly because each README embeds its
|
||||||
used, so GitHub's own source archives still contain the full tree. `dist/`
|
own). Tests, `AGENTS.md`, the CI config, the development tools and the
|
||||||
is gitignored.
|
unreferenced `resources/` images never enter the release. No `export-ignore`
|
||||||
|
rules are used, so GitHub's own source archives still contain the full tree.
|
||||||
|
`dist/` is gitignored.
|
||||||
|
|
||||||
Both archives are unpacked and verified: `pd.py` VERSION, `py_compile` of the
|
Both archives are unpacked and verified: `pd.py` VERSION, `py_compile` of the
|
||||||
three modules, `bash -n` of the shell scripts, the tar exec bits, CRLF on the
|
three modules, `bash -n` of the shell scripts, the tar exec bits, CRLF on the
|
||||||
@@ -1050,11 +1052,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
|
||||||
|
|||||||
@@ -1,21 +1,266 @@
|
|||||||
# sigrok_iso7816_stream
|
# sigrok_iso7816_stream — a passive ISO 7816 sniffer
|
||||||
|
|
||||||
|
English | [Русский](README_RUS.md)
|
||||||
|
|
||||||
|
📢 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:
|
||||||
|
|
||||||
```
|

|
||||||
SIM card ⇄ reader (passive tap on the contacts)
|
|
||||||
→ FX2 logic analyzer (fx2lafw, 8ch, 24MHz max)
|
|
||||||
→ sigrok-cli + iso7816 decoder
|
|
||||||
→ GSMTAP UDP :4729 → [SIMtrace Analyser](https://github.com/anttro/simtrace-analyser) / Wireshark
|
|
||||||
```
|
|
||||||
|
|
||||||
[SIMtrace Analyser](https://github.com/anttro/simtrace-analyser) is the
|
[SIMtrace Analyser](https://github.com/anttro/simtrace-analyser) is the
|
||||||
recommended tool for visualising live traces and viewing saved captures —
|
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
|
||||||
|
|
||||||

|

|
||||||
@@ -45,23 +290,23 @@ this decoder's `pcap_file=<path>` option).
|
|||||||

|

|
||||||
*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 +360,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 +370,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 +383,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 +403,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 +416,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 +442,40 @@ 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.
|
||||||
|
|
||||||
|
## Related tools
|
||||||
|
|
||||||
|
SIMple, SIMtrace Analyser and sigrok_iso7816_stream are three standalone
|
||||||
|
tools for working with SIM/UICC cards, published together on the same
|
||||||
|
[website](https://atroshin.ru) and [news channel](https://t.me/youeyeseesee).
|
||||||
|
Each one is fully independent — install only the tools you need:
|
||||||
|
|
||||||
|
- **[SIMple](https://github.com/anttro/simple)** — a UICC workbench: APDU
|
||||||
|
construction, SCP80/SCP81 OTA, SIM Toolkit simulation and card profiling.
|
||||||
|
- **[SIMtrace Analyser](https://github.com/anttro/simtrace-analyser)** — an
|
||||||
|
APDU trace analyser for GSMTAP-SIM captures.
|
||||||
|
- **[sigrok_iso7816_stream](https://github.com/anttro/sigrok_iso7816_stream)** —
|
||||||
|
a passive ISO 7816 sniffer built on a cheap FX2 logic analyser.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
GPL-2.0+, same as upstream.
|
GPL-2.0+, same as upstream.
|
||||||
+325
-454
@@ -1,17 +1,14 @@
|
|||||||
> English version: [README.md](README.md)
|
# sigrok_iso7816_stream — пассивный ISO 7816-сниффер
|
||||||
|
|
||||||
# sigrok_iso7816_stream
|
[English](README.md) | Русский
|
||||||
|
|
||||||
|
📢 Новости и обновления проекта: [сайт](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:
|
||||||
|
|
||||||
```
|

|
||||||
SIM-карта ⇄ ридер (пассивный съём с контактов)
|
|
||||||
→ логический анализатор FX2 (fx2lafw, 8 каналов, до 24 МГц)
|
|
||||||
→ sigrok-cli + декодер iso7816
|
|
||||||
→ GSMTAP UDP :4729 → [SIMtrace Analyser](https://github.com/anttro/simtrace-analyser) / Wireshark
|
|
||||||
```
|
|
||||||
|
|
||||||
[SIMtrace Analyser](https://github.com/anttro/simtrace-analyser) —
|
[SIMtrace Analyser](https://github.com/anttro/simtrace-analyser) —
|
||||||
рекомендуемый инструмент для визуализации живых трасс и просмотра
|
рекомендуемый инструмент для визуализации живых трасс и просмотра
|
||||||
@@ -19,6 +16,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
|
||||||
|
```
|
||||||
|
|
||||||
## Съём на практике
|
## Съём на практике
|
||||||
|
|
||||||

|

|
||||||
@@ -48,23 +301,23 @@ GSMTAP pcap-файлы (включая PCAP, который этот декод
|
|||||||

|

|
||||||
*Короткий кабель с внешними подтягивающими резисторами — 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 +372,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 +382,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 +399,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 +419,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 +432,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 +459,43 @@ 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`, но всё равно декодируются.
|
||||||
|
|
||||||
|
## Связанные инструменты
|
||||||
|
|
||||||
|
SIMple, SIMtrace Analyser и sigrok_iso7816_stream — три автономных
|
||||||
|
инструмента для работы с SIM/UICC-картами, представленные на одном
|
||||||
|
[сайте](https://atroshin.ru) и в одном [Telegram-канале](https://t.me/youeyeseesee).
|
||||||
|
Каждый полностью независим — устанавливайте только нужные вам:
|
||||||
|
|
||||||
|
- **[SIMple](https://github.com/anttro/simple)** — мастерская для UICC/SIM:
|
||||||
|
конструкторы APDU, OTA SCP80/SCP81, симуляция SIM Toolkit и профилирование
|
||||||
|
карт.
|
||||||
|
- **[SIMtrace Analyser](https://github.com/anttro/simtrace-analyser)** —
|
||||||
|
анализатор APDU-трассировок GSMTAP-SIM.
|
||||||
|
- **[sigrok_iso7816_stream](https://github.com/anttro/sigrok_iso7816_stream)** —
|
||||||
|
пассивный ISO 7816-сниффер на дешёвом логическом анализаторе FX2.
|
||||||
|
|
||||||
## Лицензия
|
## Лицензия
|
||||||
|
|
||||||
GPL-2.0+, как и upstream.
|
GPL-2.0+, как и upstream.
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="690" viewBox="0 0 960 690" role="img" aria-labelledby="diagram-title diagram-desc" font-family="'Segoe UI', 'Helvetica Neue', Arial, 'DejaVu Sans', sans-serif">
|
||||||
|
<title id="diagram-title">sigrok_iso7816_stream: signal path</title>
|
||||||
|
<desc id="diagram-desc">SIM card and device with a passive tap on the contacts, FX2 logic analyzer (fx2lafw, 8 channels, up to 24 MHz), sigrok-cli with the iso7816 decoder, GSMTAP UDP :4729, SIMtrace Analyser and Wireshark</desc>
|
||||||
|
<defs>
|
||||||
|
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||||
|
<path d="M0 0 L10 5 L0 10 Z" fill="#64748b"/>
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<rect x="1" y="1" width="958" height="688" rx="18" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.5"/>
|
||||||
|
<text x="480" y="30" text-anchor="middle" font-size="14" fill="#475569">passive tap on the contacts</text>
|
||||||
|
<rect x="150" y="48" width="210" height="72" rx="12" fill="#eff6ff" stroke="#93c5fd" stroke-width="1.5"/>
|
||||||
|
<text x="255" y="90" text-anchor="middle" font-size="20" font-weight="600" fill="#0f172a">SIM card</text>
|
||||||
|
<rect x="600" y="48" width="210" height="72" rx="12" fill="#eff6ff" stroke="#93c5fd" stroke-width="1.5"/>
|
||||||
|
<text x="705" y="90" text-anchor="middle" font-size="20" font-weight="600" fill="#0f172a">Device</text>
|
||||||
|
<line x1="372" y1="84" x2="588" y2="84" stroke="#64748b" stroke-width="2" marker-start="url(#arrow)" marker-end="url(#arrow)"/>
|
||||||
|
<circle cx="480" cy="84" r="5" fill="#2563eb"/>
|
||||||
|
<line x1="480" y1="89" x2="480" y2="196" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
|
||||||
|
<rect x="270" y="200" width="420" height="92" rx="12" fill="#f5f3ff" stroke="#c4b5fd" stroke-width="1.5"/>
|
||||||
|
<text x="480" y="236" text-anchor="middle" font-size="20" font-weight="600" fill="#0f172a">FX2 logic analyzer</text>
|
||||||
|
<text x="480" y="265" text-anchor="middle" font-size="15" fill="#475569">fx2lafw · 8 channels · up to 24 MHz</text>
|
||||||
|
<line x1="480" y1="292" x2="480" y2="332" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
|
||||||
|
<rect x="270" y="336" width="420" height="80" rx="12" fill="#ecfdf5" stroke="#6ee7b7" stroke-width="1.5"/>
|
||||||
|
<text x="480" y="382" text-anchor="middle" font-size="19" font-weight="600" fill="#0f172a" xml:space="preserve"><tspan font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">sigrok-cli</tspan><tspan> + </tspan><tspan font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">iso7816</tspan><tspan> decoder</tspan></text>
|
||||||
|
<line x1="480" y1="416" x2="480" y2="456" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
|
||||||
|
<rect x="320" y="460" width="320" height="72" rx="12" fill="#fffbeb" stroke="#fcd34d" stroke-width="1.5"/>
|
||||||
|
<text x="480" y="502" text-anchor="middle" font-size="19" font-weight="600" fill="#0f172a" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">GSMTAP UDP :4729</text>
|
||||||
|
<path d="M480 532 L480 548 Q480 558 470 558 L255 558 Q245 558 245 568 L245 584" fill="none" stroke="#64748b" stroke-width="2" stroke-linejoin="round" marker-end="url(#arrow)"/>
|
||||||
|
<path d="M480 532 L480 548 Q480 558 490 558 L705 558 Q715 558 715 568 L715 584" fill="none" stroke="#64748b" stroke-width="2" stroke-linejoin="round" marker-end="url(#arrow)"/>
|
||||||
|
<rect x="110" y="588" width="270" height="72" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
|
||||||
|
<text x="245" y="630" text-anchor="middle" font-size="18" font-weight="600" fill="#0f172a">SIMtrace Analyser</text>
|
||||||
|
<rect x="580" y="588" width="270" height="72" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
|
||||||
|
<text x="715" y="630" text-anchor="middle" font-size="18" font-weight="600" fill="#0f172a">Wireshark</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="960" height="690" viewBox="0 0 960 690" role="img" aria-labelledby="diagram-title diagram-desc" font-family="'Segoe UI', 'Helvetica Neue', Arial, 'DejaVu Sans', sans-serif">
|
||||||
|
<title id="diagram-title">sigrok_iso7816_stream: путь сигнала</title>
|
||||||
|
<desc id="diagram-desc">SIM-карта и устройство с пассивным съёмом с контактов, логический анализатор FX2 (fx2lafw, 8 каналов, до 24 МГц), sigrok-cli с декодером iso7816, GSMTAP UDP :4729, SIMtrace Analyser и Wireshark</desc>
|
||||||
|
<defs>
|
||||||
|
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse">
|
||||||
|
<path d="M0 0 L10 5 L0 10 Z" fill="#64748b"/>
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<rect x="1" y="1" width="958" height="688" rx="18" fill="#ffffff" stroke="#e2e8f0" stroke-width="1.5"/>
|
||||||
|
<text x="480" y="30" text-anchor="middle" font-size="14" fill="#475569">пассивный съём с контактов</text>
|
||||||
|
<rect x="150" y="48" width="210" height="72" rx="12" fill="#eff6ff" stroke="#93c5fd" stroke-width="1.5"/>
|
||||||
|
<text x="255" y="90" text-anchor="middle" font-size="20" font-weight="600" fill="#0f172a">SIM-карта</text>
|
||||||
|
<rect x="600" y="48" width="210" height="72" rx="12" fill="#eff6ff" stroke="#93c5fd" stroke-width="1.5"/>
|
||||||
|
<text x="705" y="90" text-anchor="middle" font-size="20" font-weight="600" fill="#0f172a">Устройство</text>
|
||||||
|
<line x1="372" y1="84" x2="588" y2="84" stroke="#64748b" stroke-width="2" marker-start="url(#arrow)" marker-end="url(#arrow)"/>
|
||||||
|
<circle cx="480" cy="84" r="5" fill="#2563eb"/>
|
||||||
|
<line x1="480" y1="89" x2="480" y2="196" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
|
||||||
|
<rect x="270" y="200" width="420" height="92" rx="12" fill="#f5f3ff" stroke="#c4b5fd" stroke-width="1.5"/>
|
||||||
|
<text x="480" y="236" text-anchor="middle" font-size="20" font-weight="600" fill="#0f172a">Логический анализатор FX2</text>
|
||||||
|
<text x="480" y="265" text-anchor="middle" font-size="15" fill="#475569">fx2lafw · 8 каналов · до 24 МГц</text>
|
||||||
|
<line x1="480" y1="292" x2="480" y2="332" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
|
||||||
|
<rect x="270" y="336" width="420" height="80" rx="12" fill="#ecfdf5" stroke="#6ee7b7" stroke-width="1.5"/>
|
||||||
|
<text x="480" y="382" text-anchor="middle" font-size="19" font-weight="600" fill="#0f172a" xml:space="preserve"><tspan font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">sigrok-cli</tspan><tspan> + декодер </tspan><tspan font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">iso7816</tspan></text>
|
||||||
|
<line x1="480" y1="416" x2="480" y2="456" stroke="#64748b" stroke-width="2" marker-end="url(#arrow)"/>
|
||||||
|
<rect x="320" y="460" width="320" height="72" rx="12" fill="#fffbeb" stroke="#fcd34d" stroke-width="1.5"/>
|
||||||
|
<text x="480" y="502" text-anchor="middle" font-size="19" font-weight="600" fill="#0f172a" font-family="'Cascadia Mono', Consolas, 'DejaVu Sans Mono', monospace">GSMTAP UDP :4729</text>
|
||||||
|
<path d="M480 532 L480 548 Q480 558 470 558 L255 558 Q245 558 245 568 L245 584" fill="none" stroke="#64748b" stroke-width="2" stroke-linejoin="round" marker-end="url(#arrow)"/>
|
||||||
|
<path d="M480 532 L480 548 Q480 558 490 558 L705 558 Q715 558 715 568 L715 584" fill="none" stroke="#64748b" stroke-width="2" stroke-linejoin="round" marker-end="url(#arrow)"/>
|
||||||
|
<rect x="110" y="588" width="270" height="72" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
|
||||||
|
<text x="245" y="630" text-anchor="middle" font-size="18" font-weight="600" fill="#0f172a">SIMtrace Analyser</text>
|
||||||
|
<rect x="580" y="588" width="270" height="72" rx="12" fill="#f8fafc" stroke="#cbd5e1" stroke-width="1.5"/>
|
||||||
|
<text x="715" y="630" text-anchor="middle" font-size="18" font-weight="600" fill="#0f172a">Wireshark</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.9 KiB |
+13
-2
@@ -38,13 +38,23 @@ trap 'rm -rf "$STAGE"' EXIT
|
|||||||
|
|
||||||
# --- expected release contents (allowlist) -------------------------------
|
# --- expected release contents (allowlist) -------------------------------
|
||||||
# The base runtime files plus every image referenced from the READMEs.
|
# The base runtime files plus every image referenced from the READMEs.
|
||||||
|
# Each README embeds its own language variant of the pipeline diagram, so the
|
||||||
|
# two diagrams are added explicitly instead of joining the shared-photo check.
|
||||||
|
LANG_RES="resources/diagram_en.svg resources/diagram_ru.svg"
|
||||||
README_RES="$(git show "$REF:README.md" \
|
README_RES="$(git show "$REF:README.md" \
|
||||||
| grep -oE '\]\(resources/[^)]+' | sed 's/](//' | LC_ALL=C sort -u || true)"
|
| grep -oE '\]\(resources/[^)]+' | sed 's/](//' \
|
||||||
|
| grep -v -e '^resources/diagram_en\.svg$' -e '^resources/diagram_ru\.svg$' \
|
||||||
|
| LC_ALL=C sort -u || true)"
|
||||||
[ -n "$README_RES" ] || die "no resources/ images referenced from $REF:README.md"
|
[ -n "$README_RES" ] || die "no resources/ images referenced from $REF:README.md"
|
||||||
README_RUS_RES="$(git show "$REF:README_RUS.md" \
|
README_RUS_RES="$(git show "$REF:README_RUS.md" \
|
||||||
| grep -oE '\]\(resources/[^)]+' | sed 's/](//' | LC_ALL=C sort -u || true)"
|
| grep -oE '\]\(resources/[^)]+' | sed 's/](//' \
|
||||||
|
| grep -v -e '^resources/diagram_en\.svg$' -e '^resources/diagram_ru\.svg$' \
|
||||||
|
| LC_ALL=C sort -u || true)"
|
||||||
[ "$README_RES" = "$README_RUS_RES" ] || \
|
[ "$README_RES" = "$README_RUS_RES" ] || \
|
||||||
die "README.md and README_RUS.md reference different resources/ images"
|
die "README.md and README_RUS.md reference different resources/ images"
|
||||||
|
for res in $LANG_RES; do
|
||||||
|
git cat-file -e "$REF:$res" 2>/dev/null || die "missing $res at $REF"
|
||||||
|
done
|
||||||
|
|
||||||
EXPECTED="$STAGE/expected.list"
|
EXPECTED="$STAGE/expected.list"
|
||||||
{
|
{
|
||||||
@@ -53,6 +63,7 @@ EXPECTED="$STAGE/expected.list"
|
|||||||
setup.sh start.sh setup.bat start.bat \
|
setup.sh start.sh setup.bat start.bat \
|
||||||
tools/vs_reader.py README.md README_RUS.md LICENSE
|
tools/vs_reader.py README.md README_RUS.md LICENSE
|
||||||
printf '%s\n' "$README_RES"
|
printf '%s\n' "$README_RES"
|
||||||
|
printf '%s\n' resources/diagram_en.svg resources/diagram_ru.svg
|
||||||
} | LC_ALL=C sort -u > "$EXPECTED"
|
} | LC_ALL=C sort -u > "$EXPECTED"
|
||||||
|
|
||||||
PATHS=()
|
PATHS=()
|
||||||
|
|||||||
Reference in new issue
Block a user