Capture (before the follow-up work starts) how to build the DNA catalog from the local datasheets: SL2S6002_SDS for the command set + memory map (63 user blocks, block 63 = counter, 48 config blocks), SL2S2602 (SLIX2) for shared opcodes, hardware-confirmed READ_CONFIG 0xC0/WRITE_CONFIG 0xC1, and docs/NTAG5_SECURITY.md for the AES commands. Marks NTAG5 done; notes the real NTAG5 datasheets (NTP5210/NTA5332) are also local. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.9 KiB
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,0bto 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 ✅, SLIX2 ✅, NTAG5 ✅, ICODE DNA (next)
- 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_decodedecodes every bit for the byte-0 hint. - Per-chip identify ✅ —
identify.name_iso15now splits the whole E0 04 family with a READ_CONFIG (0xC0) probe (addressed + retried), hardware-verified against a real NTAG5 and a real DNA: session register 0xA0 succeeds only on NTAG5 (00 01400000); DNA errors on 0xA0 (01 0F) but its config block 0x00 succeeds; SLIX2 has no READ_CONFIG (falls to the 0xBD signature step); plain SLIX answers neither. So NTAG5 → "NTAG 5", DNA → "ICODE DNA" (was mislabeled SLIX2), SLIX2/SLIX as before. Real UIDs: NTAG5E0 04 01 58, DNAE0 04 01 18(the model's NTAG5 prefix…18was copied from DNA; real NTAG5 is…58). - Catalogs —
_SLIX,_SLIX2, and_NTAG5✅ all done, dispatched bycatalog_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. - 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).
NEXT: ICODE DNA catalog (_DNA)
DNA is now identified ("ICODE DNA") but borrows _SLIX2. Build a dedicated _DNA catalog. Sourcing
(datasheets are local in the repo root — see reference_datasheets in memory):
- Command set + semantics + memory map:
SL2S6002_SDS.pdf(the DNA short data sheet). It names the commands but — being the short sheet — omits exact opcodes (defers to the NDA full sheet). - Opcodes for the shared commands:
SL2S2602.pdf(SLIX2) — DNA extends SLIX2, so EAS/AFI, password (0xB2-B5), READ_SIGNATURE (0xBD), persistent-quiet, etc. carry over. Start from_SLIX2.commandslike_NTAG5did. - DNA-specific: READ_CONFIG (0xC0) / WRITE_CONFIG (0xC1) — hardware-confirmed on the real DNA;
CID (default 0xC000); AES CHALLENGE (0x39) / AUTHENTICATE (0x35) / READBUFFER (0x3A) from
docs/NTAG5_SECURITY.md(verified protocol) — same crypto sub-protocol as the NTAG5 AES follow-up. - Memory map (for
memory.py): user = 63 blocks (0-62), block 63 = 16-bit counter; config memory = 48 blocks via READ_CONFIG (holds keys, CID, originality signature, privileges). - Route
"DNA"→_DNAincatalog_for(currently →_SLIX2). Hardware-verify against the real DNA (finicky: 16-slot inventory + addressed + retries, per project_ntag5_dna_id).
The NTAG5 AES commands (0x35/0x39/0x3A) follow-up shares this crypto work — source from NTA5332.pdf
(the real NTAG5 Link/Boost datasheet, also local) + docs/NTAG5_SECURITY.md.
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.