doc/md/em4x70/arbitrary_lf_em_commands.md
Goals:
lf em commands and responsesThis is documenting the actual commands used by existing code. Phases include:
The goal is to improve logging and debugging, and allow easily testing new LF commands.
Only six command sequences currently used:
#define EM4X70_COMMAND_ID 0x01 #define EM4X70_COMMAND_UM1 0x02 #define EM4X70_COMMAND_AUTH 0x03 #define EM4X70_COMMAND_PIN 0x04 #define EM4X70_COMMAND_WRITE 0x05 #define EM4X70_COMMAND_UM2 0x07
Wait for LIW (listen window), and start transmission at next LIW:
| source | bits | comment |
|---|---|---|
| tag | LIW | listen window sync |
| reader | 0b00 | RM |
| reader | 0b001 | CMD |
| reader | 0b1 | command parity bit |
| tag | HEADER | HEADER (0b1111'1111'1111'0000) |
| tag | 32-bits | ID (D31..D0) |
| tag | LIW | tag reverts to be ready for next command |
| source | bits | comment |
|---|---|---|
| tag | LIW | listen window |
| reader | 0b00 | RM |
| reader | 0b010 | CMD |
| reader | 0b1 | command parity bit |
| tag | 16-bits | HEADER |
| tag | 32-bits | UM1 data |
| tag | LIW | tag reverts to be ready for next command |
| source | bits | comment |
|---|---|---|
| tag | LIW | listen window |
| reader | 0b00 | RM |
| reader | 0b111 | CMD |
| reader | 0b1 | command parity bit |
| tag | 16-bits | HEADER |
| tag | 64-bits | UM2 data |
| tag | LIW | tag reverts to be ready for next command |
| source | bits | comment |
|---|---|---|
| tag | LIW | listen window |
| reader | 0b00 | RM |
| reader | 0b011 | CMD |
| reader | 0b0 | command parity bit |
| reader | 56-bits | RN |
| reader | 7-bits | Tdiv == 0b0000000 (always zero) |
| reader | 28-bits | f(RN) |
| tag | 16-bits | HEADER |
| tag | 20-bits | g(RN) |
| tag | LIW | tag reverts to be ready for next command |
| source | bits | comment |
|---|---|---|
| tag | LIW | listen window |
| reader | 0b00 | RM |
| reader | 0b101 | CMD |
| reader | 0b0 | command parity bit |
| reader | 4-bits | address/block to write |
| reader | 1-bit | address/block parity bit |
| reader | 25-bits | 5x5 data w/ row and column parity |
| tag | ACK | Wait (TWA) for ACK ... time to wait before searching for ACK |
| tag | ACK | Wait (WEE) for ACK ... time to wait before searching for ACK |
| tag | LIW | tag reverts to be ready for next command |
| source | bits | comment |
|---|---|---|
| tag | LIW | listen window |
| reader | 0b00 | RM |
| reader | 0b100 | CMD |
| reader | 0b1 | command parity bit |
| reader | 32-bits | ID of the tag |
| reader | 32-bits | PIN |
| tag | ACK | Wait (TWALB) for ACK ... time to wait before searching for ACK |
| tag | HEADER | DELAYED (TWEE) header ... time to wait before searching for header |
| tag | 32-bits | ID of the tag |
| tag | LIW | tag reverts to be ready for next command |
Possible items to abstract:
Special handling required for:
HEADER --> 12-bits of zero, 4-bits of one. Consider a timeout: if tag disappears, no pulse found, while sometimes expect long time before HEADER appears (as in SEND_PIN). Read of header may miss the first few bits during transition, so need to special-case handling of this detection.LIW --> Timing-sensitive, syncs reader with tag ... reader must send during 32 period where chip's modulator is ON.ACK --> This is currently a time-to-delay.
Should this be a maximum time to wait for ACK?
Currently, could sit waiting for long time
if no tag present, as check_ack() has no timeout.WaitTicks(EM4X70_T_TAG_TWA);
if (check_ack())
WaitTicks(EM4X70_T_TAG_WEE);
if (check_ack())
return PM3_SUCCESS;