Files
pm3py/docs/rawcli-todo.md
michael 9e18a10274 feat(rawcli): NTAG 5 datasheet catalog (config + SRAM + pick-random-UID)
_NTAG5 = the SLIX2 command set minus STAY_QUIET_PERSISTENT (which NTAG5 rejects per the
NTP5210/NTA5332 tables) plus the NTAG5-specific NXP customs: READ_CONFIG (0xC0),
WRITE_CONFIG (0xC1, session registers 0xA0 STATUS_REG / 0xA1 CONFIG_REG), PICK_RANDOM_UID
(0xC2), and READ_SRAM (0xD2) / WRITE_SRAM (0xD3) for the Link/Boost variants. Sourced
from transponders/hf/iso15693/nxp/ntag5_*, routed by catalog_for, verified live.

Not yet wired: auto-identify of NTAG5. NTAG5 and ICODE DNA share UID E0 04 01 18, so
they can't be told apart by UID — routing needs a functional probe (READ_CONFIG of a
session register), which needs a brief NTAG5 tap to nail without risking DNA
misclassification. AES/ISO-29167-10 commands (0x35/0x39/0x3A) noted as a follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 13:14:33 -07:00

80 lines
5.3 KiB
Markdown

# rawcli — catalog & memory-hinting roadmap
The MVP is a list of **named transponders**, each surfaced through the **same UX**: a command
catalog + a datasheet memory map, both offered as **autocomplete suggestions in the completion
dropdown** — never on the bottom bar, never in command output.
## The UX contract (applies to every transponder)
- Completion dropdown offers: command names (by letter → `READ(`), opcodes (by hex/binary value →
raw byte inserted, command as the label), and page/block landmarks with datasheet roles.
- **Must work in both hex AND binary entry modes**, rendering in the active base.
- Function-call args are base-10 (`READ(4)`); raw bytes are hex, `0b` to intermix binary.
## FIXED — raw byte-line autocomplete now fires in hex AND binary
Root cause: `entry._digit` applied each keystroke as `buf.document = Document(...)`, which resets
prompt_toolkit's `complete_state` and never re-fires completion — so the live menu never appeared
during raw byte entry. This hit **both** hex and binary (the earlier "hex works, binary doesn't"
was inaccurate; only command-name completion worked, because that path already used `insert_text`).
Fixed by appending the per-keystroke delta via `buf.insert_text` instead — `type_digit` only ever
appends (optionally after an auto-space) or drops, so the change is always a pure suffix, and
`insert_text` triggers completion exactly like an ordinary keystroke. Verified by driving the real
key handler: the menu now populates on every digit in both modes. Regression:
`TestKeyBindings::test_digit_binding_fires_completion_trigger_for_raw_bytes`.
The Ctrl-t / Ctrl-_ toggle correctly flips the breadcrumb `0x` <-> `0b` and requests a redraw
(verified, guarded by `test_toggle_updates_breadcrumb_prefix`). An end-to-end live-session test
(`TestRawcliLiveSession`) drives the real PromptSession via a pipe input. A human eyeball of the
rendered dropdown on a real terminal is the only thing left unautomated.
## Priority 1 — MIFARE Classic (do this first)
- **Identify**: distinguish 1K (SAK 0x08) / 4K (0x18) / Mini (0x09); today only named, no map.
- **Memory map** (block → role), mirroring the NTAG page map:
- Block 0 = manufacturer block: UID + BCC + SAK + ATQA + manufacturer data.
- Sector trailer (block 3,7,…,63 on 1K; last block of each sector on 4K): **Key A (0-5),
access bits (6-8) + GPB (9), Key B (10-15)** — the access bits are the bit-level detail.
- Other blocks = data block (with sector number).
- 4K: sectors 0-31 are 4 blocks; sectors 32-39 are 16 blocks each.
- **Catalog**: READ/WRITE/HALT exist; note that reads/writes need prior AUTH (Key A/B) — the
authenticate step is the reader's job before these.
- Autocomplete must work in hex + binary (see the bug above).
## After MFC — 15693 vicinity chips: ICODE SLIX ✅, ICODE SLIX2 ✅, NTAG5 (next)
1. **15693 header builder** ✅ — `iso15_frame()` (flags + command + NXP mfg 0x04), shared by all
15693 catalogs. The **full request-flags byte** is settable: sub-carrier (0x01), data-rate,
inventory, protocol-ext (0x08), and the mode-dependent bits 5-6 (Select/Address vs AFI byte +
Nb_slots 1/16), plus option. `iso15_flags_decode` decodes every bit for the byte-0 hint.
2. **Per-chip identify**`identify.name_iso15` distinguishes SLIX vs SLIX2 (READ_SIGNATURE 0xBD
probe). **NTAG5 and ICODE DNA both carry UID `E0 04 01 18`** (identical type indicator — model
comment confirms), so they can't be told apart by UID. Routing NTAG5 needs a **functional
probe** (e.g. READ_CONFIG 0xC0 of session register 0xA0/0xA1 — NTAG5 has them, DNA doesn't).
⚠ HARDWARE-DEPENDENT: needs a brief NTAG5 tap to capture the discriminating response (and ideally
a DNA capture to confirm it differs) before wiring — otherwise it risks misclassifying DNA.
3. **Catalogs**`_SLIX`, `_SLIX2`, and **`_NTAG5`** ✅ all done, dispatched by `catalog_for`,
verified live. `_NTAG5` = SLIX2 minus STAY_QUIET_PERSISTENT (NTAG5 rejects it) + READ_CONFIG
(0xC0) / WRITE_CONFIG (0xC1) / PICK_RANDOM_UID (0xC2) / READ_SRAM (0xD2) / WRITE_SRAM (0xD3).
**Follow-up:** the AES / ISO 29167-10 commands AUTHENTICATE (0x35) / CHALLENGE (0x39) / READBUFFER
(0x3A) for Link/Boost (AES-capable) variants — a crypto sub-protocol with its own param format.
4. Autocomplete UX ✅ (hex + binary, command names + opcode-by-value; the byte-line completion bug
is fixed).
`INVENTORY_READ` (0xA0) / `FAST_INVENTORY_READ` (0xA1) ✅ — in `_SLIX` (inherited by `_SLIX2`),
**full request body** via `_inv_read_frame`: `[AFI] | mask_len(bits) | mask value | first_block |
count-1`, with the inventory flags set by `iso15_frame(inventory=…, afi=…)`. Mask-less (default),
mask-based selective anticollision, and AFI filter all supported. **15693 is now datasheet-complete
end to end** (flags byte + both SLIX/SLIX2 command sets + inventory-read body).
**Hardware verify pending:** SLIX2 catalog was verified only against unit tests + a live-session
drive (no SLIX2 tag on the reader). Confirm on a real SLIX2 when one is available.
## Also queued
- **T5577 config block (block 0)** bitfield decode (modulation, bit-rate, block count, PWD/AOR) —
currently just "config block".
- NTAG I2C plus (model exists, identify names it) — catalog + map.
See [[project_rawcli_mvp]] in memory for the named-transponder scope.