46 KiB
English version: README.md
sigrok_iso7816_stream
📢 Новости и обновления проекта: Сайт · Telegram-канал
Форк svenso/sigrok_iso7816 с живым GSMTAP-UDP-стримингом: дешёвый логический анализатор FX2 (клон Saleae) ведёт себя как сниффер SIMtrace2:
SIM-карта ⇄ ридер (пассивный съём с контактов)
→ логический анализатор FX2 (fx2lafw, 8 каналов, до 24 МГц)
→ sigrok-cli + декодер iso7816
→ GSMTAP UDP :4729 → [SIMtrace Analyser](https://github.com/anttro/simtrace-analyser) / Wireshark
SIMtrace Analyser —
рекомендуемый инструмент для визуализации живых трасс и просмотра
сохранённых записей; он также умеет импортировать и экспортировать
GSMTAP pcap-файлы (включая PCAP, который этот декодер пишет через опцию
pcap_file=<path>).
Съём на практике
Компоненты, использованные в сборке
Стенд снимает сессию SIM-карты телефона
Стенд снимает сессию картридера
Съём коротким кабелем — меньше площадь контура и артефактов фронта
Детали подключения короткого кабеля
Короткий кабель с внешними подтягивающими резисторами — 10 кОм к GND на VCC (тянет вниз, когда питания нет), 47 кОм к VCC на DATA (быстрее фронт вверх)
Что добавлено поверх upstream
| Возможность | Описание |
|---|---|
| Живой поток GSMTAP | Каждое декодированное событие отправляется как GSMTAP-SIM UDP-пакет (включено по умолчанию, повторяет поведение simtrace2-sniff) |
| Правильные sub_types | ATR=0x01 и PPS=0x02 теперь корректно помечаются в PCAP (в upstream всё писалось как APDU=0x00) |
| 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 МГц |
Опции декодера
| Опция | По умолчанию | Описание |
|---|---|---|
clock_option |
native |
native, detect, sample_as_clock (см. FAQ upstream) |
protocol |
auto |
auto, T=0, T=1 |
gsmtap_enable |
true |
Живой GSMTAP UDP-стриминг |
gsmtap_host |
127.0.0.1 |
Хост назначения GSMTAP |
gsmtap_port |
4729 |
Порт назначения GSMTAP |
pcap_file |
(пусто) | Писать PCAP в этот файл вдобавок к бинарному выводу |
rst_detect |
false |
Отслеживать события пина RST (требуется назначенный канал rst) |
vcc_detect |
false |
Отслеживать события пина VCC (требуется назначенный канал vcc) |
Каналы: clk, data (обязательные); rst, vcc (опциональные —
назначайте только если соответствующий провод физически подключён).
События GSMTAP
Заголовок GSMTAP: версия 2, тип SIM (0x04), UDP-порт 4729.
| sub_type | Имя | Полезная нагрузка |
|---|---|---|
| 0x00 | APDU | сырые байты пакета T=0/T=1 |
| 0x01 | ATR | сырые байты ATR |
| 0x02 | Запрос PPS | сырые байты запроса PPS |
| 0x03 | Ответ PPS | сырые байты ответа PPS |
| 0x10 | Событие RST (кастомное) | [direction, level, flags, clk_hz_be32] — частота CLK добавляется, когда известна |
| 0x11 | Событие VCC (кастомное) | [direction, level, 0x00] |
Семантика байтов полезной нагрузки:
- RST:
direction1 = сброс asserted (высокий→низкий), 0 = deasserted (низкий→высокий);level= уровень линии после перехода. - VCC:
direction1 = питание подано (низкий→высокий), 0 = снято (высокий→низкий);level= уровень линии после перехода.
0x00–0x03 совпадают с gsmtap.h из libosmocore: стандартные значения и полезные нагрузки (запрос и ответ PPS отправляются отдельными пакетами). 0x10/0x11 — кастомные расширения, не определённые в gsmtap.h из libosmocore.
События RST несут измеренную частоту CLK, когда она известна: тогда
устанавливается бит 0 байта flags, а следом идёт частота как big-endian
uint32 в герцах (полезная нагрузка 7 байт). Пока частота не измерена,
нагрузка остаётся 3 байта, поэтому потребители, читающие только первые два
байта, не затрагиваются. Вместе с F/D, согласованными в ATR/PPS, скорость
передачи данных равна clk_hz × D / F бит/с.
Расширения заголовка: флаги вроде GSMTAP_FLAG_BAD_FCS пишутся в байт
res заголовка, который официальный gsmtap.h помечает как зарезервированный
(RFU). Это собственное расширение данного декодера (upstream simtrace2-sniff
никогда не заполняет res); семантика флагов повторяет флаги данных (data
flags) USB-протокола simtrace2 и не является частью спецификации libosmocore.
Использование
Быстрый старт (после установки — скачанный архив или клон репозитория; см. «Установка» ниже):
./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 МГц. Переопределяются аргументами:
./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 при длительной высокой частоте дискретизации.
./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:
# Минимум: только 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:
sigrok_iso7816_stream-<version>.tar.gz— Linuxsigrok_iso7816_stream-<version>.zip— Windows
К каждому релизу прилагается SHA256SUMS — в нём оба архива.
Положите файл рядом со скачанным архивом и проверьте:
sha256sum -c --ignore-missing SHA256SUMS # GNU coreutils (Linux)
В Windows выполните certutil -hashfile sigrok_iso7816_stream-<version>.zip SHA256
и сравните вывод со строкой .zip в SHA256SUMS.
Linux (скачать)
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 (скачать)
Предварительные требования:
- sigrok-cli — установщик для Windows (0.7.2 x86_64) с
sigrok.org/wiki/Downloads —
протестированная версия. На этой же странице публикуются ночные сборки
для Windows; они могут менять синтаксис sigrok-cli или API декодеров,
поэтому поддерживаемой остаётся версия из релизного установщика 0.7.2. Если sigrok-cli не запускается с ошибкой
0xc0150002, установите Visual C++ 2010 Redistributable (msvcr100.dllтребуется встроенному Python-рантайму). - Прошивка fx2lafw поставляется вместе с установщиком — отдельно скачивать не нужно.
Настройка драйвера (донглам FX2 нужен WinUSB, вендорский драйвер не подойдёт):
- Запустите Zadig, который лежит внутри каталога установки sigrok-cli (также доступен из меню «Пуск»). Выберите устройство FX2 в выпадающем списке и установите драйвер WinUSB.
- После загрузки прошивки устройство переподключается с другим VID/PID — если оно всё ещё не находится, запустите Zadig второй раз для переподключившегося устройства.
- Windows привязывает драйверы к USB-порту, когда нет серийного номера: перенос донгла в другой порт может потребовать повторить Zadig.
Затем распакуйте архив .zip (в Проводнике: правой кнопкой → «Извлечь все»)
и запустите в распакованном каталоге:
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 (из исходников)
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 (скачать) выше.
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 тоже работает:
start.bat --clk D1 --data D6
start.bat --help
Запись работает так же, как в Linux:
start.bat rem запись + поток GSMTAP
Примечание: bat-файлы требуют переводов строк CRLF; репозиторий следит за
этим через .gitattributes, поэтому свежий клон в Windows уже корректен
(zip-архив релиза содержит те же файлы с CRLF).
Заметки и ограничения по детектированию RST/VCC
- События детектируются асинхронно до первого ATR (включение питания / снятие сброса фиксируются, как только уровень стабилизируется) и на границах пакетов между T=0/T=1 в дальнейшем.
- Фронты, происходящие целиком внутри передачи пакета, наблюдаются как итоговое изменение уровня на следующей границе; короткие импульсы внутри пакета могут быть пропущены.
- VCC — только цифровой: декодер видит «питание есть/нет», но никогда не класс напряжения (1.8/3/5 В).
- RST и VCC используют гистерезис стабильности уровня в 10 мс (масштабируется от частоты дискретизации): новый уровень сообщается только после того, как он непрерывно стабилен ≥ 10 мс — либо потому, что он держится так долго, либо потому, что он закончился, продержавшись столько. Это делает включение и выключение питания симметричными: линия VCC, которая звенит на фронте (шумный/плавающий съём), больше не теряет событие «VCC on» — оно срабатывает, как только линия устанавливается в HIGH, вместо того чтобы быть съеденным дребезгом фронта. RST использует ту же схему, поэтому короткий глитч RST больше не вызывает фантомный re-arm по тёплому сбросу.
- События VCC в целом ненадёжны — лучше не отслеживать VCC. Плавающий
или неподключённый пин съёма VCC всегда читается как HIGH (логическая
единица без нагрузки), поэтому декодер постоянно видит «питание подано»
и выдаёт ложные события питания при каждом дребезге. Если ваш съём не
берёт VCC с чистого нагруженного источника, лучше оставить канал
vccненазначенным (не передавать--vcc) и держатьvcc_detect=false; отслеживания RST обычно достаточно, чтобы видеть сбросы. Включайте отслеживание VCC только на съёме с надёжным измерением VCC (и надёжным GND — см. заметки о подключении). - Неназначенные опциональные каналы игнорируются, даже если
rst_detect/vcc_detectвключены (защита черезhas_channel()).
Тестирование
Проверено на примерах записей из upstream:
# 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)
На контролируемом стенде (PCSC-ридер под управлением софта) эталонный журнал APDU из SDK ридера можно сравнить с декодированным PCAP:
sigrok-cli -i <trace>.sr \
-P iso7816:clk=D5:data=D0:rst=D4:vcc=D2:clock_option=native:rst_detect=true:vcc_detect=true:gsmtap_enable=false:pcap_file=out.pcap \
-A iso7816
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 мусора:
sigrok-cli -i <coldboot>.sr \
-P iso7816:clk=CLK:data=DATA:rst=RST:vcc=VCC:clock_option=native:protocol=T=0:rst_detect=true:vcc_detect=true:gsmtap_enable=false:pcap_file=out.pcap \
-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 14STK 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 для телефонных записей.
Рекомендуемые вызовы:
# Запись ридера (контролируемый стенд, CLK всегда работает)
sigrok-cli -i <trace>.sr \
-P iso7816:clk=CLK:data=DATA:rst=RST:vcc=VCC:clock_option=native:rst_detect=true:vcc_detect=true:gsmtap_enable=false:pcap_file=out.pcap \
-A iso7816
python3 tools/vs_reader.py <reader-log>.log out.pcap
# Запись телефона (середина сессии, гейтированный/остановленный CLK)
sigrok-cli -i <phone>.sr \
-P iso7816:clk=CLK:data=DATA:rst=RST:clock_option=native:rst_detect=true:vcc_detect=false:protocol=T=0:gsmtap_enable=false:pcap_file=out.pcap \
-A iso7816
Лицензия
GPL-2.0+, как и upstream.


