diff --git a/armsrc/Makefile b/armsrc/Makefile index 899b0307..502ab958 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -17,7 +17,7 @@ APP_CFLAGS = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ SRC_LF = lfops.c hitag2.c lfsampling.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c -SRC_ISO14443b = iso14443.c +SRC_ISO14443b = iso14443b.c SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c diff --git a/armsrc/appmain.c b/armsrc/appmain.c index c226c726..fb3c0f18 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -250,55 +250,6 @@ void MeasureAntennaTuningHf(void) } -void SimulateTagHfListen(void) -{ - // ToDo: historically this used the free buffer, which was 2744 Bytes long. - // There might be a better size to be defined: - #define HF_14B_SNOOP_BUFFER_SIZE 2744 - uint8_t *dest = BigBuf_malloc(HF_14B_SNOOP_BUFFER_SIZE); - uint8_t v = 0; - int i; - int p = 0; - - // We're using this mode just so that I can test it out; the simulated - // tag mode would work just as well and be simpler. - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP); - - // We need to listen to the high-frequency, peak-detected path. - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - - FpgaSetupSsc(); - - i = 0; - for(;;) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0xff; - } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - uint8_t r = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - - v <<= 1; - if(r & 1) { - v |= 1; - } - p++; - - if(p >= 8) { - dest[i] = v; - v = 0; - p = 0; - i++; - - if(i >= HF_14B_SNOOP_BUFFER_SIZE) { - break; - } - } - } - } - DbpString("simulate tag (now type bitsamples)"); -} - void ReadMem(int addr) { const uint8_t *data = ((uint8_t *)addr); @@ -782,20 +733,17 @@ void UsbPacketReceived(uint8_t *packet, int len) #endif #ifdef WITH_ISO14443b - case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443: - AcquireRawAdcSamplesIso14443(c->arg[0]); - break; case CMD_READ_SRI512_TAG: - ReadSTMemoryIso14443(0x0F); + ReadSTMemoryIso14443b(0x0F); break; case CMD_READ_SRIX4K_TAG: - ReadSTMemoryIso14443(0x7F); + ReadSTMemoryIso14443b(0x7F); break; - case CMD_SNOOP_ISO_14443: - SnoopIso14443(); + case CMD_SNOOP_ISO_14443B: + SnoopIso14443b(); break; - case CMD_SIMULATE_TAG_ISO_14443: - SimulateIso14443Tag(); + case CMD_SIMULATE_TAG_ISO_14443B: + SimulateIso14443bTag(); break; case CMD_ISO_14443B_COMMAND: SendRawCommand14443B(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes); @@ -911,10 +859,6 @@ void UsbPacketReceived(uint8_t *packet, int len) break; #endif - case CMD_SIMULATE_TAG_HF_LISTEN: - SimulateTagHfListen(); - break; - case CMD_BUFF_CLEAR: BigBuf_Clear(); break; diff --git a/armsrc/apps.h b/armsrc/apps.h index 6360b664..542f3a65 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -141,10 +141,10 @@ void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode); void EM4xWriteWord(uint32_t Data, uint8_t Address, uint32_t Pwd, uint8_t PwdMode); /// iso14443.h -void SimulateIso14443Tag(void); -void AcquireRawAdcSamplesIso14443(uint32_t parameter); -void ReadSTMemoryIso14443(uint32_t); -void RAMFUNC SnoopIso14443(void); +void SimulateIso14443bTag(void); +void AcquireRawAdcSamplesIso14443b(uint32_t parameter); +void ReadSTMemoryIso14443b(uint32_t); +void RAMFUNC SnoopIso14443b(void); void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]); /// iso14443a.h diff --git a/armsrc/iso14443.c b/armsrc/iso14443b.c similarity index 64% rename from armsrc/iso14443.c rename to armsrc/iso14443b.c index c202e312..416c31f9 100644 --- a/armsrc/iso14443.c +++ b/armsrc/iso14443b.c @@ -5,9 +5,8 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Routines to support ISO 14443. This includes both the reader software and -// the `fake tag' modes. At the moment only the Type B modulation is -// supported. +// Routines to support ISO 14443B. This includes both the reader software and +// the `fake tag' modes. //----------------------------------------------------------------------------- #include "proxmark3.h" @@ -17,15 +16,8 @@ #include "iso14443crc.h" -//static void GetSamplesFor14443(int weTx, int n); - -/*#define DEMOD_TRACE_SIZE 4096 -#define READER_TAG_BUFFER_SIZE 2048 -#define TAG_READER_BUFFER_SIZE 2048 -#define DEMOD_DMA_BUFFER_SIZE 1024 -*/ - #define RECEIVE_SAMPLES_TIMEOUT 2000 +#define ISO14443B_DMA_BUFFER_SIZE 256 //============================================================================= // An ISO 14443 Type B tag. We listen for commands from the reader, using @@ -104,14 +96,14 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) ToSendStuffBit(1); } - // Send SOF. + // Send EOF. for(i = 0; i < 10; i++) { ToSendStuffBit(0); ToSendStuffBit(0); ToSendStuffBit(0); ToSendStuffBit(0); } - for(i = 0; i < 10; i++) { + for(i = 0; i < 2; i++) { ToSendStuffBit(1); ToSendStuffBit(1); ToSendStuffBit(1); @@ -120,9 +112,6 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) // Convert from last byte pos to length ToSendMax++; - - // Add a few more for slop - ToSendMax += 2; } //----------------------------------------------------------------------------- @@ -134,8 +123,7 @@ static struct { STATE_UNSYNCD, STATE_GOT_FALLING_EDGE_OF_SOF, STATE_AWAITING_START_BIT, - STATE_RECEIVING_DATA, - STATE_ERROR_WAIT + STATE_RECEIVING_DATA } state; uint16_t shiftReg; int bitCnt; @@ -146,6 +134,9 @@ static struct { } Uart; /* Receive & handle a bit coming from the reader. + * + * This function is called 4 times per bit (every 2 subcarrier cycles). + * Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 2,36us * * LED handling: * LED A -> ON once we have received the SOF and are expecting the rest. @@ -154,11 +145,10 @@ static struct { * Returns: true if we received a EOF * false if we are still waiting for some more */ -static int Handle14443UartBit(int bit) +static RAMFUNC int Handle14443bUartBit(uint8_t bit) { switch(Uart.state) { case STATE_UNSYNCD: - LED_A_OFF(); if(!bit) { // we went low, so this could be the beginning // of an SOF @@ -170,9 +160,9 @@ static int Handle14443UartBit(int bit) case STATE_GOT_FALLING_EDGE_OF_SOF: Uart.posCnt++; - if(Uart.posCnt == 2) { + if(Uart.posCnt == 2) { // sample every 4 1/fs in the middle of a bit if(bit) { - if(Uart.bitCnt >= 10) { + if(Uart.bitCnt > 9) { // we've seen enough consecutive // zeros that it's a valid SOF Uart.posCnt = 0; @@ -182,7 +172,7 @@ static int Handle14443UartBit(int bit) } else { // didn't stay down long enough // before going high, error - Uart.state = STATE_ERROR_WAIT; + Uart.state = STATE_UNSYNCD; } } else { // do nothing, keep waiting @@ -190,20 +180,21 @@ static int Handle14443UartBit(int bit) Uart.bitCnt++; } if(Uart.posCnt >= 4) Uart.posCnt = 0; - if(Uart.bitCnt > 14) { + if(Uart.bitCnt > 12) { // Give up if we see too many zeros without // a one, too. - Uart.state = STATE_ERROR_WAIT; + LED_A_OFF(); + Uart.state = STATE_UNSYNCD; } break; case STATE_AWAITING_START_BIT: Uart.posCnt++; if(bit) { - if(Uart.posCnt > 25) { + if(Uart.posCnt > 50/2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs // stayed high for too long between // characters, error - Uart.state = STATE_ERROR_WAIT; + Uart.state = STATE_UNSYNCD; } } else { // falling edge, this starts the data byte @@ -211,7 +202,6 @@ static int Handle14443UartBit(int bit) Uart.bitCnt = 0; Uart.shiftReg = 0; Uart.state = STATE_RECEIVING_DATA; - LED_A_ON(); // Indicate we're receiving } break; @@ -238,46 +228,54 @@ static int Handle14443UartBit(int bit) if(Uart.byteCnt >= Uart.byteCntMax) { // Buffer overflowed, give up - Uart.posCnt = 0; - Uart.state = STATE_ERROR_WAIT; + LED_A_OFF(); + Uart.state = STATE_UNSYNCD; } else { // so get the next byte now Uart.posCnt = 0; Uart.state = STATE_AWAITING_START_BIT; } - } else if(Uart.shiftReg == 0x000) { + } else if (Uart.shiftReg == 0x000) { // this is an EOF byte LED_A_OFF(); // Finished receiving - return TRUE; + Uart.state = STATE_UNSYNCD; + if (Uart.byteCnt != 0) { + return TRUE; + } } else { // this is an error - Uart.posCnt = 0; - Uart.state = STATE_ERROR_WAIT; + LED_A_OFF(); + Uart.state = STATE_UNSYNCD; } } break; - case STATE_ERROR_WAIT: - // We're all screwed up, so wait a little while - // for whatever went wrong to finish, and then - // start over. - Uart.posCnt++; - if(Uart.posCnt > 10) { - Uart.state = STATE_UNSYNCD; - } - break; - default: + LED_A_OFF(); Uart.state = STATE_UNSYNCD; break; } - // This row make the error blew circular buffer in hf 14b snoop - //if (Uart.state == STATE_ERROR_WAIT) LED_A_OFF(); // Error - return FALSE; } + +static void UartReset() +{ + Uart.byteCntMax = MAX_FRAME_SIZE; + Uart.state = STATE_UNSYNCD; + Uart.byteCnt = 0; + Uart.bitCnt = 0; +} + + +static void UartInit(uint8_t *data) +{ + Uart.output = data; + UartReset(); +} + + //----------------------------------------------------------------------------- // Receive a command (from the reader to us, where we are the simulated tag), // and store it in the given buffer, up to the given maximum length. Keeps @@ -287,76 +285,76 @@ static int Handle14443UartBit(int bit) // Assume that we're called with the SSC (to the FPGA) and ADC path set // correctly. //----------------------------------------------------------------------------- -static int GetIso14443CommandFromReader(uint8_t *received, int *len, int maxLen) +static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) { - uint8_t mask; - int i, bit; - - // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen + // Set FPGA mode to "simulated ISO 14443B tag", no modulation (listen // only, since we are receiving, not transmitting). // Signal field is off with the appropriate LED LED_D_OFF(); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION); - // Now run a `software UART' on the stream of incoming samples. - Uart.output = received; - Uart.byteCntMax = maxLen; - Uart.state = STATE_UNSYNCD; + UartInit(received); for(;;) { WDT_HIT(); if(BUTTON_PRESS()) return FALSE; - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; - } if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - - mask = 0x80; - for(i = 0; i < 8; i++, mask >>= 1) { - bit = (b & mask); - if(Handle14443UartBit(bit)) { + for(uint8_t mask = 0x80; mask != 0x00; mask >>= 1) { + if(Handle14443bUartBit(b & mask)) { *len = Uart.byteCnt; return TRUE; } } } } + + return FALSE; } //----------------------------------------------------------------------------- // Main loop of simulated tag: receive commands from reader, decide what // response to send, and send it. //----------------------------------------------------------------------------- -void SimulateIso14443Tag(void) +void SimulateIso14443bTag(void) { + // the only commands we understand is REQB, AFI=0, Select All, N=0: static const uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; + // ... and REQB, AFI=0, Normal Request, N=0: + static const uint8_t cmd2[] = { 0x05, 0x00, 0x00, 0x71, 0xFF }; + + // ... and we always respond with ATQB, PUPI = 820de174, Application Data = 0x20381922, + // supports only 106kBit/s in both directions, max frame size = 32Bytes, + // supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported: static const uint8_t response1[] = { 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7 }; - uint8_t *resp; - int respLen; + clear_trace(); + set_tracing(TRUE); - uint8_t *resp1 = BigBuf_get_addr() + 800; - int resp1Len; + const uint8_t *resp; + uint8_t *respCode; + uint16_t respLen, respCodeLen; - uint8_t *receivedCmd = BigBuf_get_addr(); - int len; + // allocate command receive buffer + BigBuf_free(); + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); - int i; - - int cmdsRecvd = 0; + uint16_t len; + uint16_t cmdsRecvd = 0; FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - memset(receivedCmd, 0x44, 400); + // prepare the (only one) tag answer: CodeIso14443bAsTag(response1, sizeof(response1)); - memcpy(resp1, ToSend, ToSendMax); resp1Len = ToSendMax; + uint8_t *resp1Code = BigBuf_malloc(ToSendMax); + memcpy(resp1Code, ToSend, ToSendMax); + uint16_t resp1CodeLen = ToSendMax; // We need to listen to the high-frequency, peak-detected path. SetAdcMuxFor(GPIO_MUXSEL_HIPKD); @@ -365,20 +363,28 @@ void SimulateIso14443Tag(void) cmdsRecvd = 0; for(;;) { - uint8_t b1, b2; - if(!GetIso14443CommandFromReader(receivedCmd, &len, 100)) { - Dbprintf("button pressed, received %d commands", cmdsRecvd); - break; + if(!GetIso14443bCommandFromReader(receivedCmd, &len)) { + Dbprintf("button pressed, received %d commands", cmdsRecvd); + break; + } + + if (tracing) { + uint8_t parity[MAX_PARITY_SIZE]; + LogTrace(receivedCmd, len, 0, 0, parity, TRUE); } // Good, look at the command now. - - if(len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len)==0) { - resp = resp1; respLen = resp1Len; + if ( (len == sizeof(cmd1) && memcmp(receivedCmd, cmd1, len) == 0) + || (len == sizeof(cmd2) && memcmp(receivedCmd, cmd2, len) == 0) ) { + resp = response1; + respLen = sizeof(response1); + respCode = resp1Code; + respCodeLen = resp1CodeLen; } else { Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsRecvd); // And print whether the CRC fails, just for good measure + uint8_t b1, b2; ComputeCrc14443(CRC_14443_B, receivedCmd, len-2, &b1, &b2); if(b1 != receivedCmd[len-2] || b2 != receivedCmd[len-1]) { // Not so good, try again. @@ -389,8 +395,6 @@ void SimulateIso14443Tag(void) break; } - memset(receivedCmd, 0x44, 32); - cmdsRecvd++; if(cmdsRecvd > 0x30) { @@ -398,7 +402,7 @@ void SimulateIso14443Tag(void) break; } - if(respLen <= 0) continue; + if(respCodeLen <= 0) continue; // Modulate BPSK // Signal field is off with the appropriate LED @@ -408,15 +412,15 @@ void SimulateIso14443Tag(void) FpgaSetupSsc(); // Transmit the response. - i = 0; + uint16_t i = 0; for(;;) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - uint8_t b = resp[i]; + uint8_t b = respCode[i]; AT91C_BASE_SSC->SSC_THR = b; i++; - if(i > respLen) { + if(i > respCodeLen) { break; } } @@ -425,6 +429,13 @@ void SimulateIso14443Tag(void) (void)b; } } + + // trace the response: + if (tracing) { + uint8_t parity[MAX_PARITY_SIZE]; + LogTrace(resp, respLen, 0, 0, parity, FALSE); + } + } } @@ -442,14 +453,15 @@ static struct { DEMOD_AWAITING_FALLING_EDGE_OF_SOF, DEMOD_GOT_FALLING_EDGE_OF_SOF, DEMOD_AWAITING_START_BIT, - DEMOD_RECEIVING_DATA, - DEMOD_ERROR_WAIT + DEMOD_RECEIVING_DATA } state; int bitCount; int posCount; int thisBit; +/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented. int metric; int metricN; +*/ uint16_t shiftReg; uint8_t *output; int len; @@ -460,6 +472,9 @@ static struct { /* * Handles reception of a bit from the tag * + * This function is called 2 times per bit (every 4 subcarrier cycles). + * Subcarrier frequency fs is 848kHz, 1/fs = 1,18us, i.e. function is called every 4,72us + * * LED handling: * LED C -> ON once we have received the SOF and are expecting the rest. * LED C -> OFF once we have received EOF or are unsynced @@ -468,12 +483,12 @@ static struct { * false if we are still waiting for some more * */ -static RAMFUNC int Handle14443SamplesDemod(int ci, int cq) +static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq) { int v; - // The soft decision on the bit uses an estimate of just the - // quadrant of the reference angle, not the exact angle. +// The soft decision on the bit uses an estimate of just the +// quadrant of the reference angle, not the exact angle. #define MAKE_SOFT_DECISION() { \ if(Demod.sumI > 0) { \ v = ci; \ @@ -487,47 +502,87 @@ static RAMFUNC int Handle14443SamplesDemod(int ci, int cq) } \ } +#define SUBCARRIER_DETECT_THRESHOLD 8 + +// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by abs(ci) + abs(cq) +/* #define CHECK_FOR_SUBCARRIER() { \ + v = ci; \ + if(v < 0) v = -v; \ + if(cq > 0) { \ + v += cq; \ + } else { \ + v -= cq; \ + } \ + } + */ +// Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq))) +#define CHECK_FOR_SUBCARRIER() { \ + if(ci < 0) { \ + if(cq < 0) { /* ci < 0, cq < 0 */ \ + if (cq < ci) { \ + v = -cq - (ci >> 1); \ + } else { \ + v = -ci - (cq >> 1); \ + } \ + } else { /* ci < 0, cq >= 0 */ \ + if (cq < -ci) { \ + v = -ci + (cq >> 1); \ + } else { \ + v = cq - (ci >> 1); \ + } \ + } \ + } else { \ + if(cq < 0) { /* ci >= 0, cq < 0 */ \ + if (-cq < ci) { \ + v = ci - (cq >> 1); \ + } else { \ + v = -cq + (ci >> 1); \ + } \ + } else { /* ci >= 0, cq >= 0 */ \ + if (cq < ci) { \ + v = ci + (cq >> 1); \ + } else { \ + v = cq + (ci >> 1); \ + } \ + } \ + } \ + } + switch(Demod.state) { case DEMOD_UNSYNCD: - v = ci; - if(v < 0) v = -v; - if(cq > 0) { - v += cq; - } else { - v -= cq; - } - if(v > 40) { - Demod.posCount = 0; + CHECK_FOR_SUBCARRIER(); + if(v > SUBCARRIER_DETECT_THRESHOLD) { // subcarrier detected Demod.state = DEMOD_PHASE_REF_TRAINING; - Demod.sumI = 0; - Demod.sumQ = 0; - } + Demod.sumI = ci; + Demod.sumQ = cq; + Demod.posCount = 1; + } break; case DEMOD_PHASE_REF_TRAINING: if(Demod.posCount < 8) { - Demod.sumI += ci; - Demod.sumQ += cq; - } else if(Demod.posCount > 100) { - // error, waited too long - Demod.state = DEMOD_UNSYNCD; - } else { - MAKE_SOFT_DECISION(); - if(v < 0) { - Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF; - Demod.posCount = 0; + CHECK_FOR_SUBCARRIER(); + if (v > SUBCARRIER_DETECT_THRESHOLD) { + // set the reference phase (will code a logic '1') by averaging over 32 1/fs. + // note: synchronization time > 80 1/fs + Demod.sumI += ci; + Demod.sumQ += cq; + Demod.posCount++; + } else { // subcarrier lost + Demod.state = DEMOD_UNSYNCD; } + } else { + Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF; } - Demod.posCount++; break; case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: MAKE_SOFT_DECISION(); - if(v < 0) { + if(v < 0) { // logic '0' detected Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF; - Demod.posCount = 0; + Demod.posCount = 0; // start of SOF sequence } else { - if(Demod.posCount > 100) { + if(Demod.posCount > 200/4) { // maximum length of TR1 = 200 1/fs Demod.state = DEMOD_UNSYNCD; } } @@ -535,35 +590,40 @@ static RAMFUNC int Handle14443SamplesDemod(int ci, int cq) break; case DEMOD_GOT_FALLING_EDGE_OF_SOF: + Demod.posCount++; MAKE_SOFT_DECISION(); if(v > 0) { - if(Demod.posCount < 12) { + if(Demod.posCount < 9*2) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges Demod.state = DEMOD_UNSYNCD; } else { LED_C_ON(); // Got SOF Demod.state = DEMOD_AWAITING_START_BIT; Demod.posCount = 0; Demod.len = 0; +/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented. Demod.metricN = 0; Demod.metric = 0; +*/ } } else { - if(Demod.posCount > 100) { + if(Demod.posCount > 12*2) { // low phase of SOF too long (> 12 etu) Demod.state = DEMOD_UNSYNCD; + LED_C_OFF(); } } - Demod.posCount++; break; case DEMOD_AWAITING_START_BIT: + Demod.posCount++; MAKE_SOFT_DECISION(); if(v > 0) { - if(Demod.posCount > 10) { + if(Demod.posCount > 3*2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs Demod.state = DEMOD_UNSYNCD; + LED_C_OFF(); } - } else { + } else { // start bit detected Demod.bitCount = 0; - Demod.posCount = 1; + Demod.posCount = 1; // this was the first half Demod.thisBit = v; Demod.shiftReg = 0; Demod.state = DEMOD_RECEIVING_DATA; @@ -572,39 +632,41 @@ static RAMFUNC int Handle14443SamplesDemod(int ci, int cq) case DEMOD_RECEIVING_DATA: MAKE_SOFT_DECISION(); - if(Demod.posCount == 0) { + if(Demod.posCount == 0) { // first half of bit Demod.thisBit = v; Demod.posCount = 1; - } else { + } else { // second half of bit Demod.thisBit += v; +/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented. if(Demod.thisBit > 0) { Demod.metric += Demod.thisBit; } else { Demod.metric -= Demod.thisBit; } (Demod.metricN)++; +*/ Demod.shiftReg >>= 1; - if(Demod.thisBit > 0) { + if(Demod.thisBit > 0) { // logic '1' Demod.shiftReg |= 0x200; } Demod.bitCount++; if(Demod.bitCount == 10) { uint16_t s = Demod.shiftReg; - if((s & 0x200) && !(s & 0x001)) { + if((s & 0x200) && !(s & 0x001)) { // stop bit == '1', start bit == '0' uint8_t b = (s >> 1); Demod.output[Demod.len] = b; Demod.len++; Demod.state = DEMOD_AWAITING_START_BIT; - } else if(s == 0x000) { - // This is EOF - LED_C_OFF(); - Demod.state = DEMOD_UNSYNCD; - return TRUE; } else { Demod.state = DEMOD_UNSYNCD; + LED_C_OFF(); + if(s == 0x000) { + // This is EOF (start, stop and all data bits == '0' + return TRUE; + } } } Demod.posCount = 0; @@ -613,48 +675,39 @@ static RAMFUNC int Handle14443SamplesDemod(int ci, int cq) default: Demod.state = DEMOD_UNSYNCD; + LED_C_OFF(); break; } - if (Demod.state == DEMOD_UNSYNCD) LED_C_OFF(); // Not synchronized... return FALSE; } + + static void DemodReset() { // Clear out the state of the "UART" that receives from the tag. Demod.len = 0; Demod.state = DEMOD_UNSYNCD; + Demod.posCount = 0; memset(Demod.output, 0x00, MAX_FRAME_SIZE); } + + static void DemodInit(uint8_t *data) { Demod.output = data; DemodReset(); } -static void UartReset() -{ - Uart.byteCntMax = MAX_FRAME_SIZE; - Uart.state = STATE_UNSYNCD; - Uart.byteCnt = 0; - Uart.bitCnt = 0; -} -static void UartInit(uint8_t *data) -{ - Uart.output = data; - UartReset(); -} /* * Demodulate the samples we received from the tag, also log to tracebuffer - * weTx: set to 'TRUE' if we behave like a reader - * set to 'FALSE' if we behave like a snooper * quiet: set to 'TRUE' to disable debug output */ -static void GetSamplesFor14443Demod(int weTx, int n, int quiet) +static void GetSamplesFor14443bDemod(int n, bool quiet) { int max = 0; - int gotFrame = FALSE; + bool gotFrame = FALSE; int lastRxCounter, ci, cq, samples = 0; // Allocate memory from BigBuf for some buffers @@ -665,101 +718,68 @@ static void GetSamplesFor14443Demod(int weTx, int n, int quiet) uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE); // The DMA buffer, used to stream samples from the FPGA - uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); + int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); // Set up the demodulator for tag -> reader responses. DemodInit(receivedResponse); // Setup and start DMA. - FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE); + FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE); - uint8_t *upTo= dmaBuf; - lastRxCounter = DMA_BUFFER_SIZE; + int8_t *upTo = dmaBuf; + lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; // Signal field is ON with the appropriate LED: - if (weTx) LED_D_ON(); else LED_D_OFF(); + LED_D_ON(); // And put the FPGA in the appropriate mode - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | - (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP)); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); for(;;) { int behindBy = lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR; if(behindBy > max) max = behindBy; - while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (DMA_BUFFER_SIZE-1)) - > 2) - { + while(((lastRxCounter-AT91C_BASE_PDC_SSC->PDC_RCR) & (ISO14443B_DMA_BUFFER_SIZE-1)) > 2) { ci = upTo[0]; cq = upTo[1]; upTo += 2; - if(upTo >= dmaBuf + DMA_BUFFER_SIZE) { + if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { upTo = dmaBuf; AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; } lastRxCounter -= 2; if(lastRxCounter <= 0) { - lastRxCounter += DMA_BUFFER_SIZE; + lastRxCounter += ISO14443B_DMA_BUFFER_SIZE; } samples += 2; - if(Handle14443SamplesDemod(ci, cq)) { - gotFrame = 1; + if(Handle14443bSamplesDemod(ci, cq)) { + gotFrame = TRUE; + break; } } - if(samples > n) { + if(samples > n || gotFrame) { break; } } + AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; - if (!quiet) Dbprintf("%x %x %x", max, gotFrame, Demod.len); + + if (!quiet) Dbprintf("max behindby = %d, samples = %d, gotFrame = %d, Demod.len = %d, Demod.sumI = %d, Demod.sumQ = %d", max, samples, gotFrame, Demod.len, Demod.sumI, Demod.sumQ); //Tracing if (tracing && Demod.len > 0) { uint8_t parity[MAX_PARITY_SIZE]; - GetParity(Demod.output, Demod.len, parity); LogTrace(Demod.output, Demod.len, 0, 0, parity, FALSE); } } -//----------------------------------------------------------------------------- -// Read the tag's response. We just receive a stream of slightly-processed -// samples from the FPGA, which we will later do some signal processing on, -// to get the bits. -//----------------------------------------------------------------------------- -/*static void GetSamplesFor14443(int weTx, int n) -{ - uint8_t *dest = (uint8_t *)BigBuf; - int c; - - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | - (weTx ? 0 : FPGA_HF_READER_RX_XCORR_SNOOP)); - - c = 0; - for(;;) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x43; - } - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - int8_t b; - b = (int8_t)AT91C_BASE_SSC->SSC_RHR; - - dest[c++] = (uint8_t)b; - - if(c >= n) { - break; - } - } - } -}*/ //----------------------------------------------------------------------------- // Transmit the command (to the tag) that was placed in ToSend[]. //----------------------------------------------------------------------------- -static void TransmitFor14443(void) +static void TransmitFor14443b(void) { int c; @@ -773,8 +793,7 @@ static void TransmitFor14443(void) LED_D_ON(); // Signal we are transmitting with the Green LED LED_B_ON(); - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); for(c = 0; c < 10;) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { @@ -806,9 +825,10 @@ static void TransmitFor14443(void) LED_B_OFF(); // Finished sending } + //----------------------------------------------------------------------------- // Code a layer 2 command (string of octets, including CRC) into ToSend[], -// so that it is ready to transmit to the tag using TransmitFor14443(). +// so that it is ready to transmit to the tag using TransmitFor14443b(). //----------------------------------------------------------------------------- static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { @@ -862,20 +882,6 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) ToSendMax++; } -//----------------------------------------------------------------------------- -// Read an ISO 14443 tag. We send it some set of commands, and record the -// responses. -// The command name is misleading, it actually decodes the reponse in HEX -// into the output buffer (read the result using hexsamples, not hisamples) -// -// obsolete function only for test -//----------------------------------------------------------------------------- -void AcquireRawAdcSamplesIso14443(uint32_t parameter) -{ - uint8_t cmd1[] = { 0x05, 0x00, 0x08, 0x39, 0x73 }; - - SendRawCommand14443B(sizeof(cmd1),1,1,cmd1); -} /** Convenience function to encode, transmit and trace iso 14443b comms @@ -883,16 +889,16 @@ void AcquireRawAdcSamplesIso14443(uint32_t parameter) static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) { CodeIso14443bAsReader(cmd, len); - TransmitFor14443(); + TransmitFor14443b(); if (tracing) { uint8_t parity[MAX_PARITY_SIZE]; - GetParity(cmd, len, parity); LogTrace(cmd,len, 0, 0, parity, TRUE); } } + //----------------------------------------------------------------------------- -// Read a SRI512 ISO 14443 tag. +// Read a SRI512 ISO 14443B tag. // // SRI512 tags are just simple memory tags, here we're looking at making a dump // of the contents of the memory. No anticollision algorithm is done, we assume @@ -900,7 +906,7 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) // // I tried to be systematic and check every answer of the tag, every CRC, etc... //----------------------------------------------------------------------------- -void ReadSTMemoryIso14443(uint32_t dwLast) +void ReadSTMemoryIso14443b(uint32_t dwLast) { clear_trace(); set_tracing(TRUE); @@ -920,108 +926,97 @@ void ReadSTMemoryIso14443(uint32_t dwLast) // Now give it time to spin up. // Signal field is on with the appropriate LED LED_D_ON(); - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); SpinDelay(200); // First command: wake up the tag using the INITIATE command - uint8_t cmd1[] = { 0x06, 0x00, 0x97, 0x5b}; - + uint8_t cmd1[] = {0x06, 0x00, 0x97, 0x5b}; CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); -// LED_A_ON(); - GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE); -// LED_A_OFF(); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); if (Demod.len == 0) { - DbpString("No response from tag"); - return; + DbpString("No response from tag"); + return; } else { - Dbprintf("Randomly generated UID from tag (+ 2 byte CRC): %x %x %x", - Demod.output[0], Demod.output[1],Demod.output[2]); + Dbprintf("Randomly generated Chip ID (+ 2 byte CRC): %02x %02x %02x", + Demod.output[0], Demod.output[1], Demod.output[2]); } + // There is a response, SELECT the uid DbpString("Now SELECT tag:"); cmd1[0] = 0x0E; // 0x0E is SELECT cmd1[1] = Demod.output[0]; ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]); CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); - -// LED_A_ON(); - GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE); -// LED_A_OFF(); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); if (Demod.len != 3) { - Dbprintf("Expected 3 bytes from tag, got %d", Demod.len); - return; + Dbprintf("Expected 3 bytes from tag, got %d", Demod.len); + return; } // Check the CRC of the answer: ComputeCrc14443(CRC_14443_B, Demod.output, 1 , &cmd1[2], &cmd1[3]); if(cmd1[2] != Demod.output[1] || cmd1[3] != Demod.output[2]) { - DbpString("CRC Error reading select response."); - return; + DbpString("CRC Error reading select response."); + return; } // Check response from the tag: should be the same UID as the command we just sent: if (cmd1[1] != Demod.output[0]) { - Dbprintf("Bad response to SELECT from Tag, aborting: %x %x", cmd1[1], Demod.output[0]); - return; + Dbprintf("Bad response to SELECT from Tag, aborting: %02x %02x", cmd1[1], Demod.output[0]); + return; } + // Tag is now selected, // First get the tag's UID: cmd1[0] = 0x0B; ComputeCrc14443(CRC_14443_B, cmd1, 1 , &cmd1[1], &cmd1[2]); CodeAndTransmit14443bAsReader(cmd1, 3); // Only first three bytes for this one - -// LED_A_ON(); - GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE); -// LED_A_OFF(); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); if (Demod.len != 10) { - Dbprintf("Expected 10 bytes from tag, got %d", Demod.len); - return; + Dbprintf("Expected 10 bytes from tag, got %d", Demod.len); + return; } // The check the CRC of the answer (use cmd1 as temporary variable): ComputeCrc14443(CRC_14443_B, Demod.output, 8, &cmd1[2], &cmd1[3]); - if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) { - Dbprintf("CRC Error reading block! - Below: expected, got %x %x", - (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]); - // Do not return;, let's go on... (we should retry, maybe ?) + if(cmd1[2] != Demod.output[8] || cmd1[3] != Demod.output[9]) { + Dbprintf("CRC Error reading block! Expected: %04x got: %04x", + (cmd1[2]<<8)+cmd1[3], (Demod.output[8]<<8)+Demod.output[9]); + // Do not return;, let's go on... (we should retry, maybe ?) } Dbprintf("Tag UID (64 bits): %08x %08x", - (Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4], - (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]); + (Demod.output[7]<<24) + (Demod.output[6]<<16) + (Demod.output[5]<<8) + Demod.output[4], + (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0]); // Now loop to read all 16 blocks, address from 0 to last block - Dbprintf("Tag memory dump, block 0 to %d",dwLast); + Dbprintf("Tag memory dump, block 0 to %d", dwLast); cmd1[0] = 0x08; i = 0x00; dwLast++; for (;;) { - if (i == dwLast) { + if (i == dwLast) { DbpString("System area block (0xff):"); i = 0xff; } cmd1[1] = i; ComputeCrc14443(CRC_14443_B, cmd1, 2, &cmd1[2], &cmd1[3]); CodeAndTransmit14443bAsReader(cmd1, sizeof(cmd1)); - -// LED_A_ON(); - GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE); -// LED_A_OFF(); + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); if (Demod.len != 6) { // Check if we got an answer from the tag - DbpString("Expected 6 bytes from tag, got less..."); - return; + DbpString("Expected 6 bytes from tag, got less..."); + return; } // The check the CRC of the answer (use cmd1 as temporary variable): ComputeCrc14443(CRC_14443_B, Demod.output, 4, &cmd1[2], &cmd1[3]); - if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) { - Dbprintf("CRC Error reading block! - Below: expected, got %x %x", - (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]); - // Do not return;, let's go on... (we should retry, maybe ?) + if(cmd1[2] != Demod.output[4] || cmd1[3] != Demod.output[5]) { + Dbprintf("CRC Error reading block! Expected: %04x got: %04x", + (cmd1[2]<<8)+cmd1[3], (Demod.output[4]<<8)+Demod.output[5]); + // Do not return;, let's go on... (we should retry, maybe ?) } // Now print out the memory location: - Dbprintf("Address=%x, Contents=%x, CRC=%x", i, - (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], - (Demod.output[4]<<8)+Demod.output[5]); + Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i, + (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], + (Demod.output[4]<<8)+Demod.output[5]); if (i == 0xff) { - break; + break; } i++; } @@ -1040,17 +1035,17 @@ void ReadSTMemoryIso14443(uint32_t dwLast) //----------------------------------------------------------------------------- /* * Memory usage for this function, (within BigBuf) - * 0-4095 : Demodulated samples receive (4096 bytes) - DEMOD_TRACE_SIZE - * 4096-6143 : Last Received command, 2048 bytes (reader->tag) - READER_TAG_BUFFER_SIZE - * 6144-8191 : Last Received command, 2048 bytes(tag->reader) - TAG_READER_BUFFER_SIZE - * 8192-9215 : DMA Buffer, 1024 bytes (samples) - DEMOD_DMA_BUFFER_SIZE + * Last Received command (reader->tag) - MAX_FRAME_SIZE + * Last Received command (tag->reader) - MAX_FRAME_SIZE + * DMA Buffer - ISO14443B_DMA_BUFFER_SIZE + * Demodulated samples received - all the rest */ -void RAMFUNC SnoopIso14443(void) +void RAMFUNC SnoopIso14443b(void) { // We won't start recording the frames that we acquire until we trigger; // a good trigger condition to get started is probably when we see a // response from the tag. - int triggered = TRUE; + int triggered = TRUE; // TODO: set and evaluate trigger condition FpgaDownloadAndGo(FPGA_BITSTREAM_HF); BigBuf_free(); @@ -1059,9 +1054,9 @@ void RAMFUNC SnoopIso14443(void) set_tracing(TRUE); // The DMA buffer, used to stream samples from the FPGA - uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); + int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); int lastRxCounter; - uint8_t *upTo; + int8_t *upTo; int ci, cq; int maxBehindBy = 0; @@ -1077,110 +1072,106 @@ void RAMFUNC SnoopIso14443(void) Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen()); Dbprintf(" Reader -> tag: %i bytes", MAX_FRAME_SIZE); Dbprintf(" tag -> Reader: %i bytes", MAX_FRAME_SIZE); - Dbprintf(" DMA: %i bytes", DMA_BUFFER_SIZE); + Dbprintf(" DMA: %i bytes", ISO14443B_DMA_BUFFER_SIZE); - // Signal field is off with the appropriate LED - LED_D_OFF(); + // Signal field is off, no reader signal, no tag signal + LEDsoff(); // And put the FPGA in the appropriate mode - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | - FPGA_HF_READER_RX_XCORR_SNOOP); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); // Setup for the DMA. FpgaSetupSsc(); upTo = dmaBuf; - lastRxCounter = DMA_BUFFER_SIZE; - FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); + lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; + FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE); uint8_t parity[MAX_PARITY_SIZE]; - LED_A_ON(); - + + bool TagIsActive = FALSE; + bool ReaderIsActive = FALSE; + // And now we loop, receiving samples. for(;;) { int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & - (DMA_BUFFER_SIZE-1); + (ISO14443B_DMA_BUFFER_SIZE-1); if(behindBy > maxBehindBy) { maxBehindBy = behindBy; - if(behindBy > (9*DMA_BUFFER_SIZE/10)) { // TODO: understand whether we can increase/decrease as we want or not? - Dbprintf("blew circular buffer! behindBy=0x%x", behindBy); - break; - } } + if(behindBy < 2) continue; ci = upTo[0]; cq = upTo[1]; upTo += 2; lastRxCounter -= 2; - if(upTo >= dmaBuf + DMA_BUFFER_SIZE) { + if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { upTo = dmaBuf; - lastRxCounter += DMA_BUFFER_SIZE; + lastRxCounter += ISO14443B_DMA_BUFFER_SIZE; AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; + WDT_HIT(); + if(behindBy > (9*ISO14443B_DMA_BUFFER_SIZE/10)) { // TODO: understand whether we can increase/decrease as we want or not? + Dbprintf("blew circular buffer! behindBy=%d", behindBy); + break; + } + if(!tracing) { + DbpString("Reached trace limit"); + break; + } + if(BUTTON_PRESS()) { + DbpString("cancelled"); + break; + } } samples += 2; - if(Handle14443UartBit(ci & 1)) { - if(triggered && tracing) { - GetParity(Uart.output, Uart.byteCnt, parity); - LogTrace(Uart.output,Uart.byteCnt,samples, samples,parity,TRUE); + if (!TagIsActive) { // no need to try decoding reader data if the tag is sending + if(Handle14443bUartBit(ci & 0x01)) { + if(triggered && tracing) { + LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE); + } + /* And ready to receive another command. */ + UartReset(); + /* And also reset the demod code, which might have been */ + /* false-triggered by the commands from the reader. */ + DemodReset(); } - if(Uart.byteCnt==0) Dbprintf("[1] Error, Uart.byteCnt==0, Uart.bitCnt=%d", Uart.bitCnt); - - /* And ready to receive another command. */ - UartReset(); - /* And also reset the demod code, which might have been */ - /* false-triggered by the commands from the reader. */ - DemodReset(); - } - if(Handle14443UartBit(cq & 1)) { - if(triggered && tracing) { - GetParity(Uart.output, Uart.byteCnt, parity); - LogTrace(Uart.output,Uart.byteCnt,samples, samples,parity,TRUE); + if(Handle14443bUartBit(cq & 0x01)) { + if(triggered && tracing) { + LogTrace(Uart.output, Uart.byteCnt, samples, samples, parity, TRUE); + } + /* And ready to receive another command. */ + UartReset(); + /* And also reset the demod code, which might have been */ + /* false-triggered by the commands from the reader. */ + DemodReset(); } - if(Uart.byteCnt==0) Dbprintf("[2] Error, Uart.byteCnt==0, Uart.bitCnt=%d", Uart.bitCnt); - - /* And ready to receive another command. */ - UartReset(); - /* And also reset the demod code, which might have been */ - /* false-triggered by the commands from the reader. */ - DemodReset(); + ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF); } - if(Handle14443SamplesDemod(ci, cq)) { + if(!ReaderIsActive) { // no need to try decoding tag data if the reader is sending - and we cannot afford the time + if(Handle14443bSamplesDemod(ci | 0x01, cq | 0x01)) { - //Use samples as a time measurement - if(tracing) - { - uint8_t parity[MAX_PARITY_SIZE]; - GetParity(Demod.output, Demod.len, parity); - LogTrace(Demod.output,Demod.len,samples, samples,parity,FALSE); + //Use samples as a time measurement + if(tracing) + { + uint8_t parity[MAX_PARITY_SIZE]; + LogTrace(Demod.output, Demod.len, samples, samples, parity, FALSE); + } + triggered = TRUE; + + // And ready to receive another response. + DemodReset(); } - triggered = TRUE; - LED_A_OFF(); - LED_B_ON(); - - // And ready to receive another response. - DemodReset(); - } - WDT_HIT(); - - if(!tracing) { - DbpString("Reached trace limit"); - break; + TagIsActive = (Demod.state > DEMOD_GOT_FALLING_EDGE_OF_SOF); } - if(BUTTON_PRESS()) { - DbpString("cancelled"); - break; - } } + FpgaDisableSscDma(); - LED_A_OFF(); - LED_B_OFF(); - LED_C_OFF(); + LEDsoff(); AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; DbpString("Snoop statistics:"); Dbprintf(" Max behind by: %i", maxBehindBy); @@ -1190,6 +1181,7 @@ void RAMFUNC SnoopIso14443(void) Dbprintf(" Trace length: %i", BigBuf_get_traceLen()); } + /* * Send raw command to tag ISO14443B * @Input @@ -1202,42 +1194,23 @@ void RAMFUNC SnoopIso14443(void) * none * */ - -void SendRawCommand14443B(uint32_t datalen, uint32_t recv,uint8_t powerfield, uint8_t data[]) +void SendRawCommand14443B(uint32_t datalen, uint32_t recv, uint8_t powerfield, uint8_t data[]) { FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - if(!powerfield) - { - // Make sure that we start from off, since the tags are stateful; - // confusing things will happen if we don't reset them between reads. - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_D_OFF(); - SpinDelay(200); - } - - if(!GETBIT(GPIO_LED_D)) - { - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - FpgaSetupSsc(); - - // Now give it time to spin up. - // Signal field is on with the appropriate LED - LED_D_ON(); - FpgaWriteConfWord( - FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); - SpinDelay(200); - } + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaSetupSsc(); + set_tracing(TRUE); + CodeAndTransmit14443bAsReader(data, datalen); - if(recv) - { - GetSamplesFor14443Demod(TRUE, RECEIVE_SAMPLES_TIMEOUT, TRUE); - uint16_t iLen = MIN(Demod.len,USB_CMD_DATA_SIZE); - cmd_send(CMD_ACK,iLen,0,0,Demod.output,iLen); + if(recv) { + GetSamplesFor14443bDemod(RECEIVE_SAMPLES_TIMEOUT, TRUE); + uint16_t iLen = MIN(Demod.len, USB_CMD_DATA_SIZE); + cmd_send(CMD_ACK, iLen, 0, 0, Demod.output, iLen); } - if(!powerfield) - { + + if(!powerfield) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); } diff --git a/client/cmdhf.c b/client/cmdhf.c index 16f7bb0f..fc6127c2 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -378,7 +378,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01); } uint8_t parityBits = parityBytes[j>>3]; - if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { + if (protocol != ISO_14443B && isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) { snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]); } else { diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 525ffcc6..496267cd 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -25,154 +25,23 @@ static int CmdHelp(const char *Cmd); -int CmdHF14BDemod(const char *Cmd) -{ - int i, j, iold; - int isum, qsum; - int outOfWeakAt; - bool negateI, negateQ; - - uint8_t data[256]; - int dataLen = 0; - - // As received, the samples are pairs, correlations against I and Q - // square waves. So estimate angle of initial carrier (or just - // quadrant, actually), and then do the demod. - - // First, estimate where the tag starts modulating. - for (i = 0; i < GraphTraceLen; i += 2) { - if (abs(GraphBuffer[i]) + abs(GraphBuffer[i + 1]) > 40) { - break; - } - } - if (i >= GraphTraceLen) { - PrintAndLog("too weak to sync"); - return 0; - } - PrintAndLog("out of weak at %d", i); - outOfWeakAt = i; - - // Now, estimate the phase in the initial modulation of the tag - isum = 0; - qsum = 0; - for (; i < (outOfWeakAt + 16); i += 2) { - isum += GraphBuffer[i + 0]; - qsum += GraphBuffer[i + 1]; - } - negateI = (isum < 0); - negateQ = (qsum < 0); - - // Turn the correlation pairs into soft decisions on the bit. - j = 0; - for (i = 0; i < GraphTraceLen / 2; i++) { - int si = GraphBuffer[j]; - int sq = GraphBuffer[j + 1]; - if (negateI) si = -si; - if (negateQ) sq = -sq; - GraphBuffer[i] = si + sq; - j += 2; - } - GraphTraceLen = i; - - i = outOfWeakAt / 2; - while (GraphBuffer[i] > 0 && i < GraphTraceLen) - i++; - if (i >= GraphTraceLen) goto demodError; - - iold = i; - while (GraphBuffer[i] < 0 && i < GraphTraceLen) - i++; - if (i >= GraphTraceLen) goto demodError; - if ((i - iold) > 23) goto demodError; - - PrintAndLog("make it to demod loop"); - - for (;;) { - iold = i; - while (GraphBuffer[i] >= 0 && i < GraphTraceLen) - i++; - if (i >= GraphTraceLen) goto demodError; - if ((i - iold) > 6) goto demodError; - - uint16_t shiftReg = 0; - if (i + 20 >= GraphTraceLen) goto demodError; - - for (j = 0; j < 10; j++) { - int soft = GraphBuffer[i] + GraphBuffer[i + 1]; - - if (abs(soft) < (abs(isum) + abs(qsum)) / 20) { - PrintAndLog("weak bit"); - } - - shiftReg >>= 1; - if(GraphBuffer[i] + GraphBuffer[i+1] >= 0) { - shiftReg |= 0x200; - } - - i+= 2; - } - - if ((shiftReg & 0x200) && !(shiftReg & 0x001)) - { - // valid data byte, start and stop bits okay - PrintAndLog(" %02x", (shiftReg >> 1) & 0xff); - data[dataLen++] = (shiftReg >> 1) & 0xff; - if (dataLen >= sizeof(data)) { - return 0; - } - } else if (shiftReg == 0x000) { - // this is EOF - break; - } else { - goto demodError; - } - } - - uint8_t first, second; - ComputeCrc14443(CRC_14443_B, data, dataLen-2, &first, &second); - PrintAndLog("CRC: %02x %02x (%s)\n", first, second, - (first == data[dataLen-2] && second == data[dataLen-1]) ? - "ok" : "****FAIL****"); - - RepaintGraphWindow(); - return 0; - -demodError: - PrintAndLog("demod error"); - RepaintGraphWindow(); - return 0; -} - int CmdHF14BList(const char *Cmd) { PrintAndLog("Deprecated command, use 'hf list 14b' instead"); return 0; } -int CmdHF14BRead(const char *Cmd) -{ - UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443, {strtol(Cmd, NULL, 0), 0, 0}}; - SendCommand(&c); - return 0; -} -int CmdHF14Sim(const char *Cmd) +int CmdHF14BSim(const char *Cmd) { - UsbCommand c={CMD_SIMULATE_TAG_ISO_14443}; - SendCommand(&c); - return 0; -} - -int CmdHFSimlisten(const char *Cmd) -{ - UsbCommand c = {CMD_SIMULATE_TAG_HF_LISTEN}; + UsbCommand c={CMD_SIMULATE_TAG_ISO_14443B}; SendCommand(&c); return 0; } int CmdHF14BSnoop(const char *Cmd) { - UsbCommand c = {CMD_SNOOP_ISO_14443}; + UsbCommand c = {CMD_SNOOP_ISO_14443B}; SendCommand(&c); return 0; } @@ -288,7 +157,7 @@ int CmdHF14BCmdRaw (const char *cmd) { if (WaitForResponseTimeout(CMD_ACK,&resp,1000)) { recv = resp.d.asBytes; PrintAndLog("received %i octets",resp.arg[0]); - if(!resp.arg[0]) + if(resp.arg[0] == 0) return 0; hexout = (char *)malloc(resp.arg[0] * 3 + 1); if (hexout != NULL) { @@ -298,11 +167,13 @@ int CmdHF14BCmdRaw (const char *cmd) { } PrintAndLog("%s", hexout); free(hexout); - ComputeCrc14443(CRC_14443_B, recv, resp.arg[0]-2, &first, &second); - if(recv[resp.arg[0]-2]==first && recv[resp.arg[0]-1]==second) { - PrintAndLog("CRC OK"); - } else { - PrintAndLog("CRC failed"); + if (resp.arg[0] > 2) { + ComputeCrc14443(CRC_14443_B, recv, resp.arg[0]-2, &first, &second); + if(recv[resp.arg[0]-2]==first && recv[resp.arg[0]-1]==second) { + PrintAndLog("CRC OK"); + } else { + PrintAndLog("CRC failed"); + } } } else { PrintAndLog("malloc failed your client has low memory?"); @@ -385,12 +256,9 @@ int CmdHF14BWrite( const char *Cmd){ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"demod", CmdHF14BDemod, 1, "Demodulate ISO14443 Type B from tag"}, {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443b history"}, - {"read", CmdHF14BRead, 0, "Read HF tag (ISO 14443)"}, - {"sim", CmdHF14Sim, 0, "Fake ISO 14443 tag"}, - {"simlisten", CmdHFSimlisten, 0, "Get HF samples as fake tag"}, - {"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443"}, + {"sim", CmdHF14BSim, 0, "Fake ISO 14443B tag"}, + {"snoop", CmdHF14BSnoop, 0, "Eavesdrop ISO 14443B"}, {"sri512read", CmdSri512Read, 0, "Read contents of a SRI512 tag"}, {"srix4kread", CmdSrix4kRead, 0, "Read contents of a SRIX4K tag"}, {"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"}, diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index c5b91f99..b3a7f4ec 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -89,7 +89,6 @@ typedef struct { // For the 13.56 MHz tags #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 -#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301 #define CMD_READ_SRI512_TAG 0x0303 #define CMD_READ_SRIX4K_TAG 0x0304 #define CMD_READER_ISO_15693 0x0310 @@ -105,9 +104,8 @@ typedef struct { #define CMD_SIMULATE_HITAG 0x0371 #define CMD_READER_HITAG 0x0372 -#define CMD_SIMULATE_TAG_HF_LISTEN 0x0380 -#define CMD_SIMULATE_TAG_ISO_14443 0x0381 -#define CMD_SNOOP_ISO_14443 0x0382 +#define CMD_SIMULATE_TAG_ISO_14443B 0x0381 +#define CMD_SNOOP_ISO_14443B 0x0382 #define CMD_SNOOP_ISO_14443a 0x0383 #define CMD_SIMULATE_TAG_ISO_14443a 0x0384 #define CMD_READER_ISO_14443a 0x0385 diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index 678c745e..4c7bc638 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -59,7 +59,6 @@ local _commands = { --// For the 13.56 MHz tags CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 = 0x0300, - CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 = 0x0301, CMD_READ_SRI512_TAG = 0x0303, CMD_READ_SRIX4K_TAG = 0x0304, CMD_READER_ISO_15693 = 0x0310, @@ -76,9 +75,8 @@ local _commands = { CMD_SIMULATE_HITAG = 0x0371, CMD_READER_HITAG = 0x0372, - CMD_SIMULATE_TAG_HF_LISTEN = 0x0380, - CMD_SIMULATE_TAG_ISO_14443 = 0x0381, - CMD_SNOOP_ISO_14443 = 0x0382, + CMD_SIMULATE_TAG_ISO_14443B = 0x0381, + CMD_SNOOP_ISO_14443B = 0x0382, CMD_SNOOP_ISO_14443a = 0x0383, CMD_SIMULATE_TAG_ISO_14443a = 0x0384, CMD_READER_ISO_14443a = 0x0385, diff --git a/fpga/fpga_hf.bit b/fpga/fpga_hf.bit index 20fb2bd4..50c7eef9 100644 Binary files a/fpga/fpga_hf.bit and b/fpga/fpga_hf.bit differ diff --git a/fpga/fpga_hf.v b/fpga/fpga_hf.v index a2100df6..8a465e75 100644 --- a/fpga/fpga_hf.v +++ b/fpga/fpga_hf.v @@ -73,9 +73,6 @@ wire hi_read_rx_xcorr_848 = conf_word[0]; // and whether to drive the coil (reader) or just short it (snooper) wire hi_read_rx_xcorr_snoop = conf_word[1]; -// Divide the expected subcarrier frequency for hi_read_rx_xcorr by 4 -wire hi_read_rx_xcorr_quarter = conf_word[2]; - // For the high-frequency simulated tag: what kind of modulation to use. wire [2:0] hi_simulate_mod_type = conf_word[2:0]; @@ -102,7 +99,7 @@ hi_read_rx_xcorr hrxc( hrxc_ssp_frame, hrxc_ssp_din, ssp_dout, hrxc_ssp_clk, cross_hi, cross_lo, hrxc_dbg, - hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop, hi_read_rx_xcorr_quarter + hi_read_rx_xcorr_848, hi_read_rx_xcorr_snoop ); hi_simulate hs( diff --git a/fpga/hi_read_rx_xcorr.v b/fpga/hi_read_rx_xcorr.v index dece2db3..afaf7cb6 100644 --- a/fpga/hi_read_rx_xcorr.v +++ b/fpga/hi_read_rx_xcorr.v @@ -10,7 +10,7 @@ module hi_read_rx_xcorr( ssp_frame, ssp_din, ssp_dout, ssp_clk, cross_hi, cross_lo, dbg, - xcorr_is_848, snoop, xcorr_quarter_freq + xcorr_is_848, snoop ); input pck0, ck_1356meg, ck_1356megb; output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4; @@ -20,58 +20,24 @@ module hi_read_rx_xcorr( output ssp_frame, ssp_din, ssp_clk; input cross_hi, cross_lo; output dbg; - input xcorr_is_848, snoop, xcorr_quarter_freq; + input xcorr_is_848, snoop; // Carrier is steady on through this, unless we're snooping. assign pwr_hi = ck_1356megb & (~snoop); assign pwr_oe1 = 1'b0; -assign pwr_oe2 = 1'b0; assign pwr_oe3 = 1'b0; assign pwr_oe4 = 1'b0; -reg ssp_clk; -reg ssp_frame; +wire adc_clk = ck_1356megb; reg fc_div_2; -always @(posedge ck_1356meg) - fc_div_2 = ~fc_div_2; - -reg fc_div_4; -always @(posedge fc_div_2) - fc_div_4 = ~fc_div_4; - -reg fc_div_8; -always @(posedge fc_div_4) - fc_div_8 = ~fc_div_8; - -reg adc_clk; - -always @(xcorr_is_848 or xcorr_quarter_freq or ck_1356meg) - if(~xcorr_quarter_freq) - begin - if(xcorr_is_848) - // The subcarrier frequency is fc/16; we will sample at fc, so that - // means the subcarrier is 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 1 1 ... - adc_clk <= ck_1356meg; - else - // The subcarrier frequency is fc/32; we will sample at fc/2, and - // the subcarrier will look identical. - adc_clk <= fc_div_2; - end - else - begin - if(xcorr_is_848) - // The subcarrier frequency is fc/64 - adc_clk <= fc_div_4; - else - // The subcarrier frequency is fc/128 - adc_clk <= fc_div_8; - end +always @(negedge ck_1356megb) + fc_div_2 <= fc_div_2 + 1; // When we're a reader, we just need to do the BPSK demod; but when we're an // eavesdropper, we also need to pick out the commands sent by the reader, // using AM. Do this the same way that we do it for the simulated tag. -reg after_hysteresis, after_hysteresis_prev; +reg after_hysteresis, after_hysteresis_prev, after_hysteresis_prev_prev; reg [11:0] has_been_low_for; always @(negedge adc_clk) begin @@ -97,12 +63,24 @@ end // Let us report a correlation every 4 subcarrier cycles, or 4*16 samples, // so we need a 6-bit counter. reg [5:0] corr_i_cnt; -reg [5:0] corr_q_cnt; // And a couple of registers in which to accumulate the correlations. -reg signed [15:0] corr_i_accum; -reg signed [15:0] corr_q_accum; +// we would add at most 32 times adc_d, the result can be held in 13 bits. +// Need one additional bit because it can be negative as well +reg signed [13:0] corr_i_accum; +reg signed [13:0] corr_q_accum; reg signed [7:0] corr_i_out; reg signed [7:0] corr_q_out; +// clock and frame signal for communication to ARM +reg ssp_clk; +reg ssp_frame; + + +always @(negedge adc_clk) +begin + if (xcorr_is_848 | fc_div_2) + corr_i_cnt <= corr_i_cnt + 1; +end + // ADC data appears on the rising edge, so sample it on the falling edge always @(negedge adc_clk) @@ -110,24 +88,24 @@ begin // These are the correlators: we correlate against in-phase and quadrature // versions of our reference signal, and keep the (signed) result to // send out later over the SSP. - if(corr_i_cnt == 7'd63) + if(corr_i_cnt == 6'd0) begin if(snoop) begin - corr_i_out <= {corr_i_accum[12:6], after_hysteresis_prev}; - corr_q_out <= {corr_q_accum[12:6], after_hysteresis}; + // Send only 7 most significant bits of tag signal (signed), LSB is reader signal: + corr_i_out <= {corr_i_accum[13:7], after_hysteresis_prev_prev}; + corr_q_out <= {corr_q_accum[13:7], after_hysteresis_prev}; + after_hysteresis_prev_prev <= after_hysteresis; end else begin - // Only correlations need to be delivered. + // 8 most significant bits of tag signal corr_i_out <= corr_i_accum[13:6]; corr_q_out <= corr_q_accum[13:6]; end corr_i_accum <= adc_d; corr_q_accum <= adc_d; - corr_q_cnt <= 4; - corr_i_cnt <= 0; end else begin @@ -136,18 +114,16 @@ begin else corr_i_accum <= corr_i_accum + adc_d; - if(corr_q_cnt[3]) - corr_q_accum <= corr_q_accum - adc_d; - else + if(corr_i_cnt[3] == corr_i_cnt[2]) // phase shifted by pi/2 corr_q_accum <= corr_q_accum + adc_d; + else + corr_q_accum <= corr_q_accum - adc_d; - corr_i_cnt <= corr_i_cnt + 1; - corr_q_cnt <= corr_q_cnt + 1; end // The logic in hi_simulate.v reports 4 samples per bit. We report two // (I, Q) pairs per bit, so we should do 2 samples per pair. - if(corr_i_cnt == 6'd31) + if(corr_i_cnt == 6'd32) after_hysteresis_prev <= after_hysteresis; // Then the result from last time is serialized and send out to the ARM. @@ -168,7 +144,9 @@ begin end end - if(corr_i_cnt[5:2] == 4'b000 || corr_i_cnt[5:2] == 4'b1000) + // set ssp_frame signal for corr_i_cnt = 0..3 and corr_i_cnt = 32..35 + // (send two frames with 8 Bits each) + if(corr_i_cnt[5:2] == 4'b0000 || corr_i_cnt[5:2] == 4'b1000) ssp_frame = 1'b1; else ssp_frame = 1'b0; @@ -181,5 +159,6 @@ assign dbg = corr_i_cnt[3]; // Unused. assign pwr_lo = 1'b0; +assign pwr_oe2 = 1'b0; endmodule diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 357395d4..132e1805 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -100,7 +100,6 @@ typedef struct{ // For the 13.56 MHz tags #define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693 0x0300 -#define CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_14443 0x0301 #define CMD_READ_SRI512_TAG 0x0303 #define CMD_READ_SRIX4K_TAG 0x0304 #define CMD_ISO_14443B_COMMAND 0x0305 @@ -118,9 +117,8 @@ typedef struct{ #define CMD_SIMULATE_HITAG 0x0371 #define CMD_READER_HITAG 0x0372 -#define CMD_SIMULATE_TAG_HF_LISTEN 0x0380 -#define CMD_SIMULATE_TAG_ISO_14443 0x0381 -#define CMD_SNOOP_ISO_14443 0x0382 +#define CMD_SIMULATE_TAG_ISO_14443B 0x0381 +#define CMD_SNOOP_ISO_14443B 0x0382 #define CMD_SNOOP_ISO_14443a 0x0383 #define CMD_SIMULATE_TAG_ISO_14443a 0x0384 #define CMD_READER_ISO_14443a 0x0385