diff --git a/README.md b/README.md index 33cfd6f..12b59e3 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,8 @@ GSMTAP into this analyser. one GSMTAP source of several that the analyser accepts (see also [sigrok_iso7816_stream](https://github.com/anttro/sigrok_iso7816_stream)). - **PWA** ([`frontend/`](frontend/)) — trace browser with decoded APDU, - SIM Toolkit, SMS and SCP80 OTA detail; sessions, PCAP import, EN/RU UI. + SIM Toolkit, SMS and SCP80 OTA detail; sessions, PCAP and COMPRION trace + import, EN/RU UI. ## Features @@ -61,6 +62,7 @@ GSMTAP into this analyser. - Trace view with Map/List modes — proactive, TERMINAL RESPONSE, ENVELOPE and AUTH commands get distinctive styling in map view - Sessions with deep links (`#session=N`), PCAP import (`.pcap/.pcapng/.cap`), + COMPRION trace import (the Device Manager *ISO Protocol Layer* text export), search and type filtering - Installable PWA, dark theme, English/Russian UI @@ -141,6 +143,49 @@ on mis-framed exchanges) are surfaced as a flagged/desynced entry in the capture timeline, so such artefacts are easy to spot when reviewing a capture rather than silently altering the decode. +### COMPRION text export import + +The **Import COMPRION trace** button accepts the tab-separated **ISO Protocol +Layer** export of COMPRION's Device Manager — the byte-accurate protocol view +(ATR, PPS, APDUs with their return codes). The *ISO Application Layer* export +carries no raw response bytes and is not needed; selecting it answers with a +pointer to the Protocol Layer file (the same check runs in the PWA before the +upload and on the server for API callers). + +Exchanges are re-encoded into the same wire-shaped TPDUs a GSMTAP capture +carries (a case-4 exchange becomes the command, a `61 xx` status word and a +GET RESPONSE with the response data and the final SW), so command/response +pairing, FCP/file decoding and the filters behave exactly as for a live +capture. + +**Exact timestamps:** the import dialog asks for the *ISO Protocol Layer* +export (required) and, optionally, the matching *ISO Application Layer* +export — two separate pickers, both file names visible, and an error stays in +the dialog until it is fixed or cancelled. With both files the Application +Layer's per-exchange wall-clock times become the trace's timeline — the +session window and the inter-APDU gaps are then exact; without it the +timeline is the estimate described below. Before anything is imported the +two files are verified to belong to the same session (`Session Name`, +falling back to `Working directory`; the export timestamps of the two layers +differ and are not compared) and their exchange counts must align (the two +exports must cover the same set of exchanges) — a mismatch refuses the import +instead of mixing sessions. The ATR and the PPS exchange have no Application +Layer blocks, so they carry the timestamp of the preceding exchange. + +**Protocol Layer alone:** the `Delay` column measures only card/line activity +— host pauses between APDU bursts are absent — so the timeline keeps the +message order and the short-term gaps but is much shorter than the real +session. Its unit comes from an assumed 3.8 MHz interface clock (`CLK_HZ` in +`simtrace_analyser/comprion.py`), which is a scale, not a measurement: the +export carries no CLK, and the import deliberately does not invent one (the +ATR shows the F/D the file states, with no data-rate/ETU annotation, unlike +a capture from the sigrok-iso7816-stream sniffer). The session's wall-clock +window is taken from the file's `Session Name` timestamp when it carries +one. + +Exchanges larger than 255 bytes (extended-length APDUs) cannot be represented +in the stored wire shape and are skipped with a note in the import report. + Server options: ``` diff --git a/README_RUS.md b/README_RUS.md index 64646a8..54a0314 100644 --- a/README_RUS.md +++ b/README_RUS.md @@ -24,7 +24,8 @@ SIM/UICC из UDP-потока GSMTAP (или импортирует файлы анализатор (см. также [sigrok_iso7816_stream](https://github.com/anttro/sigrok_iso7816_stream)). - **PWA** ([`frontend/`](frontend/)) — окно трассировки с декодированными - APDU, SIM Toolkit, SMS и SCP80 OTA; сессии, импорт PCAP, интерфейс EN/RU. + APDU, SIM Toolkit, SMS и SCP80 OTA; сессии, импорт PCAP и трасс COMPRION, + интерфейс EN/RU. ## Возможности @@ -64,7 +65,8 @@ SIM/UICC из UDP-потока GSMTAP (или импортирует файлы - Окно трассировки с режимами «Карта»/«Список» — proactive, TERMINAL RESPONSE, ENVELOPE и AUTH-команды выделяются в режиме карты - Сессии с прямыми ссылками (`#session=N`), импорт PCAP - (`.pcap/.pcapng/.cap`), поиск и фильтрация по типу + (`.pcap/.pcapng/.cap`), импорт трасс COMPRION (текстовый экспорт + «ISO Protocol Layer» из Device Manager), поиск и фильтрация по типу - Устанавливаемая PWA, тёмная тема, интерфейс на английском/русском ## Требования @@ -147,6 +149,48 @@ RST несёт измеренную частоту CLK (декодер v1.9.0+, помеченная/десинхронизированная запись, чтобы такие артефакты было легко заметить при разборе, а не молча искажали декодирование. +### Импорт текстового экспорта COMPRION + +Кнопка **Import COMPRION trace** принимает экспорт **ISO Protocol Layer** +(табулированный текст) из COMPRION Device Manager — байтовое представление +протокола (ATR, PPS, APDU с кодами возврата). Экспорт *ISO Application +Layer* не содержит необработанных байтов ответов и не нужен; при его выборе +выводится указание на файл Protocol Layer (та же проверка выполняется в PWA +до загрузки и на сервере — для вызовов API). + +Обмены перекодируются в такие же «проводные» TPDU, какие несёт захват +GSMTAP (обмен case 4 превращается в команду, статусное слово `61 xx` и GET +RESPONSE с данными ответа и итоговым SW), поэтому связывание +команда/ответ, декодирование FCP и файлов и фильтры работают так же, как +для живого захвата. + +**Точные метки времени:** диалог импорта запрашивает экспорт *ISO Protocol +Layer* (обязательный) и, при наличии, соответствующий экспорт *ISO +Application Layer* — два отдельных поля выбора, имена выбранных файлов +видны, а ошибка остаётся в диалоге до исправления или отмены. С обоими +файлами метки времени Application Layer по обменам становятся таймлайном +трассы: окно сессии и интервалы между APDU точные; без него таймлайн — +оценка, описанная ниже. Перед импортом проверяется, что файлы относятся к +одной сессии (`Session Name`, при отсутствии — `Working directory`; метки +времени экспорта у слоёв различаются и не сравниваются) и что число обменов +совпадает (экспорты должны покрывать один и тот же набор обменов) — при +несовпадении импорт отклоняется, а не смешивает сессии. У ATR и обмена PPS +блоков в Application Layer нет, поэтому они получают метку времени +предыдущего обмена. + +**Только Protocol Layer:** столбец `Delay` измеряет лишь активность +карты/линии — паузы хоста между сериями APDU в него не входят — поэтому +таймлайн сохраняет порядок сообщений и короткие интервалы, но заметно +короче реальной сессии. Его единица измерения задаётся предполагаемой +тактовой частотой 3,8 МГц (`CLK_HZ` в `simtrace_analyser/comprion.py`) — +это масштаб, а не измерение: в экспорте нет CLK, и импорт намеренно его не +выдумывает (ATR показывает F/D из файла, без аннотации скорости/ETU, в +отличие от захвата сниффером sigrok-iso7816-stream). Окно настенных часов +сессии берётся из метки времени `Session Name` в файле, если она там есть. + +Обмены длиннее 255 байт (APDU с расширенной длиной) невозможно представить +в хранимом «проводном» виде — они пропускаются с пометкой в отчёте импорта. + Параметры сервера: ``` diff --git a/frontend/index.html b/frontend/index.html index 27d059d..007307c 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -278,6 +278,18 @@ body { font: 14px/1.5 system-ui, sans-serif; background: var(--bg); color: var(- .modal-buttons button { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; } .modal-buttons .confirm { background: var(--accent); color: #fff; } .modal-buttons .cancel { background: var(--bg-input); color: var(--text-faint); } +.modal-buttons button:disabled { opacity: 0.5; cursor: default; } + +/* COMPRION import dialog */ +.comprion-modal { max-width: 560px; } +.comprion-slot { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; } +.comprion-slot label { flex: 0 0 200px; font-size: 13px; color: var(--text-muted); } +.comprion-slot button { padding: 6px 10px; border: none; border-radius: 4px; cursor: pointer; background: var(--bg-input); color: var(--text); flex: 0 0 auto; } +.comprion-slot button:disabled { opacity: 0.5; cursor: default; } +.comprion-slot .file-name { font-size: 12px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; } +.comprion-hint { font-size: 12px; line-height: 1.45; margin: 10px 0 0; } +.comprion-error { font-size: 12px; line-height: 1.45; color: var(--error); margin-top: 8px; } +.comprion-error:empty { display: none; } /* Scrollbar */ ::-webkit-scrollbar { width: 6px; } @@ -342,6 +354,7 @@ body { font: 14px/1.5 system-ui, sans-serif; background: var(--bg); color: var(- +
@@ -406,6 +419,32 @@ body { font: 14px/1.5 system-ui, sans-serif; background: var(--bg); color: var(-
+ + +