README: install/start first, remove history-heavy sections

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

Docs only; no decoder or release change.
This commit is contained in:
catarrh committed 2026-10-27 10:48:42 +03:00
1 parent 8e36419143
commit a385648a80
2 files changed
+617 -875

No files matched your search

+315 -446
View File
@@ -21,6 +21,272 @@ SIM-карта ⇄ ридер (пассивный съём с контактов
GSMTAP pcap-файлы (включая PCAP, который этот декодер пишет через опцию
`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 В — нормально.
**Частота дискретизации и 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` проверяют и сообщают фактический максимум
вашего железа при том же ограничении.
### Режимы CLK
- `native` (по умолчанию) — живые записи. Декодер отслеживает переключение
скорости по PPS и заново взводится по RST, поэтому тёплые сбросы и трафик
после PPS разбираются корректно.
- `detect` — для офлайн-экспериментов или записей без PPS. Он не отслеживает
переключение по PPS, поэтому трафик после PPS может читаться неверно.
- `sample_as_clock` — экспериментальный режим upstream; для съёма SIM не
рекомендуется.
### Решение проблем при живой записи
**Запись обрывается рано (особенно в Windows).** Частая причина —
неподходящий драйвер USB. Драйвер Saleae Logic работает только с Saleae
Logic software; sigrok нужен драйвер **WinUSB**. Установите его через
**Zadig** (входит в установщик sigrok-cli) и повторите назначение после
переподключения устройства с VID/PID прошивки. Подробности в документации
sigrok:
- https://sigrok.org/wiki/Windows#Drivers
- https://sigrok.org/wiki/Fx2lafw
**Устройство не найдено / нет сигнала.** Проверьте драйвер WinUSB (Windows),
прошивку fx2lafw, подключение и GND (см. «Подключение»), попробуйте другой
USB-порт и заведомо исправный кабель. Дешёвые USB-кабели и хабы — частая
причина остановок.
**Запись завершается сама (`rc=0`).** FX2 упирается в потолок пропускной
способности USB на высокой частоте дискретизации. Снизьте `--samplerate`,
избегайте хабов, закройте другой USB-трафик. `start.sh` автоматически
перезапускает запись при `rc=0` (по умолчанию 20 перезапусков с паузой 2 с;
`--no-loop`, `--max-restarts=N`, `--restart-delay=S`). При `--pcap=FILE`
каждый перезапуск пишет `FILE.<N>.<ext>`.
`start.sh` работает до Ctrl+C; нажатия клавиш его не останавливают
(приглашение «нажмите любую клавишу» отключено). Полезные опции:
```bash
./start.sh --pcap=s.pcap --log=s.log # записать события и вердикт rc=
./start.sh ... --samplerate=24M # больше запаса по таймингу при необходимости
./start.sh ... --klog # также записать журнал ядра
./start.sh ... --debug # полный вывод декодера и sigrok
```
- `--log` сохраняет строку вердикта `rc=` в конце сессии.
- Декодер пишет `SIGNAL INTEGRITY WARNING`, когда ≥ 8 из последних 64 кадров
не проходят проверку чётности.
- Десинхронизированные пакеты сохраняются с флагом `GSMTAP_FLAG_BAD_FCS` в
байте `res` заголовка GSMTAP — видно в Wireshark как предупреждение BAD-FCS.
### Сырые команды sigrok-cli
Эквивалентные команды без скриптов-обёрток:
```bash
# Минимум: только CLK+I/O, живой поток на localhost:4729
sigrok-cli -d fx2lafw --config samplerate=12M --continuous \
-P iso7816:clk=D0:data=D1:clock_option=detect -A iso7816
# Полное подключение: CLK + I/O + RST + VCC с отслеживанием событий линий
sigrok-cli -d fx2lafw --config samplerate=12M --continuous \
-P iso7816:clk=D5:data=D0:rst=D4:vcc=D2:clock_option=native:rst_detect=true:vcc_detect=true \
-A iso7816
# Поток на удалённый анализатор / отключить стриминг / писать PCAP-файл
... -P iso7816:...:gsmtap_host=10.0.28.7 ...
... -P iso7816:...:gsmtap_enable=false ...
... -P iso7816:...:pcap_file=trace.pcap ...
# Классический режим upstream: бинарный PCAP в stdout
sigrok-cli -i capture.sr -P iso7816:clk=2:data=0 -B iso7816=pcap > out.pcap
```
## Съём на практике
![Компоненты](resources/components.jpg)
@@ -50,23 +316,23 @@ GSMTAP pcap-файлы (включая PCAP, который этот декод
![Подтягивающие резисторы](resources/short_cable_pull_resistors.jpg)
*Короткий кабель с внешними подтягивающими резисторами — 10 кОм к GND на VCC (тянет вниз, когда питания нет), 47 кОм к VCC на DATA (быстрее фронт вверх)*
## Что добавлено поверх upstream
## Возможности
| Возможность | Описание |
|---------|-------------|
| Живой поток 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-пакеты |
| Отслеживание RST (опционально) | `rst_detect=true`: события assert/deassert сброса (sub_type 0x10) |
| Отслеживание VCC (опционально) | `vcc_detect=true`: события включения/выключения питания (sub_type 0x11) |
| PCAP сразу в файл | `pcap_file=<path>` пишет PCAP без перенаправления вывода оболочки |
| Деглитч стартового бита | Деглитч в детекторе стартового бита (2 отсчёта при 16 МГц, с v1.9.7 масштабируется от частоты дискретизации) убирает LOW-глитчи короче ETU от артефактов подтяжки FX2LP и предотвращает смещение байтов на быстрых телефонных трассах |
| Захват ETU в середине сессии | Оценщик ETU по фронтам DATA отбрасывает пачки только со сторожевым интервалом (нулевые данные) и одиночные интервалы, а также сбрасывает скорость, не прошедшую проверку чётности, поэтому трасса с нестандартным F/D захватывается надёжно |
| Защита ATR / ресинхронизации | `0x3B`/`0x3F` в состоянии DATA считается кандидатом в ATR только до первого APDU; кадры с ошибкой чётности или голый TS+T0 игнорируются, а `resync_idle` действительно ждёт уровень простоя |
| Инверсная конвенция | ATR с TS=0x3F разбирается по ISO 7816-3 7.1: инверсные данные, msb первым, стартовый бит по-прежнему LOW при простое линии HIGH |
| Блоки T=1 | Разбор NAD/PCB/LEN/INF/LRC с цепочкой по биту M; INF I-блока выдаётся как APDU, R/S-блоки не выдаются; обрезанная запись завершается чисто |
| Флаг чётности | Пакет с байтом с ошибкой чётности выдаётся с флагом GSMTAP BAD_FCS (не только аннотацией) |
| Пороги от частоты | Деглитч стартового бита, пороги защиты и порог глитча ETU масштабируются от частоты дискретизации, а не считаются от 16 МГц |
| Деглитч стартового бита | Подавляет LOW-глитчи короче ETU (2 отсчёта при 16 МГц, масштабируется от частоты дискретизации) |
| Захват ETU в середине сессии | Восстанавливает ETU по линии DATA, когда CLK непригоден; скорость, не прошедшая проверку чётности, измеряется заново |
| Защита ATR / ресинхронизации | Проверяет ATR, игнорирует неверно кадрированные кандидаты и выравнивается после десинхронизации |
| Инверсная конвенция | Поддерживает прямую (TS=0x3B) и инверсную (TS=0x3F) карты |
| Блоки T=1 | Разбирает NAD/PCB/LEN/INF/LRC с цепочкой по биту M; INF I-блока выдаётся как APDU |
| Флаг чётности | Пакеты с ошибкой чётности помечаются `GSMTAP_FLAG_BAD_FCS` |
| Пороги от частоты | Пороги деглитча, защиты и ETU масштабируются от частоты дискретизации |
## Опции декодера
@@ -121,354 +387,6 @@ uint32 в герцах (полезная нагрузка 7 байт). Пока
никогда не заполняет `res`); семантика флагов повторяет флаги данных (data
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
- События детектируются **асинхронно до первого ATR** (включение питания /
@@ -479,16 +397,11 @@ start.bat rem запись + поток GSMTAP
пакета могут быть пропущены.
- VCC — только цифровой: декодер видит «питание есть/нет», но никогда
не класс напряжения (1.8/3/5 В).
- **RST и VCC используют гистерезис стабильности уровня в 10 мс**
- **RST и VCC используют гистерезис стабильности уровня 10 мс**
(масштабируется от частоты дискретизации): новый уровень сообщается
только после того, как он непрерывно стабилен ≥ 10 мс — либо потому, что
он держится так долго, либо потому, что он закончился, продержавшись
столько. Это делает включение и выключение питания *симметричными*:
линия VCC, которая **звенит на фронте** (шумный/плавающий съём), больше
не теряет событие «VCC on» — оно срабатывает, как только линия
устанавливается в HIGH, вместо того чтобы быть съеденным дребезгом
фронта. RST использует ту же схему, поэтому короткий глитч RST больше
не вызывает фантомный re-arm по тёплому сбросу.
только после того, как он непрерывно стабилен ≥ 10 мс. Это делает
включение и выключение питания *симметричными* и подавляет звон и
короткие глитчи.
- **События VCC в целом ненадёжны — лучше не отслеживать VCC.** Плавающий
или неподключённый пин съёма VCC всегда читается как HIGH (логическая
единица без нагрузки), поэтому декодер постоянно видит «питание подано»
@@ -501,20 +414,10 @@ start.bat rem запись + поток GSMTAP
- Неназначенные опциональные каналы игнорируются, даже если
`rst_detect`/`vcc_detect` включены (защита через `has_channel()`).
## Тестирование
## Разработка и тестирование
Проверено на примерах записей из upstream:
```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` в родительском рабочем
пространстве).
Декодер проверяется на примерах записей с помощью `tools/vs_reader.py`.
Фикстуры трасс хранятся локально и не входят в репозиторий.
### Проверка по SDK ридера (`tools/vs_reader.py`)
@@ -531,33 +434,12 @@ python3 tools/vs_reader.py <reader-log>.log out.pcap
`vs_reader.py` выравнивает каждый обмен из журнала ридера с APDU из записи
(побайтовое LCS-совпадение) и классифицирует остатки как proactive/CAT
(невидимые для 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` обрезаны до
окна включения питания.
### Записи холодного старта (запись начинается до включения питания)
Когда запись начинается до включения питания, декодер должен взвести охоту
за ATR, потому что RST всё ещё низкий на отсчёте 0: он инициализирует
начальные уровни VCC/RST на первом шаге (вместо того чтобы по умолчанию
считать их снятыми) и при низком RST на старте входит в `FIND START` с
очищенным ETU, поэтому переходы DATA при включении питания до ATR не могут
зафиксировать фиктивную битовую скорость. Затем он декодирует полный ATR
(`3b9f96801fc78031e073fe2117574a3382033339001e`) с 0 мусора:
Когда запись начинается до включения питания, RST всё ещё низкий на
отсчёте 0. Используйте `rst_detect=true` и `protocol=T=0`; декодер взводит
охоту за ATR по начальному уровню RST и разбирает полный ATR. Пример:
```bash
sigrok-cli -i <coldboot>.sr \
@@ -565,52 +447,17 @@ sigrok-cli -i <coldboot>.sr \
-A iso7816
```
Снятие RST (deassert), которое приходит, пока разбор ATR уже идёт, больше не
перевзводит охоту посреди чтения — оно логирует `RST deasserted (hunt/ATR
already in progress)` и не трогает разбираемый ATR (test_8/test_7
CHKSUM 18→0).
### Сценарии записи: ридер (постоянный CLK) и телефон (Clock Stop Mode)
Декодер обрабатывает две физически разные схемы съёма SIM:
- **Запись ридера / постоянный CLK** — ридер ведёт ровный CLK всю сессию.
В режиме mid-session запись декодируется в **0 мусора**
(`RESULT: OK`) относительно эталона из SDK ридера
(`tools/vs_reader.py <reader-log>.log out.pcap`).
Записи ридера с тёплыми сбросами используют fallback с синтетическим
T=0-ATR.
- **Запись телефона / остановленный CLK** — телефон гейтирует или
останавливает CLK между передачами (Clock Stop Mode), поэтому ETU не
равен стандартным 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` для телефонных записей.
Проверяйте её по SDK ридера через
`tools/vs_reader.py <reader-log>.log out.pcap`.
- **Запись телефона / гейтированный или остановленный CLK** — телефон
гейтирует или останавливает CLK между передачами (Clock Stop Mode),
поэтому ETU нельзя вывести из CLK. Запускайте с `protocol=T=0`; декодер
восстанавливает ETU из линии DATA и декодирует edge-list читателем.
Команды T=0 case 3/4 (например, `80 12`/`80 14` STK envelope) объединяются
в один APDU команда→ответ.
Рекомендуемые вызовы:
@@ -627,6 +474,28 @@ sigrok-cli -i <phone>.sr \
-A iso7816
```
### Скорости данных и ETU
Справочные значения, наблюдавшиеся на примерах записей при частоте
дискретизации 16 МГц:
| Трасса | Режим CLK | ETU (отсчёты) | CLK/ETU | Конвенция | Примечания |
|-------|----------|---------------|---------|------------|-------|
| test_8 | постоянный | ~43 | 372 (стандарт) | Direct | PC/SC ридер, ATR+PPS+APDU |
| test_7 | постоянный | ~43 | 372 (стандарт) | Direct | PC/SC ридер, тёплые сбросы |
| xiaomi | гейтированный/остановленный | ~53 | восстановлен из DATA | Direct | Телефон, середина сессии |
| samsung | гейтированный/остановленный | ~72 | 16 (F=512/D=32) | Direct | Телефон, нестандартный F/D, меню STK |
| alcor_reader | постоянный | ~53 | 16 (F=512/D=32) | Direct | PC/SC ридер, CLK 4.0 МГц на ATR -> 4.8 МГц после PPS |
Декодер автоопределяет ETU и выбирает подходящий читатель битов
(CLK-синхронный для постоянного CLK, edge-list для гейтированного/
остановленного CLK). Никакой ручной настройки не требуется, кроме
`clock_option=native` и `protocol=T=0` для телефонных записей.
Чётность — **чётная** по TS 102 221 («чётное число битов, установленных в
'1', включая бит чётности»); кадры, не прошедшие проверку, помечаются
`CHKSUM ERROR`, но всё равно декодируются.
## Лицензия
GPL-2.0+, как и upstream.