User Tools

Site Tools


cvend

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
cvend [2026-05-03 20:18 UTC (4 weeks ago)] – Further document 0xd5 read response haylincvend [2026-05-24 10:59 UTC (6 days ago)] (current) – 0xd0 EMV doof
Line 34: Line 34:
 | 0x07 | <- | Heartbeat| sent periodically by reader | | 0x07 | <- | Heartbeat| sent periodically by reader |
 | 0x0f | <- | Startup | sent by reader after startup, approx 1 minute after power on, e.g. "\x00" | | 0x0f | <- | Startup | sent by reader after startup, approx 1 minute after power on, e.g. "\x00" |
-| 0x10 | -> | Reset | Seems to be unimplemented | +| 0x10 | -> | Reset | first byte selects subcommand (2 = restart application, 3 = reboot, 4 = poweroff, 33-36 = reset sam 1-4, others = ''Error: Reset Code not implemented yet. [IppBaseTelegram.cpp:157]'') | 
-| 0x11 | <| ResetReply | Always seems to be ''Error: Reset Code not implemented yet. [IppBaseTelegram.cpp:157]'' |+| 0x11 | <- | ResetReply | e.g. "\x00\x00" |
 | 0x20 | -> | LEDs | sets LED status, u32 bitmap; the only two externally visible LEDs on the PM3 are "\x00\x00\x00\x40" and "\x00\x00\x00\x80" | | 0x20 | -> | LEDs | sets LED status, u32 bitmap; the only two externally visible LEDs on the PM3 are "\x00\x00\x00\x40" and "\x00\x00\x00\x80" |
 | 0x22 | -> | Buzzer | makes the cvend beep; u16 frequency, u16 duration.  e.g. "\x06\x00\x01\x00" | | 0x22 | -> | Buzzer | makes the cvend beep; u16 frequency, u16 duration.  e.g. "\x06\x00\x01\x00" |
Line 67: Line 67:
 | 0xbc | -> | DESFireCommand | sends desfire command, documented in {{ 0:m075031_desfire.pdf}} | | 0xbc | -> | DESFireCommand | sends desfire command, documented in {{ 0:m075031_desfire.pdf}} |
 | 0xbd | <- | DESFireCommandReply | response to command, documented above | | 0xbd | <- | DESFireCommandReply | response to command, documented above |
-| 0xbe | <- | UnhandledCard | sent by reader when a card is presented that is not supported by any enabled ProxCardFunction, containing UID, historical bytes, and other data |+| 0xbe | <- | UnhandledCard | sent by reader when a card is presented that is not supported by any enabled ProxCardFunction, containing UID, historical bytes, and other data. First two bytes seem to be card type |
 | 0xce | -> | | //unknown, registered in IppHandling::IppHandling()// | | 0xce | -> | | //unknown, registered in IppHandling::IppHandling()// |
-| 0xd0 | -> | EMV | first byte selects subcommand (0 = load config, 1 = preprocess, 2 = toggle polling) |+| 0xd0 | -> | EMV | first byte selects subcommand (0 = load config, 1 = preprocess, 2 = toggle polling)\\ * load config followed by null terminated filename, which is read and passed to fetfpd ''emvco_ep_configure''\\ * preprocess following bytes passed to fetfpd ''emvco_ep_preprocess''\\ * toggle polling following byte (0 = start polling, 1 = stop polling) |
 | 0xd1 | <- | EMVStatus | sent by reader after startup and certain nfc state changes, format and semantics not yet understood | | 0xd1 | <- | EMVStatus | sent by reader after startup and certain nfc state changes, format and semantics not yet understood |
-| 0xd4 | -> | | //unknown, registered in ProxCardUltralightC::ProxCardUltralightC(RFIDReader&)// +| 0xd4 | -> | UltralightCommand Sends a subcommand to the UltralightC/NTAG card in the field. First byte is subcmd. See table below. 
-| 0xd5 | <- | UltralightRead Two sub-forms: card present: byte = 0x00byte 1 0x00 (unknown), bytes 2+ = UID (7 bytes for cascade UIDs e.g04 21 B9 01 10 04 03); card removed: byte 0 = 0x01, byte 1 = 0x00 |+| 0xd5 | <- | UltralightReply Unsolicited card event (''replyTo''0)or reply to a 0xD4 command (''replyTo'' seq of the 0xD4). See tables below. |
 | 0xe4 | -> | ProxCardFunction | first 2 bytes specify function (4=VdvKa, 5=MifareClassic, 6=Iso, 7=Desfire, 8=Girogo, 9=Itso, 10=UltralightC), next byte must be 1, next byte (0=disable, 1=enable)\\ ''00070101'' sent by PM3 to enable DESFire reading at startup | | 0xe4 | -> | ProxCardFunction | first 2 bytes specify function (4=VdvKa, 5=MifareClassic, 6=Iso, 7=Desfire, 8=Girogo, 9=Itso, 10=UltralightC), next byte must be 1, next byte (0=disable, 1=enable)\\ ''00070101'' sent by PM3 to enable DESFire reading at startup |
-| 0xe5 | <- | ProxCardFunctionReply | |+| 0xe5 | <- | ProxCardFunctionReply | Returns 4 byte payload: 0x00, the function number (as above), 0x00, 0x00 |
 | 0xe6 | -> | | //unknown, registered in GirogoIppHandler::GirogoIppHandler(RFIDReader&, ProxCardGirogo*)// | | 0xe6 | -> | | //unknown, registered in GirogoIppHandler::GirogoIppHandler(RFIDReader&, ProxCardGirogo*)// |
 | 0xe8 | -> | SecurityServices | first byte selects subcommand (0=GetVersionOfKey, 1=RemoveX509Cert, 2=RemoveKeyBlock, 3=ImportX509Cert, 4=ExportX509Cert, 5=ImportKeyBlock, 6=ExportKeyBlock, 7=GenerateKSKPair), remaining bytes unknown | | 0xe8 | -> | SecurityServices | first byte selects subcommand (0=GetVersionOfKey, 1=RemoveX509Cert, 2=RemoveKeyBlock, 3=ImportX509Cert, 4=ExportX509Cert, 5=ImportKeyBlock, 6=ExportKeyBlock, 7=GenerateKSKPair), remaining bytes unknown |
Line 83: Line 83:
 -> - Host to Reader\\ -> - Host to Reader\\
 <- - Reader to Host <- - Reader to Host
 +
 +==== 0xD5 UltralightReply — unsolicited card events ====
 +
 +''replyTo'' = 0 for both forms.
 +
 +^ byte 0 ^ meaning ^ payload ^
 +| 0x00 | Card entered field | byte 1 = 0x00 (purpose unknown); bytes 2–8 = 7-byte UID (cascade / double UID format, e.g. ''04 21 B9 01 10 04 03'' for NTAG 215) |
 +| 0x01 | Card left field    | byte 1 = 0x00 |
 +
 +==== 0xD4 UltralightCommand / 0xD5 UltralightReply — subcommands ====
 +
 +Host sends 0xD4 with ''msgData[0]'' = subcmd. Reader replies with 0xD5 where ''replyTo'' = seq of the 0xD4.
 +
 +Reply format: ''[subcmd_echo, status, payload...]''
 +
 +Status codes: ''0x00'' = success, ''0x01'' = operation error (e.g. no card in field), ''0x02'' = invalid parameters.
 +
 +^ subcmd ^ name ^ request payload (after subcmd byte) ^ reply payload (after subcmd + status) ^
 +| 0x02 | Read | ''[start_page: u8, num_pages: u8]'' — exactly 3 bytes total | page data, 4 bytes per page (e.g. 135 pages × 4 = 540 bytes for NTAG 215) |
 +| 0x03 | Write | ''[page_addr: u8, data: 4 bytes]'' — 5 bytes total | //empty// |
 +| 0x04 | Authenticate (raw key) | ''[key: 16 bytes]'' — 17 bytes total | //empty// |
 +| 0x05 | Authenticate (key index) | ''[key_idx: BE u16]'' — 3 bytes total | //empty// |
 +| 0x06 | Authenticate (index + key) | ''[key_idx: BE u16, key: 16 bytes]'' — 19 bytes total | //empty// |
 +| 0x07 | Abort | //none// — exactly 1 byte total | //empty// |
 +| 0x00–0x01, 0x08+ | (invalid) | — | no reply frame; device logs "Unknown subcommand" |
 +
 +Notes:
 +  * Subcmds 0x02–0x07 are registered in ''ProxCardUltralightC::ProxCardUltralightC(RFIDReader&)'' (confirmed by disassembly of ''feig'' ARM binary from V0200.C72 firmware).
 +  * If no card is in the field, the device echoes ''[subcmd, 0x01]'' immediately without attempting the operation.
 +  * To read all pages of an NTAG 215: send subcmd 0x02 with ''start_page=0x00'', ''num_pages=135''.
  
 ==== Sample reader flow ==== ==== Sample reader flow ====
Line 147: Line 177:
  
 * Host only sends two types of messages after initialization - both of type 0xBC. One is length 1 and the body is always 0x60 (+ negated CRC 2A714F60), the other is of length 4 and the body is always 5A2BC3F9 (+ negated-CRC 11A8A56A) * Host only sends two types of messages after initialization - both of type 0xBC. One is length 1 and the body is always 0x60 (+ negated CRC 2A714F60), the other is of length 4 and the body is always 5A2BC3F9 (+ negated-CRC 11A8A56A)
 +
cvend.1777839520.txt.gz · Last modified: by haylin