From: pwpiwi Date: Tue, 19 Nov 2019 17:11:26 +0000 (+0100) Subject: Merge pull request #884 from pwpiwi/fix_iclass_snoop X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/e938f7101179641c9478e9c914bc1bb3ee171570?hp=d3bcdbdabfccb09e93be14d6478eeccc0b131201 Merge pull request #884 from pwpiwi/fix_iclass_snoop * determine and write meaningful times into trace * code deduplication: use ISO15693 snoop function * speed up SnoopIso15693(), reduce DMA buffer size * add jamming option '-j' to 'hf iclass snoop' * fix issue #882 * whitespace fixes * make room for one more bit for FPGA minor mode * new mode FPGA_HF_READER_MODE_SEND_JAM * implement jamming in Handle15693SampleFromReader --- diff --git a/armsrc/Makefile b/armsrc/Makefile index 7348fda6..3d1ba79e 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -21,12 +21,12 @@ else SRC_LCD = endif SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c protocols.c -SRC_ISO15693 = iso15693.c iso15693tools.c +SRC_ISO15693 = iso15693.c SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c mifaresim.c SRC_ISO14443b = iso14443b.c SRC_CRAPTO1 = crypto1.c SRC_DES = platform_util_arm.c des.c -SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c parity.c +SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c parity.c iso15693tools.c SRC_SMARTCARD = i2c.c #the FPGA bitstream files. Note: order matters! @@ -43,7 +43,6 @@ APP_CFLAGS += -I../zlib # Compile these in thumb mode (small size) THUMBSRC = start.c \ $(SRC_LCD) \ - $(SRC_ISO15693) \ $(SRC_LF) \ $(SRC_ZLIB) \ $(SRC_SMARTCARD) \ @@ -54,6 +53,9 @@ THUMBSRC = start.c \ usb_cdc.c \ cmd.c +# Compile these in thumb mode optimized for speed (still smaller than ARM mode) +THUMBOPTSRC = $(SRC_ISO15693) + # These are to be compiled in ARM mode ARMSRC = fpgaloader.c \ legicrf.c \ @@ -72,7 +74,7 @@ ARMSRC = fpgaloader.c \ VERSIONSRC = version.c \ fpga_version_info.c -# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC +# Do not move this inclusion before the definition of {THUMB,THUMBOPT,ASM,ARM}SRC include ../common/Makefile.common OBJS = $(OBJDIR)/fullimage.s19 @@ -99,7 +101,7 @@ $(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) $(FPGA_COMPRESSOR): make -C ../client $(notdir $(FPGA_COMPRESSOR)) -$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) +$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(THUMBOPTOBJ) $(ARMOBJ) $(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) $(OBJDIR)/fullimage.nodata.bin: $(OBJDIR)/fullimage.stage1.elf diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 56da5434..589f394d 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1142,7 +1142,7 @@ void UsbPacketReceived(uint8_t *packet, int len) break; case CMD_SNOOP_ISO_15693: - SnoopIso15693(); + SnoopIso15693(0, NULL); break; case CMD_ISO_15693_COMMAND: @@ -1307,7 +1307,7 @@ void UsbPacketReceived(uint8_t *packet, int len) #ifdef WITH_ICLASS // Makes use of ISO14443a FPGA Firmware case CMD_SNOOP_ICLASS: - SnoopIClass(); + SnoopIClass(c->arg[0], c->d.asBytes); break; case CMD_SIMULATE_TAG_ICLASS: SimulateIClass(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 5ca0cce1..8693d6b5 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -115,8 +115,7 @@ void SetupSpi(int mode) // Set up the synchronous serial port with the set of options that fits // the FPGA mode. Both RX and TX are always enabled. //----------------------------------------------------------------------------- -void FpgaSetupSsc(uint8_t FPGA_mode) -{ +void FpgaSetupSsc(uint16_t FPGA_mode) { // First configure the GPIOs, and get ourselves a clock. AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_FRAME | @@ -136,7 +135,7 @@ void FpgaSetupSsc(uint8_t FPGA_mode) // 8, 16 or 32 bits per transfer, no loopback, MSB first, 1 transfer per sync // pulse, no output sync - if ((FPGA_mode & 0xe0) == FPGA_MAJOR_MODE_HF_READER && FpgaGetCurrent() == FPGA_BITSTREAM_HF) { + if ((FPGA_mode & 0x1c0) == FPGA_MAJOR_MODE_HF_READER && FpgaGetCurrent() == FPGA_BITSTREAM_HF) { AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); } else { AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); @@ -450,10 +449,9 @@ void FpgaDownloadAndGo(int bitstream_version) // The bit format is: C3 C2 C1 C0 D11 D10 D9 D8 D7 D6 D5 D4 D3 D2 D1 D0 // where C is the 4 bit command and D is the 12 bit data //----------------------------------------------------------------------------- -void FpgaSendCommand(uint16_t cmd, uint16_t v) -{ +void FpgaSendCommand(uint16_t cmd, uint16_t v) { SetupSpi(SPI_FPGA_MODE); - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete + while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v; // send the data } @@ -462,21 +460,18 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v) // vs. clone vs. etc.). This is now a special case of FpgaSendCommand() to // avoid changing this function's occurence everywhere in the source code. //----------------------------------------------------------------------------- -void FpgaWriteConfWord(uint16_t v) -{ +void FpgaWriteConfWord(uint16_t v) { FpgaSendCommand(FPGA_CMD_SET_CONFREG, v); } //----------------------------------------------------------------------------- // enable/disable FPGA internal tracing //----------------------------------------------------------------------------- -void FpgaEnableTracing(void) -{ +void FpgaEnableTracing(void) { FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 1); } -void FpgaDisableTracing(void) -{ +void FpgaDisableTracing(void) { FpgaSendCommand(FPGA_CMD_TRACE_ENABLE, 0); } diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 42f9ccc6..09eaec42 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -19,7 +19,7 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v); void FpgaWriteConfWord(uint16_t v); void FpgaDownloadAndGo(int bitstream_version); -void FpgaSetupSsc(uint8_t mode); +void FpgaSetupSsc(uint16_t mode); void SetupSpi(int mode); bool FpgaSetupSscDma(uint8_t *buf, uint16_t sample_count); void Fpga_print_status(); @@ -45,17 +45,17 @@ void SetAdcMuxFor(uint32_t whichGpio); // Definitions for the FPGA configuration word. // LF -#define FPGA_MAJOR_MODE_LF_ADC (0<<5) -#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5) -#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5) +#define FPGA_MAJOR_MODE_LF_ADC (0<<6) +#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<6) +#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<6) // HF -#define FPGA_MAJOR_MODE_HF_READER (0<<5) -#define FPGA_MAJOR_MODE_HF_SIMULATOR (1<<5) -#define FPGA_MAJOR_MODE_HF_ISO14443A (2<<5) -#define FPGA_MAJOR_MODE_HF_SNOOP (3<<5) -#define FPGA_MAJOR_MODE_HF_GET_TRACE (4<<5) +#define FPGA_MAJOR_MODE_HF_READER (0<<6) +#define FPGA_MAJOR_MODE_HF_SIMULATOR (1<<6) +#define FPGA_MAJOR_MODE_HF_ISO14443A (2<<6) +#define FPGA_MAJOR_MODE_HF_SNOOP (3<<6) +#define FPGA_MAJOR_MODE_HF_GET_TRACE (4<<6) // BOTH -#define FPGA_MAJOR_MODE_OFF (7<<5) +#define FPGA_MAJOR_MODE_OFF (7<<6) // Options for LF_ADC #define FPGA_LF_ADC_READER_FIELD (1<<0) @@ -74,10 +74,11 @@ void SetAdcMuxFor(uint32_t whichGpio); #define FPGA_HF_READER_MODE_SNOOP_IQ (5<<0) #define FPGA_HF_READER_MODE_SNOOP_AMPLITUDE (6<<0) #define FPGA_HF_READER_MODE_SNOOP_PHASE (7<<0) +#define FPGA_HF_READER_MODE_SEND_JAM (8<<0) -#define FPGA_HF_READER_SUBCARRIER_848_KHZ (0<<3) -#define FPGA_HF_READER_SUBCARRIER_424_KHZ (1<<3) -#define FPGA_HF_READER_SUBCARRIER_212_KHZ (2<<3) +#define FPGA_HF_READER_SUBCARRIER_848_KHZ (0<<4) +#define FPGA_HF_READER_SUBCARRIER_424_KHZ (1<<4) +#define FPGA_HF_READER_SUBCARRIER_212_KHZ (2<<4) // Options for the HF simulated tag, how to modulate #define FPGA_HF_SIMULATOR_NO_MODULATION (0<<0) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 430597c1..6a2fd648 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -69,693 +69,18 @@ #define ICLASS_READER_TIMEOUT_UPDATE 3390 // 16000us, nominal 4-15ms #define ICLASS_READER_TIMEOUT_OTHERS 80 // 380us, nominal 330us +#define ICLASS_BUFFER_SIZE 34 // we expect max 34 bytes as tag answer (response to READ4) -//----------------------------------------------------------------------------- -// The software UART that receives commands from the reader, and its state -// variables. -//----------------------------------------------------------------------------- -static struct { - enum { - STATE_UNSYNCD, - STATE_START_OF_COMMUNICATION, - STATE_RECEIVING - } state; - uint16_t shiftReg; - int bitCnt; - int byteCnt; - int byteCntMax; - int posCnt; - int nOutOfCnt; - int OutOfCnt; - int syncBit; - int samples; - int highCnt; - int swapper; - int counter; - int bitBuffer; - int dropPosition; - uint8_t *output; -} Uart; - -static RAMFUNC int OutOfNDecoding(int bit) { - //int error = 0; - int bitright; - - if (!Uart.bitBuffer) { - Uart.bitBuffer = bit ^ 0xFF0; - return false; - } else { - Uart.bitBuffer <<= 4; - Uart.bitBuffer ^= bit; - } - - /*if (Uart.swapper) { - Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF; - Uart.byteCnt++; - Uart.swapper = 0; - if (Uart.byteCnt > 15) { return true; } - } - else { - Uart.swapper = 1; - }*/ - - if (Uart.state != STATE_UNSYNCD) { - Uart.posCnt++; - - if ((Uart.bitBuffer & Uart.syncBit) ^ Uart.syncBit) { - bit = 0x00; - } else { - bit = 0x01; - } - if (((Uart.bitBuffer << 1) & Uart.syncBit) ^ Uart.syncBit) { - bitright = 0x00; - } else { - bitright = 0x01; - } - if (bit != bitright) { - bit = bitright; - } - - - // So, now we only have to deal with *bit*, lets see... - if (Uart.posCnt == 1) { - // measurement first half bitperiod - if (!bit) { - // Drop in first half means that we are either seeing - // an SOF or an EOF. - - if (Uart.nOutOfCnt == 1) { - // End of Communication - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - if (Uart.byteCnt == 0) { - // Its not straightforward to show single EOFs - // So just leave it and do not return true - Uart.output[0] = 0xf0; - Uart.byteCnt++; - } else { - return true; - } - } else if (Uart.state != STATE_START_OF_COMMUNICATION) { - // When not part of SOF or EOF, it is an error - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - //error = 4; - } - } - } else { - // measurement second half bitperiod - // Count the bitslot we are in... (ISO 15693) - Uart.nOutOfCnt++; - - if (!bit) { - if (Uart.dropPosition) { - if (Uart.state == STATE_START_OF_COMMUNICATION) { - //error = 1; - } else { - //error = 7; - } - // It is an error if we already have seen a drop in current frame - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - } else { - Uart.dropPosition = Uart.nOutOfCnt; - } - } - - Uart.posCnt = 0; - - - if (Uart.nOutOfCnt == Uart.OutOfCnt && Uart.OutOfCnt == 4) { - Uart.nOutOfCnt = 0; - - if (Uart.state == STATE_START_OF_COMMUNICATION) { - if (Uart.dropPosition == 4) { - Uart.state = STATE_RECEIVING; - Uart.OutOfCnt = 256; - } else if (Uart.dropPosition == 3) { - Uart.state = STATE_RECEIVING; - Uart.OutOfCnt = 4; - //Uart.output[Uart.byteCnt] = 0xdd; - //Uart.byteCnt++; - } else { - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - } - Uart.dropPosition = 0; - } else { - // RECEIVING DATA - // 1 out of 4 - if (!Uart.dropPosition) { - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - //error = 9; - } else { - Uart.shiftReg >>= 2; - - // Swap bit order - Uart.dropPosition--; - //if (Uart.dropPosition == 1) { Uart.dropPosition = 2; } - //else if (Uart.dropPosition == 2) { Uart.dropPosition = 1; } - - Uart.shiftReg ^= ((Uart.dropPosition & 0x03) << 6); - Uart.bitCnt += 2; - Uart.dropPosition = 0; - - if (Uart.bitCnt == 8) { - Uart.output[Uart.byteCnt] = (Uart.shiftReg & 0xff); - Uart.byteCnt++; - Uart.bitCnt = 0; - Uart.shiftReg = 0; - } - } - } - } else if (Uart.nOutOfCnt == Uart.OutOfCnt) { - // RECEIVING DATA - // 1 out of 256 - if (!Uart.dropPosition) { - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - //error = 3; - } else { - Uart.dropPosition--; - Uart.output[Uart.byteCnt] = (Uart.dropPosition & 0xff); - Uart.byteCnt++; - Uart.bitCnt = 0; - Uart.shiftReg = 0; - Uart.nOutOfCnt = 0; - Uart.dropPosition = 0; - } - } - - /*if (error) { - Uart.output[Uart.byteCnt] = 0xAA; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = error & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = 0xAA; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = (Uart.bitBuffer >> 8) & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = (Uart.syncBit >> 3) & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = 0xAA; - Uart.byteCnt++; - return true; - }*/ - } - - } else { - bit = Uart.bitBuffer & 0xf0; - bit >>= 4; - bit ^= 0x0F; // drops become 1s ;-) - if (bit) { - // should have been high or at least (4 * 128) / fc - // according to ISO this should be at least (9 * 128 + 20) / fc - if (Uart.highCnt == 8) { - // we went low, so this could be start of communication - // it turns out to be safer to choose a less significant - // syncbit... so we check whether the neighbour also represents the drop - Uart.posCnt = 1; // apparently we are busy with our first half bit period - Uart.syncBit = bit & 8; - Uart.samples = 3; - if (!Uart.syncBit) { Uart.syncBit = bit & 4; Uart.samples = 2; } - else if (bit & 4) { Uart.syncBit = bit & 4; Uart.samples = 2; bit <<= 2; } - if (!Uart.syncBit) { Uart.syncBit = bit & 2; Uart.samples = 1; } - else if (bit & 2) { Uart.syncBit = bit & 2; Uart.samples = 1; bit <<= 1; } - if (!Uart.syncBit) { Uart.syncBit = bit & 1; Uart.samples = 0; - if (Uart.syncBit && (Uart.bitBuffer & 8)) { - Uart.syncBit = 8; - - // the first half bit period is expected in next sample - Uart.posCnt = 0; - Uart.samples = 3; - } - } else if (bit & 1) { Uart.syncBit = bit & 1; Uart.samples = 0; } - - Uart.syncBit <<= 4; - Uart.state = STATE_START_OF_COMMUNICATION; - Uart.bitCnt = 0; - Uart.byteCnt = 0; - Uart.nOutOfCnt = 0; - Uart.OutOfCnt = 4; // Start at 1/4, could switch to 1/256 - Uart.dropPosition = 0; - Uart.shiftReg = 0; - //error = 0; - } else { - Uart.highCnt = 0; - } - } else if (Uart.highCnt < 8) { - Uart.highCnt++; - } - } - - return false; -} - - -//============================================================================= -// Manchester -//============================================================================= - -static struct { - enum { - DEMOD_UNSYNCD, - DEMOD_START_OF_COMMUNICATION, - DEMOD_START_OF_COMMUNICATION2, - DEMOD_START_OF_COMMUNICATION3, - DEMOD_SOF_COMPLETE, - DEMOD_MANCHESTER_D, - DEMOD_MANCHESTER_E, - DEMOD_END_OF_COMMUNICATION, - DEMOD_END_OF_COMMUNICATION2, - DEMOD_MANCHESTER_F, - DEMOD_ERROR_WAIT - } state; - int bitCount; - int posCount; - int syncBit; - uint16_t shiftReg; - int buffer; - int buffer2; - int buffer3; - int buff; - int samples; - int len; - enum { - SUB_NONE, - SUB_FIRST_HALF, - SUB_SECOND_HALF, - SUB_BOTH - } sub; - uint8_t *output; -} Demod; - -static RAMFUNC int ManchesterDecoding(int v) { - int bit; - int modulation; - int error = 0; - - bit = Demod.buffer; - Demod.buffer = Demod.buffer2; - Demod.buffer2 = Demod.buffer3; - Demod.buffer3 = v; - - if (Demod.buff < 3) { - Demod.buff++; - return false; - } - - if (Demod.state==DEMOD_UNSYNCD) { - Demod.output[Demod.len] = 0xfa; - Demod.syncBit = 0; - //Demod.samples = 0; - Demod.posCount = 1; // This is the first half bit period, so after syncing handle the second part - - if (bit & 0x08) { - Demod.syncBit = 0x08; - } - - if (bit & 0x04) { - if (Demod.syncBit) { - bit <<= 4; - } - Demod.syncBit = 0x04; - } - - if (bit & 0x02) { - if (Demod.syncBit) { - bit <<= 2; - } - Demod.syncBit = 0x02; - } - - if (bit & 0x01 && Demod.syncBit) { - Demod.syncBit = 0x01; - } - - if (Demod.syncBit) { - Demod.len = 0; - Demod.state = DEMOD_START_OF_COMMUNICATION; - Demod.sub = SUB_FIRST_HALF; - Demod.bitCount = 0; - Demod.shiftReg = 0; - Demod.samples = 0; - if (Demod.posCount) { - switch (Demod.syncBit) { - case 0x08: Demod.samples = 3; break; - case 0x04: Demod.samples = 2; break; - case 0x02: Demod.samples = 1; break; - case 0x01: Demod.samples = 0; break; - } - // SOF must be long burst... otherwise stay unsynced!!! - if (!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit)) { - Demod.state = DEMOD_UNSYNCD; - } - } else { - // SOF must be long burst... otherwise stay unsynced!!! - if (!(Demod.buffer2 & Demod.syncBit) || !(Demod.buffer3 & Demod.syncBit)) { - Demod.state = DEMOD_UNSYNCD; - error = 0x88; - } - - } - error = 0; - - } - } else { - // state is DEMOD is in SYNC from here on. - modulation = bit & Demod.syncBit; - modulation |= ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit; - - Demod.samples += 4; - - if (Demod.posCount == 0) { - Demod.posCount = 1; - if (modulation) { - Demod.sub = SUB_FIRST_HALF; - } else { - Demod.sub = SUB_NONE; - } - } else { - Demod.posCount = 0; - if (modulation) { - if (Demod.sub == SUB_FIRST_HALF) { - Demod.sub = SUB_BOTH; - } else { - Demod.sub = SUB_SECOND_HALF; - } - } else if (Demod.sub == SUB_NONE) { - if (Demod.state == DEMOD_SOF_COMPLETE) { - Demod.output[Demod.len] = 0x0f; - Demod.len++; - Demod.state = DEMOD_UNSYNCD; - return true; - } else { - Demod.state = DEMOD_ERROR_WAIT; - error = 0x33; - } - } - - switch(Demod.state) { - case DEMOD_START_OF_COMMUNICATION: - if (Demod.sub == SUB_BOTH) { - Demod.state = DEMOD_START_OF_COMMUNICATION2; - Demod.posCount = 1; - Demod.sub = SUB_NONE; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; - error = 0xd2; - } - break; - case DEMOD_START_OF_COMMUNICATION2: - if (Demod.sub == SUB_SECOND_HALF) { - Demod.state = DEMOD_START_OF_COMMUNICATION3; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; - error = 0xd3; - } - break; - case DEMOD_START_OF_COMMUNICATION3: - if (Demod.sub == SUB_SECOND_HALF) { - Demod.state = DEMOD_SOF_COMPLETE; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; - error = 0xd4; - } - break; - case DEMOD_SOF_COMPLETE: - case DEMOD_MANCHESTER_D: - case DEMOD_MANCHESTER_E: - // OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443) - // 00001111 = 1 (0 in 14443) - if (Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF - Demod.bitCount++; - Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100; - Demod.state = DEMOD_MANCHESTER_D; - } else if (Demod.sub == SUB_FIRST_HALF) { // SUB_SECOND_HALF - Demod.bitCount++; - Demod.shiftReg >>= 1; - Demod.state = DEMOD_MANCHESTER_E; - } else if (Demod.sub == SUB_BOTH) { - Demod.state = DEMOD_MANCHESTER_F; - } else { - Demod.state = DEMOD_ERROR_WAIT; - error = 0x55; - } - break; - - case DEMOD_MANCHESTER_F: - // Tag response does not need to be a complete byte! - if (Demod.len > 0 || Demod.bitCount > 0) { - if (Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF - Demod.shiftReg >>= (9 - Demod.bitCount); // right align data - Demod.output[Demod.len] = Demod.shiftReg & 0xff; - Demod.len++; - } - - Demod.state = DEMOD_UNSYNCD; - return true; - } else { - Demod.output[Demod.len] = 0xad; - Demod.state = DEMOD_ERROR_WAIT; - error = 0x03; - } - break; - - case DEMOD_ERROR_WAIT: - Demod.state = DEMOD_UNSYNCD; - break; - - default: - Demod.output[Demod.len] = 0xdd; - Demod.state = DEMOD_UNSYNCD; - break; - } - - if (Demod.bitCount >= 8) { - Demod.shiftReg >>= 1; - Demod.output[Demod.len] = (Demod.shiftReg & 0xff); - Demod.len++; - Demod.bitCount = 0; - Demod.shiftReg = 0; - } - - if (error) { - Demod.output[Demod.len] = 0xBB; - Demod.len++; - Demod.output[Demod.len] = error & 0xFF; - Demod.len++; - Demod.output[Demod.len] = 0xBB; - Demod.len++; - Demod.output[Demod.len] = bit & 0xFF; - Demod.len++; - Demod.output[Demod.len] = Demod.buffer & 0xFF; - Demod.len++; - // Look harder ;-) - Demod.output[Demod.len] = Demod.buffer2 & 0xFF; - Demod.len++; - Demod.output[Demod.len] = Demod.syncBit & 0xFF; - Demod.len++; - Demod.output[Demod.len] = 0xBB; - Demod.len++; - return true; - } - - } - - } // end (state != UNSYNCED) - - return false; -} //============================================================================= -// Finally, a `sniffer' for iClass communication +// A `sniffer' for iClass communication // Both sides of communication! //============================================================================= - -//----------------------------------------------------------------------------- -// Record the sequence of commands sent by the reader to the tag, with -// triggering so that we start recording at the point that the tag is moved -// near the reader. -//----------------------------------------------------------------------------- -void RAMFUNC SnoopIClass(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 = false; // false to wait first for card - - // The command (reader -> tag) that we're receiving. - // The length of a received command will in most cases be no more than 18 bytes. - // So 32 should be enough! - #define ICLASS_BUFFER_SIZE 32 - uint8_t readerToTagCmd[ICLASS_BUFFER_SIZE]; - // The response (tag -> reader) that we're receiving. - uint8_t tagToReaderResponse[ICLASS_BUFFER_SIZE]; - - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - - // free all BigBuf memory - BigBuf_free(); - // The DMA buffer, used to stream samples from the FPGA - uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); - - set_tracing(true); - clear_trace(); - iso14a_set_trigger(false); - - int lastRxCounter; - uint8_t *upTo; - int smpl; - int maxBehindBy = 0; - - // Count of samples received so far, so that we can include timing - // information in the trace buffer. - int samples = 0; - rsamples = 0; - - // Set up the demodulator for tag -> reader responses. - Demod.output = tagToReaderResponse; - Demod.len = 0; - Demod.state = DEMOD_UNSYNCD; - - // Setup for the DMA. - FpgaSetupSsc(FPGA_MAJOR_MODE_HF_ISO14443A); - upTo = dmaBuf; - lastRxCounter = DMA_BUFFER_SIZE; - FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); - - // And the reader -> tag commands - memset(&Uart, 0, sizeof(Uart)); - Uart.output = readerToTagCmd; - Uart.byteCntMax = 32; // was 100 (greg)//////////////////////////////////////////////////////////////////////// - Uart.state = STATE_UNSYNCD; - - // And put the FPGA in the appropriate mode - // Signal field is off with the appropriate LED - LED_D_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER); - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - - uint32_t time_0 = GetCountSspClk(); - uint32_t time_start = 0; - uint32_t time_stop = 0; - - int div = 0; - //int div2 = 0; - int decbyte = 0; - int decbyter = 0; - - // And now we loop, receiving samples. - for (;;) { - LED_A_ON(); - WDT_HIT(); - int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & (DMA_BUFFER_SIZE-1); - if (behindBy > maxBehindBy) { - maxBehindBy = behindBy; - if (behindBy > (9 * DMA_BUFFER_SIZE / 10)) { - Dbprintf("blew circular buffer! behindBy=0x%x", behindBy); - goto done; - } - } - if (behindBy < 1) continue; - - LED_A_OFF(); - smpl = upTo[0]; - upTo++; - lastRxCounter -= 1; - if (upTo - dmaBuf > DMA_BUFFER_SIZE) { - upTo -= DMA_BUFFER_SIZE; - lastRxCounter += DMA_BUFFER_SIZE; - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; - } - - //samples += 4; - samples += 1; - - if (smpl & 0xF) { - decbyte ^= (1 << (3 - div)); - } - - // FOR READER SIDE COMMUMICATION... - - decbyter <<= 2; - decbyter ^= (smpl & 0x30); - - div++; - - if ((div + 1) % 2 == 0) { - smpl = decbyter; - if (OutOfNDecoding((smpl & 0xF0) >> 4)) { - rsamples = samples - Uart.samples; - time_stop = (GetCountSspClk()-time_0) << 4; - - //if (!LogTrace(Uart.output, Uart.byteCnt, rsamples, Uart.parityBits,true)) break; - //if (!LogTrace(NULL, 0, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, 0, true)) break; - uint8_t parity[MAX_PARITY_SIZE]; - GetParity(Uart.output, Uart.byteCnt, parity); - LogTrace_ISO15693(Uart.output, Uart.byteCnt, time_start*32, time_stop*32, parity, true); - - /* And ready to receive another command. */ - Uart.state = STATE_UNSYNCD; - /* And also reset the demod code, which might have been */ - /* false-triggered by the commands from the reader. */ - Demod.state = DEMOD_UNSYNCD; - Uart.byteCnt = 0; - } else { - time_start = (GetCountSspClk()-time_0) << 4; - } - decbyter = 0; - } - - if (div > 3) { - smpl = decbyte; - if (ManchesterDecoding(smpl & 0x0F)) { - time_stop = (GetCountSspClk()-time_0) << 4; - - rsamples = samples - Demod.samples; - - uint8_t parity[MAX_PARITY_SIZE]; - GetParity(Demod.output, Demod.len, parity); - LogTrace_ISO15693(Demod.output, Demod.len, time_start*32, time_stop*32, parity, false); - - // And ready to receive another response. - memset(&Demod, 0, sizeof(Demod)); - Demod.output = tagToReaderResponse; - Demod.state = DEMOD_UNSYNCD; - } else { - time_start = (GetCountSspClk()-time_0) << 4; - } - - div = 0; - decbyte = 0x00; - } - - if (BUTTON_PRESS()) { - DbpString("cancelled_a"); - goto done; - } - } - - DbpString("COMMAND FINISHED"); - - Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt); - Dbprintf("%x %x %x", Uart.byteCntMax, BigBuf_get_traceLen(), (int)Uart.output[0]); - -done: - AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; - Dbprintf("%x %x %x", maxBehindBy, Uart.state, Uart.byteCnt); - Dbprintf("%x %x %x", Uart.byteCntMax, BigBuf_get_traceLen(), (int)Uart.output[0]); - LEDsoff(); +void SnoopIClass(uint8_t jam_search_len, uint8_t *jam_search_string) { + SnoopIso15693(jam_search_len, jam_search_string); } + void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN) { int i; for (i = 0; i < 8; i++) { @@ -763,6 +88,7 @@ void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN) { } } + // Encode SOF only static void CodeIClassTagSOF() { ToSendReset(); @@ -770,6 +96,7 @@ static void CodeIClassTagSOF() { ToSendMax++; } + static void AppendCrc(uint8_t *data, int len) { ComputeCrc14443(CRC_ICLASS, data, len, data+len, data+len+1); } diff --git a/armsrc/iclass.h b/armsrc/iclass.h index 9666e888..541e1a2c 100644 --- a/armsrc/iclass.h +++ b/armsrc/iclass.h @@ -16,9 +16,8 @@ #include #include -#include "common.h" // for RAMFUNC -extern void RAMFUNC SnoopIClass(void); +extern void SnoopIClass(uint8_t jam_search_len, uint8_t *jam_search_string); extern void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); extern void ReaderIClass(uint8_t arg0); extern void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC); diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index bb5bdfe2..f10b0206 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -69,31 +69,35 @@ #define DELAY_READER_TO_ARM 8 #define DELAY_ARM_TO_READER 0 //SSP_CLK runs at 13.56MHz / 4 = 3,39MHz when acting as reader. All values should be multiples of 16 -#define DELAY_TAG_TO_ARM 32 #define DELAY_ARM_TO_TAG 16 +#define DELAY_TAG_TO_ARM 32 +//SSP_CLK runs at 13.56MHz / 4 = 3,39MHz when snooping. All values should be multiples of 16 +#define DELAY_TAG_TO_ARM_SNOOP 32 +#define DELAY_READER_TO_ARM_SNOOP 32 static int DEBUG = 0; -// specific LogTrace function for ISO15693: the duration needs to be scaled because otherwise it won't fit into a uint16_t -bool LogTrace_ISO15693(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag) { - uint32_t duration = timestamp_end - timestamp_start; - duration /= 32; - timestamp_end = timestamp_start + duration; - return LogTrace(btBytes, iLen, timestamp_start, timestamp_end, parity, readerToTag); -} - - /////////////////////////////////////////////////////////////////////// // ISO 15693 Part 2 - Air Interface // This section basically contains transmission and receiving of bits /////////////////////////////////////////////////////////////////////// // buffers -#define ISO15693_DMA_BUFFER_SIZE 2048 // must be a power of 2 +#define ISO15693_DMA_BUFFER_SIZE 256 // must be a power of 2 #define ISO15693_MAX_RESPONSE_LENGTH 36 // allows read single block with the maximum block size of 256bits. Read multiple blocks not supported yet #define ISO15693_MAX_COMMAND_LENGTH 45 // allows write single block with the maximum block size of 256bits. Write multiple blocks not supported yet + +// specific LogTrace function for ISO15693: the duration needs to be scaled because otherwise it won't fit into a uint16_t +bool LogTrace_ISO15693(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag) { + uint32_t duration = timestamp_end - timestamp_start; + duration /= 32; + timestamp_end = timestamp_start + duration; + return LogTrace(btBytes, iLen, timestamp_start, timestamp_end, parity, readerToTag); +} + + // --------------------------- // Signal Processing // --------------------------- @@ -383,14 +387,13 @@ typedef struct DecodeTag { } DecodeTag_t; -static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *DecodeTag) -{ - switch(DecodeTag->state) { +static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint16_t amplitude, DecodeTag_t *DecodeTag) { + switch (DecodeTag->state) { case STATE_TAG_SOF_LOW: // waiting for a rising edge if (amplitude > NOISE_THRESHOLD + DecodeTag->previous_amplitude) { if (DecodeTag->posCount > 10) { - DecodeTag->threshold_sof = amplitude - DecodeTag->previous_amplitude; + DecodeTag->threshold_sof = amplitude - DecodeTag->previous_amplitude; // to be divided by 2 DecodeTag->threshold_half = 0; DecodeTag->state = STATE_TAG_SOF_RISING_EDGE; } else { @@ -403,8 +406,8 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1 break; case STATE_TAG_SOF_RISING_EDGE: - if (amplitude - DecodeTag->previous_amplitude > DecodeTag->threshold_sof) { // edge still rising - if (amplitude - DecodeTag->threshold_sof > DecodeTag->threshold_sof) { // steeper edge, take this as time reference + if (amplitude > DecodeTag->threshold_sof + DecodeTag->previous_amplitude) { // edge still rising + if (amplitude > DecodeTag->threshold_sof + DecodeTag->threshold_sof) { // steeper edge, take this as time reference DecodeTag->posCount = 1; } else { DecodeTag->posCount = 2; @@ -447,7 +450,7 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1 DecodeTag->sum2 = 0; DecodeTag->posCount = 2; DecodeTag->state = STATE_TAG_RECEIVING_DATA; - FpgaDisableTracing(); // DEBUGGING + // FpgaDisableTracing(); // DEBUGGING // Dbprintf("amplitude = %d, threshold_sof = %d, threshold_half/4 = %d, previous_amplitude = %d", // amplitude, // DecodeTag->threshold_sof, @@ -466,6 +469,12 @@ static int inline __attribute__((always_inline)) Handle15693SamplesFromTag(uint1 break; case STATE_TAG_RECEIVING_DATA: + // FpgaDisableTracing(); // DEBUGGING + // Dbprintf("amplitude = %d, threshold_sof = %d, threshold_half/4 = %d, previous_amplitude = %d", + // amplitude, + // DecodeTag->threshold_sof, + // DecodeTag->threshold_half/4, + // DecodeTag->previous_amplitude); // DEBUGGING if (DecodeTag->posCount == 1) { DecodeTag->sum1 = 0; DecodeTag->sum2 = 0; @@ -658,7 +667,7 @@ int GetIso15693AnswerFromTag(uint8_t* response, uint16_t max_len, uint16_t timeo if(upTo >= dmaBuf + ISO15693_DMA_BUFFER_SIZE) { // we have read all of the DMA buffer content. upTo = dmaBuf; // start reading the circular buffer from the beginning - if(behindBy > (9*ISO15693_DMA_BUFFER_SIZE/10)) { + if (behindBy > (9*ISO15693_DMA_BUFFER_SIZE/10)) { Dbprintf("About to blow circular buffer - aborted! behindBy=%d", behindBy); ret = -1; break; @@ -731,7 +740,8 @@ typedef struct DecodeReader { STATE_READER_AWAIT_2ND_RISING_EDGE_OF_SOF, STATE_READER_AWAIT_END_OF_SOF_1_OUT_OF_4, STATE_READER_RECEIVE_DATA_1_OUT_OF_4, - STATE_READER_RECEIVE_DATA_1_OUT_OF_256 + STATE_READER_RECEIVE_DATA_1_OUT_OF_256, + STATE_READER_RECEIVE_JAMMING } state; enum { CODING_1_OUT_OF_4, @@ -744,11 +754,12 @@ typedef struct DecodeReader { int posCount; int sum1, sum2; uint8_t *output; + uint8_t jam_search_len; + uint8_t *jam_search_string; } DecodeReader_t; -static void DecodeReaderInit(DecodeReader_t* DecodeReader, uint8_t *data, uint16_t max_len) -{ +static void DecodeReaderInit(DecodeReader_t* DecodeReader, uint8_t *data, uint16_t max_len, uint8_t jam_search_len, uint8_t *jam_search_string) { DecodeReader->output = data; DecodeReader->byteCountMax = max_len; DecodeReader->state = STATE_READER_UNSYNCD; @@ -756,17 +767,17 @@ static void DecodeReaderInit(DecodeReader_t* DecodeReader, uint8_t *data, uint16 DecodeReader->bitCount = 0; DecodeReader->posCount = 1; DecodeReader->shiftReg = 0; + DecodeReader->jam_search_len = jam_search_len; + DecodeReader->jam_search_string = jam_search_string; } -static void DecodeReaderReset(DecodeReader_t* DecodeReader) -{ +static void DecodeReaderReset(DecodeReader_t* DecodeReader) { DecodeReader->state = STATE_READER_UNSYNCD; } -static int inline __attribute__((always_inline)) Handle15693SampleFromReader(uint8_t bit, DecodeReader_t *restrict DecodeReader) -{ +static int inline __attribute__((always_inline)) Handle15693SampleFromReader(bool bit, DecodeReader_t *DecodeReader) { switch (DecodeReader->state) { case STATE_READER_UNSYNCD: // wait for unmodulated carrier @@ -881,16 +892,15 @@ static int inline __attribute__((always_inline)) Handle15693SampleFromReader(uin break; case STATE_READER_RECEIVE_DATA_1_OUT_OF_4: - bit = !!bit; DecodeReader->posCount++; if (DecodeReader->posCount == 1) { - DecodeReader->sum1 = bit; + DecodeReader->sum1 = bit?1:0; } else if (DecodeReader->posCount <= 4) { - DecodeReader->sum1 += bit; + if (bit) DecodeReader->sum1++; } else if (DecodeReader->posCount == 5) { - DecodeReader->sum2 = bit; + DecodeReader->sum2 = bit?1:0; } else { - DecodeReader->sum2 += bit; + if (bit) DecodeReader->sum2++; } if (DecodeReader->posCount == 8) { DecodeReader->posCount = 0; @@ -900,8 +910,7 @@ static int inline __attribute__((always_inline)) Handle15693SampleFromReader(uin if (DecodeReader->byteCount != 0) { return true; } - } - if (DecodeReader->sum1 >= 3 && DecodeReader->sum2 <= 1) { // detected a 2bit position + } else if (DecodeReader->sum1 >= 3 && DecodeReader->sum2 <= 1) { // detected a 2bit position DecodeReader->shiftReg >>= 2; DecodeReader->shiftReg |= (DecodeReader->bitCount << 6); } @@ -914,6 +923,13 @@ static int inline __attribute__((always_inline)) Handle15693SampleFromReader(uin } DecodeReader->bitCount = 0; DecodeReader->shiftReg = 0; + if (DecodeReader->byteCount == DecodeReader->jam_search_len) { + if (!memcmp(DecodeReader->output, DecodeReader->jam_search_string, DecodeReader->jam_search_len)) { + LED_D_ON(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_JAM); + DecodeReader->state = STATE_READER_RECEIVE_JAMMING; + } + } } else { DecodeReader->bitCount++; } @@ -921,16 +937,15 @@ static int inline __attribute__((always_inline)) Handle15693SampleFromReader(uin break; case STATE_READER_RECEIVE_DATA_1_OUT_OF_256: - bit = !!bit; DecodeReader->posCount++; if (DecodeReader->posCount == 1) { - DecodeReader->sum1 = bit; + DecodeReader->sum1 = bit?1:0; } else if (DecodeReader->posCount <= 4) { - DecodeReader->sum1 += bit; + if (bit) DecodeReader->sum1++; } else if (DecodeReader->posCount == 5) { - DecodeReader->sum2 = bit; - } else { - DecodeReader->sum2 += bit; + DecodeReader->sum2 = bit?1:0; + } else if (bit) { + DecodeReader->sum2++; } if (DecodeReader->posCount == 8) { DecodeReader->posCount = 0; @@ -940,8 +955,7 @@ static int inline __attribute__((always_inline)) Handle15693SampleFromReader(uin if (DecodeReader->byteCount != 0) { return true; } - } - if (DecodeReader->sum1 >= 3 && DecodeReader->sum2 <= 1) { // detected the bit position + } else if (DecodeReader->sum1 >= 3 && DecodeReader->sum2 <= 1) { // detected the bit position DecodeReader->shiftReg = DecodeReader->bitCount; } if (DecodeReader->bitCount == 255) { // we have a full byte @@ -951,11 +965,42 @@ static int inline __attribute__((always_inline)) Handle15693SampleFromReader(uin LED_B_OFF(); DecodeReaderReset(DecodeReader); } + if (DecodeReader->byteCount == DecodeReader->jam_search_len) { + if (!memcmp(DecodeReader->output, DecodeReader->jam_search_string, DecodeReader->jam_search_len)) { + LED_D_ON(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_JAM); + DecodeReader->state = STATE_READER_RECEIVE_JAMMING; + } + } } DecodeReader->bitCount++; } break; + case STATE_READER_RECEIVE_JAMMING: + DecodeReader->posCount++; + if (DecodeReader->Coding == CODING_1_OUT_OF_4) { + if (DecodeReader->posCount == 7*16) { // 7 bits jammed + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNOOP_AMPLITUDE); // stop jamming + // FpgaDisableTracing(); + LED_D_OFF(); + } else if (DecodeReader->posCount == 8*16) { + DecodeReader->posCount = 0; + DecodeReader->output[DecodeReader->byteCount++] = 0x00; + DecodeReader->state = STATE_READER_RECEIVE_DATA_1_OUT_OF_4; + } + } else { + if (DecodeReader->posCount == 7*256) { // 7 bits jammend + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNOOP_AMPLITUDE); // stop jamming + LED_D_OFF(); + } else if (DecodeReader->posCount == 8*256) { + DecodeReader->posCount = 0; + DecodeReader->output[DecodeReader->byteCount++] = 0x00; + DecodeReader->state = STATE_READER_RECEIVE_DATA_1_OUT_OF_256; + } + } + break; + default: LED_B_OFF(); DecodeReaderReset(DecodeReader); @@ -985,7 +1030,7 @@ int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eo // the decoder data structure DecodeReader_t DecodeReader = {0}; - DecodeReaderInit(&DecodeReader, received, max_len); + DecodeReaderInit(&DecodeReader, received, max_len, 0, NULL); // wait for last transfer to complete while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXEMPTY)); @@ -1126,19 +1171,17 @@ void AcquireRawAdcSamplesIso15693(void) } -void SnoopIso15693(void) -{ +void SnoopIso15693(uint8_t jam_search_len, uint8_t *jam_search_string) { + LED_A_ON(); - + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - BigBuf_free(); clear_trace(); set_tracing(true); // The DMA buffer, used to stream samples from the FPGA - uint16_t* dmaBuf = (uint16_t*)BigBuf_malloc(ISO15693_DMA_BUFFER_SIZE*sizeof(uint16_t)); - uint16_t *upTo; + uint16_t dmaBuf[ISO15693_DMA_BUFFER_SIZE]; // Count of samples received so far, so that we can include timing // information in the trace buffer. @@ -1148,9 +1191,9 @@ void SnoopIso15693(void) uint8_t response[ISO15693_MAX_RESPONSE_LENGTH]; DecodeTagInit(&DecodeTag, response, sizeof(response)); - DecodeReader_t DecodeReader = {0};; + DecodeReader_t DecodeReader = {0}; uint8_t cmd[ISO15693_MAX_COMMAND_LENGTH]; - DecodeReaderInit(&DecodeReader, cmd, sizeof(cmd)); + DecodeReaderInit(&DecodeReader, cmd, sizeof(cmd), jam_search_len, jam_search_string); // Print some debug information about the buffer sizes if (DEBUG) { @@ -1163,28 +1206,41 @@ void SnoopIso15693(void) Dbprintf("Snoop started. Press PM3 Button to stop."); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SNOOP_AMPLITUDE); + LED_D_OFF(); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - - // Setup for the DMA. FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER); - upTo = dmaBuf; + StartCountSspClk(); FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE); bool TagIsActive = false; bool ReaderIsActive = false; bool ExpectTagAnswer = false; + uint32_t dma_start_time = 0; + uint16_t *upTo = dmaBuf; + uint16_t max_behindBy = 0; + // And now we loop, receiving samples. for(;;) { uint16_t behindBy = ((uint16_t*)AT91C_BASE_PDC_SSC->PDC_RPR - upTo) & (ISO15693_DMA_BUFFER_SIZE-1); - + if (behindBy > max_behindBy) { + max_behindBy = behindBy; + } + if (behindBy == 0) continue; + samples++; + if (samples == 1) { + // DMA has transferred the very first data + dma_start_time = GetCountSspClk() & 0xfffffff0; + } + uint16_t snoopdata = *upTo++; - if(upTo >= dmaBuf + ISO15693_DMA_BUFFER_SIZE) { // we have read all of the DMA buffer content. + if (upTo >= dmaBuf + ISO15693_DMA_BUFFER_SIZE) { // we have read all of the DMA buffer content. upTo = dmaBuf; // start reading the circular buffer from the beginning - if(behindBy > (9*ISO15693_DMA_BUFFER_SIZE/10)) { + if (behindBy > (9*ISO15693_DMA_BUFFER_SIZE/10)) { + // FpgaDisableTracing(); Dbprintf("About to blow circular buffer - aborted! behindBy=%d, samples=%d", behindBy, samples); break; } @@ -1192,71 +1248,101 @@ void SnoopIso15693(void) AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; // refresh the DMA Next Buffer and AT91C_BASE_PDC_SSC->PDC_RNCR = ISO15693_DMA_BUFFER_SIZE; // DMA Next Counter registers WDT_HIT(); - if(BUTTON_PRESS()) { + if (BUTTON_PRESS()) { DbpString("Snoop stopped."); break; } } } - samples++; - if (!TagIsActive) { // no need to try decoding reader data if the tag is sending + if (!TagIsActive) { // no need to try decoding reader data if the tag is sending if (Handle15693SampleFromReader(snoopdata & 0x02, &DecodeReader)) { - FpgaDisableSscDma(); - ExpectTagAnswer = true; - LogTrace_ISO15693(DecodeReader.output, DecodeReader.byteCount, samples*64, samples*64, NULL, true); + // FpgaDisableSscDma(); + uint32_t eof_time = dma_start_time + samples*16 + 8 - DELAY_READER_TO_ARM_SNOOP; // end of EOF + if (DecodeReader.byteCount > 0) { + uint32_t sof_time = eof_time + - DecodeReader.byteCount * (DecodeReader.Coding==CODING_1_OUT_OF_4?128*16:2048*16) // time for byte transfers + - 32*16 // time for SOF transfer + - 16*16; // time for EOF transfer + LogTrace_ISO15693(DecodeReader.output, DecodeReader.byteCount, sof_time*4, eof_time*4, NULL, true); + } /* And ready to receive another command. */ DecodeReaderReset(&DecodeReader); /* And also reset the demod code, which might have been */ /* false-triggered by the commands from the reader. */ DecodeTagReset(&DecodeTag); - upTo = dmaBuf; - FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE); - } - if (Handle15693SampleFromReader(snoopdata & 0x01, &DecodeReader)) { - FpgaDisableSscDma(); + ReaderIsActive = false; ExpectTagAnswer = true; - LogTrace_ISO15693(DecodeReader.output, DecodeReader.byteCount, samples*64, samples*64, NULL, true); + // upTo = dmaBuf; + // samples = 0; + // FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE); + // continue; + } else if (Handle15693SampleFromReader(snoopdata & 0x01, &DecodeReader)) { + // FpgaDisableSscDma(); + uint32_t eof_time = dma_start_time + samples*16 + 16 - DELAY_READER_TO_ARM_SNOOP; // end of EOF + if (DecodeReader.byteCount > 0) { + uint32_t sof_time = eof_time + - DecodeReader.byteCount * (DecodeReader.Coding==CODING_1_OUT_OF_4?128*16:2048*16) // time for byte transfers + - 32*16 // time for SOF transfer + - 16*16; // time for EOF transfer + LogTrace_ISO15693(DecodeReader.output, DecodeReader.byteCount, sof_time*4, eof_time*4, NULL, true); + } /* And ready to receive another command. */ DecodeReaderReset(&DecodeReader); /* And also reset the demod code, which might have been */ /* false-triggered by the commands from the reader. */ DecodeTagReset(&DecodeTag); - upTo = dmaBuf; - FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE); + ReaderIsActive = false; + ExpectTagAnswer = true; + // upTo = dmaBuf; + // samples = 0; + // FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE); + // continue; + } else { + ReaderIsActive = (DecodeReader.state >= STATE_READER_RECEIVE_DATA_1_OUT_OF_4); } - ReaderIsActive = (DecodeReader.state >= STATE_READER_AWAIT_2ND_RISING_EDGE_OF_SOF); } if (!ReaderIsActive && ExpectTagAnswer) { // no need to try decoding tag data if the reader is currently sending or no answer expected yet if (Handle15693SamplesFromTag(snoopdata >> 2, &DecodeTag)) { - FpgaDisableSscDma(); - //Use samples as a time measurement - LogTrace_ISO15693(DecodeTag.output, DecodeTag.len, samples*64, samples*64, NULL, false); + // FpgaDisableSscDma(); + uint32_t eof_time = dma_start_time + samples*16 - DELAY_TAG_TO_ARM_SNOOP; // end of EOF + if (DecodeTag.lastBit == SOF_PART2) { + eof_time -= 8*16; // needed 8 additional samples to confirm single SOF (iCLASS) + } + uint32_t sof_time = eof_time + - DecodeTag.len * 8 * 8 * 16 // time for byte transfers + - 32 * 16 // time for SOF transfer + - (DecodeTag.lastBit != SOF_PART2?32*16:0); // time for EOF transfer + LogTrace_ISO15693(DecodeTag.output, DecodeTag.len, sof_time*4, eof_time*4, NULL, false); // And ready to receive another response. DecodeTagReset(&DecodeTag); DecodeReaderReset(&DecodeReader); ExpectTagAnswer = false; - upTo = dmaBuf; - FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE); + TagIsActive = false; + // upTo = dmaBuf; + // samples = 0; + // FpgaSetupSscDma((uint8_t*) dmaBuf, ISO15693_DMA_BUFFER_SIZE); + // continue; + } else { + TagIsActive = (DecodeTag.state >= STATE_TAG_RECEIVING_DATA); } - TagIsActive = (DecodeTag.state >= STATE_TAG_RECEIVING_DATA); } } FpgaDisableSscDma(); - BigBuf_free(); - - LEDsoff(); DbpString("Snoop statistics:"); - Dbprintf(" ExpectTagAnswer: %d", ExpectTagAnswer); + Dbprintf(" ExpectTagAnswer: %d, TagIsActive: %d, ReaderIsActive: %d", ExpectTagAnswer, TagIsActive, ReaderIsActive); Dbprintf(" DecodeTag State: %d", DecodeTag.state); Dbprintf(" DecodeTag byteCnt: %d", DecodeTag.len); + Dbprintf(" DecodeTag posCount: %d", DecodeTag.posCount); Dbprintf(" DecodeReader State: %d", DecodeReader.state); Dbprintf(" DecodeReader byteCnt: %d", DecodeReader.byteCount); + Dbprintf(" DecodeReader posCount: %d", DecodeReader.posCount); Dbprintf(" Trace length: %d", BigBuf_get_traceLen()); + Dbprintf(" Max behindBy: %d", max_behindBy); } @@ -1691,44 +1777,26 @@ void SetTag15693Uid(uint8_t *uid) { LED_A_ON(); - uint8_t cmd[4][9] = {0x00}; + uint8_t cmd[4][9] = { + {0x02, 0x21, 0x3e, 0x00, 0x00, 0x00, 0x00}, + {0x02, 0x21, 0x3f, 0x69, 0x96, 0x00, 0x00}, + {0x02, 0x21, 0x38}, + {0x02, 0x21, 0x39} + }; + uint16_t crc; int recvlen = 0; uint8_t recvbuf[ISO15693_MAX_RESPONSE_LENGTH]; uint32_t eof_time; - // Command 1 : 02213E00000000 - cmd[0][0] = 0x02; - cmd[0][1] = 0x21; - cmd[0][2] = 0x3e; - cmd[0][3] = 0x00; - cmd[0][4] = 0x00; - cmd[0][5] = 0x00; - cmd[0][6] = 0x00; - - // Command 2 : 02213F69960000 - cmd[1][0] = 0x02; - cmd[1][1] = 0x21; - cmd[1][2] = 0x3f; - cmd[1][3] = 0x69; - cmd[1][4] = 0x96; - cmd[1][5] = 0x00; - cmd[1][6] = 0x00; - // Command 3 : 022138u8u7u6u5 (where uX = uid byte X) - cmd[2][0] = 0x02; - cmd[2][1] = 0x21; - cmd[2][2] = 0x38; cmd[2][3] = uid[7]; cmd[2][4] = uid[6]; cmd[2][5] = uid[5]; cmd[2][6] = uid[4]; // Command 4 : 022139u4u3u2u1 (where uX = uid byte X) - cmd[3][0] = 0x02; - cmd[3][1] = 0x21; - cmd[3][2] = 0x39; cmd[3][3] = uid[3]; cmd[3][4] = uid[2]; cmd[3][5] = uid[1]; diff --git a/armsrc/iso15693.h b/armsrc/iso15693.h index 5cbe5ecc..5175ff20 100644 --- a/armsrc/iso15693.h +++ b/armsrc/iso15693.h @@ -31,7 +31,7 @@ void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t *start_time, int GetIso15693CommandFromReader(uint8_t *received, size_t max_len, uint32_t *eof_time); void TransmitTo15693Tag(const uint8_t *cmd, int len, uint32_t *start_time); int GetIso15693AnswerFromTag(uint8_t* response, uint16_t max_len, uint16_t timeout, uint32_t *eof_time); -void SnoopIso15693(void); +void SnoopIso15693(uint8_t jam_search_len, uint8_t *jam_search_string); void AcquireRawAdcSamplesIso15693(void); void ReaderIso15693(uint32_t parameter); void SimTagIso15693(uint32_t parameter, uint8_t *uid); diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 229af0e1..b59c0bdc 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -18,6 +18,7 @@ #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type #include "comms.h" #include "ui.h" +#include "cliparser/cliparser.h" #include "cmdparser.h" #include "cmdhficlass.h" #include "common.h" @@ -175,8 +176,29 @@ static int CmdHFiClassList(const char *Cmd) { static int CmdHFiClassSnoop(const char *Cmd) { - UsbCommand c = {CMD_SNOOP_ICLASS}; + + CLIParserInit("hf iclass snoop", "\nSnoop a communication between an iClass Reader and an iClass Tag.", NULL); + void* argtable[] = { + arg_param_begin, + arg_lit0("j", "jam", "Jam (prevent) e-purse Updates"), + arg_param_end + }; + if (CLIParserParseString(Cmd, argtable, arg_getsize(argtable), true)){ + CLIParserFree(); + return 0; + } + + bool jam_epurse_update = arg_get_lit(1); + + const uint8_t update_epurse_sequence[2] = {0x87, 0x02}; + + UsbCommand c = {CMD_SNOOP_ICLASS, {0}}; + if (jam_epurse_update) { + c.arg[0] = sizeof(update_epurse_sequence); + memcpy(c.d.asBytes, update_epurse_sequence, sizeof(update_epurse_sequence)); + } SendCommand(&c); + return 0; } diff --git a/common/Makefile.common b/common/Makefile.common index 952a5b9a..116a1b26 100644 --- a/common/Makefile.common +++ b/common/Makefile.common @@ -67,27 +67,31 @@ VPATH = . ../common ../common/crapto1 ../common/mbedtls ../fpga ../zlib INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/usb_cmd.h $(APP_INCLUDES) -CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 -Os $(APP_CFLAGS) +CFLAGS = -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 $(APP_CFLAGS) LDFLAGS = -nostartfiles -nodefaultlibs -Wl,-gc-sections -n LIBS = -lgcc THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(THUMBSRC))) +THUMBOPTOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(THUMBOPTSRC))) ARMOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(ARMSRC))) ASMOBJ = $(patsubst %.s,$(OBJDIR)/%.o,$(notdir $(ASMSRC))) VERSIONOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(VERSIONSRC))) $(THUMBOBJ): $(OBJDIR)/%.o: %.c $(INCLUDES) - $(CC) $(CFLAGS) -mthumb -mthumb-interwork -o $@ $< + $(CC) $(CFLAGS) -Os -mthumb -mthumb-interwork -o $@ $< + +$(THUMBOPTOBJ): $(OBJDIR)/%.o: %.c $(INCLUDES) + $(CC) $(CFLAGS) -O -mthumb -mthumb-interwork -o $@ $< $(ARMOBJ): $(OBJDIR)/%.o: %.c $(INCLUDES) - $(CC) $(CFLAGS) -mthumb-interwork -o $@ $< + $(CC) $(CFLAGS) -Os -mthumb-interwork -o $@ $< $(ASMOBJ): $(OBJDIR)/%.o: %.s - $(CC) $(CFLAGS) -mthumb-interwork -o $@ $< + $(CC) $(CFLAGS) -Os -mthumb-interwork -o $@ $< $(VERSIONOBJ): $(OBJDIR)/%.o: %.c $(INCLUDES) - $(CC) $(CFLAGS) -mthumb -mthumb-interwork -o $@ $< + $(CC) $(CFLAGS) -Os -mthumb -mthumb-interwork -o $@ $< # This objcopy call translates physical flash addresses to logical addresses # without touching start address or RAM addresses (.bss and .data sections) @@ -101,12 +105,13 @@ $(OBJDIR)/%.s19: $(OBJDIR)/%.elf # Automatic dependency generation DEPENDENCY_FILES = $(patsubst %.c,$(OBJDIR)/%.d,$(notdir $(THUMBSRC))) \ + $(patsubst %.c,$(OBJDIR)/%.d,$(notdir $(THUMBOPTSRC))) \ $(patsubst %.c,$(OBJDIR)/%.d,$(notdir $(ARMSRC))) \ $(patsubst %.s,$(OBJDIR)/%.d,$(notdir $(ASMSRC))) $(DEPENDENCY_FILES): Makefile ../common/Makefile.common -$(patsubst %.o,%.d,$(THUMBOBJ) $(ARMOBJ)): $(OBJDIR)/%.d: %.c +$(patsubst %.o,%.d,$(THUMBOBJ) $(THUMBOPTOBJ) $(ARMOBJ)): $(OBJDIR)/%.d: %.c @$(CC) -MM -MT "$(@) $(@:.d=.o)" $(CFLAGS) $< > $@ $(patsubst %.o,%.d,$(ASMOBJ)):$(OBJDIR)/%.d: %.s @$(CC) -MM -MT "$(@) $(@:.d=.o)" $(CFLAGS) $< > $@ diff --git a/common/iso15693tools.c b/common/iso15693tools.c index f1214458..0769eefb 100644 --- a/common/iso15693tools.c +++ b/common/iso15693tools.c @@ -7,10 +7,10 @@ //----------------------------------------------------------------------------- -#include "proxmark3.h" +#include "iso15693tools.h" + +#include #include -#include -//#include "iso15693tools.h" #ifdef ON_DEVICE #include "printf.h" #else @@ -18,24 +18,24 @@ #endif -#define POLY 0x8408 +#define ISO15693_CRC_PRESET (uint16_t)0xFFFF +#define ISO15693_CRC_POLY (uint16_t)0x8408 // The CRC as described in ISO 15693-Part 3-Annex C -// v buffer with data -// n length -// returns crc as 16bit value -uint16_t Iso15693Crc(uint8_t *v, int n) -{ +// v buffer with data +// n length +// returns crc as 16bit value +uint16_t Iso15693Crc(uint8_t *v, int n) { uint32_t reg; int i, j; - reg = 0xffff; - for(i = 0; i < n; i++) { + reg = ISO15693_CRC_PRESET; + for (i = 0; i < n; i++) { reg = reg ^ ((uint32_t)v[i]); for (j = 0; j < 8; j++) { if (reg & 0x0001) { - reg = (reg >> 1) ^ 0x8408; + reg = (reg >> 1) ^ ISO15693_CRC_POLY; } else { reg = (reg >> 1); } @@ -46,55 +46,50 @@ uint16_t Iso15693Crc(uint8_t *v, int n) } // adds a CRC to a dataframe -// req[] iso15963 frame without crc -// n length without crc +// req[] iso15963 frame without crc +// n length without crc // returns the new length of the dataframe. int Iso15693AddCrc(uint8_t *req, int n) { - uint16_t crc=Iso15693Crc(req,n); + uint16_t crc = Iso15693Crc(req, n); req[n] = crc & 0xff; req[n+1] = crc >> 8; - return n+2; + return n + 2; } // returns a string representation of the UID // UID is transmitted and stored LSB first, displayed MSB first -// target char* buffer, where to put the UID, if NULL a static buffer is returned -// uid[] the UID in transmission order -// return: ptr to string -char* Iso15693sprintUID(char *target,uint8_t *uid) { - static char tempbuf[2*8+1]=""; - if (target==NULL) target=tempbuf; - sprintf(target,"%02X%02X%02X%02X%02X%02X%02X%02X", - uid[7],uid[6],uid[5],uid[4],uid[3],uid[2],uid[1],uid[0]); - return target; +// target char* buffer, where to put the UID, if NULL a static buffer is returned +// uid[] the UID in transmission order +// return: ptr to string +char* Iso15693sprintUID(char *target, uint8_t *uid) { + static char tempbuf[2*8+1] = ""; + if (target == NULL) target = tempbuf; + sprintf(target, "%02X%02X%02X%02X%02X%02X%02X%02X", uid[7], uid[6], uid[5], uid[4], uid[3], uid[2], uid[1], uid[0]); + return target; } -uint16_t iclass_crc16(char *data_p, unsigned short length) -{ - unsigned char i; - unsigned int data; - uint16_t crc = 0xffff; - - if (length == 0) - return (~crc); - - do - { - for (i=0, data=(unsigned int)0xff & *data_p++; - i < 8; - i++, data >>= 1) - { - if ((crc & 0x0001) ^ (data & 0x0001)) - crc = (crc >> 1) ^ POLY; - else crc >>= 1; - } - } while (--length); - - crc = ~crc; - data = crc; - crc = (crc << 8) | (data >> 8 & 0xff); - crc = crc ^ 0xBC3; - return (crc); + +uint16_t iclass_crc16(char *data_p, unsigned short length) { + unsigned char i; + unsigned int data; + uint16_t crc = ISO15693_CRC_PRESET; + + if (length == 0) + return (~crc); + + do { + for (i = 0, data = (unsigned int)0xff & *data_p++; i < 8; i++, data >>= 1) { + if ((crc & 0x0001) ^ (data & 0x0001)) + crc = (crc >> 1) ^ ISO15693_CRC_POLY; + else crc >>= 1; + } + } while (--length); + + crc = ~crc; + data = crc; + crc = (crc << 8) | (data >> 8 & 0xff); + crc = crc ^ 0x0BC3; + return (crc); } diff --git a/common/iso15693tools.h b/common/iso15693tools.h index ceb6393e..b421c23f 100644 --- a/common/iso15693tools.h +++ b/common/iso15693tools.h @@ -4,11 +4,10 @@ #ifndef ISO15693TOOLS_H__ #define ISO15693TOOLS_H__ +#include + // ISO15693 CRC -#define ISO15693_CRC_PRESET (uint16_t)0xFFFF -#define ISO15693_CRC_POLY (uint16_t)0x8408 #define ISO15693_CRC_CHECK ((uint16_t)(~0xF0B8 & 0xFFFF)) // use this for checking of a correct crc - uint16_t Iso15693Crc(uint8_t *v, int n); int Iso15693AddCrc(uint8_t *req, int n); char* Iso15693sprintUID(char *target, uint8_t *uid); diff --git a/fpga/fpga_hf.bit b/fpga/fpga_hf.bit index 38990597..ea7c7ebf 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 01c6ebb2..4e1785d7 100644 --- a/fpga/fpga_hf.v +++ b/fpga/fpga_hf.v @@ -13,8 +13,14 @@ // iZsh , June 2014 //----------------------------------------------------------------------------- -// Defining modes and options. This must be aligned to the definitions in fpgaloader.h + +// Defining commands, modes and options. This must be aligned to the definitions in fpgaloader.h // Note: the definitions here are without shifts + +// Commands: +`define FPGA_CMD_SET_CONFREG 1 +`define FPGA_CMD_TRACE_ENABLE 2 + // Major modes: `define FPGA_MAJOR_MODE_LF_ADC 0 `define FPGA_MAJOR_MODE_LF_EDGE_DETECT 1 @@ -35,6 +41,7 @@ `define FPGA_HF_READER_MODE_SNIFF_IQ 5 `define FPGA_HF_READER_MODE_SNIFF_AMPLITUDE 6 `define FPGA_HF_READER_MODE_SNIFF_PHASE 7 +`define FPGA_HF_READER_MODE_SEND_JAM 8 `define FPGA_HF_READER_SUBCARRIER_848_KHZ 0 `define FPGA_HF_READER_SUBCARRIER_424_KHZ 1 `define FPGA_HF_READER_SUBCARRIER_212_KHZ 2 @@ -79,7 +86,7 @@ module fpga_hf( //----------------------------------------------------------------------------- reg [15:0] shift_reg; -reg [7:0] conf_word; +reg [8:0] conf_word; reg trace_enable; // We switch modes between transmitting to the 13.56 MHz tag and receiving @@ -88,8 +95,8 @@ reg trace_enable; always @(posedge ncs) begin case(shift_reg[15:12]) - 4'b0001: conf_word <= shift_reg[7:0]; // FPGA_CMD_SET_CONFREG - 4'b0010: trace_enable <= shift_reg[0]; // FPGA_CMD_TRACE_ENABLE + `FPGA_CMD_SET_CONFREG: conf_word <= shift_reg[8:0]; + `FPGA_CMD_TRACE_ENABLE: trace_enable <= shift_reg[0]; endcase end @@ -103,11 +110,11 @@ begin end // select module (outputs) based on major mode -wire [2:0] major_mode = conf_word[7:5]; +wire [2:0] major_mode = conf_word[8:6]; // configuring the HF reader -wire [1:0] subcarrier_frequency = conf_word[4:3]; -wire [2:0] minor_mode = conf_word[2:0]; +wire [1:0] subcarrier_frequency = conf_word[5:4]; +wire [3:0] minor_mode = conf_word[3:0]; //----------------------------------------------------------------------------- // And then we instantiate the modules corresponding to each of the FPGA's diff --git a/fpga/fpga_lf.bit b/fpga/fpga_lf.bit index bd4d821b..96d27372 100644 Binary files a/fpga/fpga_lf.bit and b/fpga/fpga_lf.bit differ diff --git a/fpga/fpga_lf.v b/fpga/fpga_lf.v index 1b7a1127..bb0795e8 100644 --- a/fpga/fpga_lf.v +++ b/fpga/fpga_lf.v @@ -29,17 +29,18 @@ module fpga_lf( reg [15:0] shift_reg; reg [7:0] divisor; -reg [7:0] conf_word; +reg [8:0] conf_word; reg [7:0] user_byte1; always @(posedge ncs) begin - case(shift_reg[15:12]) - 4'b0001: + case (shift_reg[15:12]) + 4'b0001: // FPGA_CMD_SET_CONFREG begin - conf_word <= shift_reg[7:0]; - if (shift_reg[7:0] == 8'b00000001) begin // LF edge detect - user_byte1 <= 127; // default threshold + conf_word <= shift_reg[8:0]; + if (shift_reg[8:0] == 9'b000000001) + begin // LF edge detect + user_byte1 <= 127; // default threshold end end 4'b0010: divisor <= shift_reg[7:0]; // FPGA_CMD_SET_DIVISOR @@ -49,14 +50,14 @@ end always @(posedge spck) begin - if(~ncs) + if (~ncs) begin shift_reg[15:1] <= shift_reg[14:0]; shift_reg[0] <= mosi; end end -wire [2:0] major_mode = conf_word[7:5]; +wire [2:0] major_mode = conf_word[8:6]; // For the low-frequency configuration: wire lf_field = conf_word[0]; diff --git a/fpga/hi_iso14443a.v b/fpga/hi_iso14443a.v index e460a2cc..1c6e4cbf 100644 --- a/fpga/hi_iso14443a.v +++ b/fpga/hi_iso14443a.v @@ -18,7 +18,7 @@ module hi_iso14443a( input ssp_dout; output ssp_frame, ssp_din, ssp_clk; output dbg; - input [2:0] mod_type; + input [3:0] mod_type; wire adc_clk = ck_1356meg; diff --git a/fpga/hi_reader.v b/fpga/hi_reader.v index aca9132f..fe5ae4e5 100644 --- a/fpga/hi_reader.v +++ b/fpga/hi_reader.v @@ -19,7 +19,7 @@ module hi_reader( output ssp_frame, ssp_din, ssp_clk; output dbg; input [1:0] subcarrier_frequency; - input [2:0] minor_mode; + input [3:0] minor_mode; assign adc_clk = ck_1356meg; // sample frequency is 13,56 MHz @@ -139,7 +139,7 @@ begin // These are the correlators: we correlate against in-phase and quadrature // versions of our reference signal, and keep the (signed) results or the // resulting amplitude to send out later over the SSP. - if(corr_i_cnt == 6'd0) + if (corr_i_cnt == 6'd0) begin if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_AMPLITUDE) begin @@ -213,7 +213,7 @@ begin end // for each Q/I pair report two reader signal samples when sniffing. Store the 2nd. - if(corr_i_cnt == 6'd32) + 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. @@ -221,10 +221,10 @@ begin // ssp_clk should be the adc_clk divided by 64/16 = 4. // ssp_clk frequency = 13,56MHz / 4 = 3.39MHz - if(corr_i_cnt[1:0] == 2'b00) + if (corr_i_cnt[1:0] == 2'b00) begin // Don't shift if we just loaded new data, obviously. - if(corr_i_cnt != 6'd0) + if (corr_i_cnt != 6'd0) begin corr_i_out[7:0] <= {corr_i_out[6:0], corr_q_out[7]}; corr_q_out[7:1] <= corr_q_out[6:0]; @@ -257,6 +257,19 @@ end assign ssp_din = corr_i_out[7]; +// a jamming signal +reg jam_signal; +reg [3:0] jam_counter; + +always @(negedge adc_clk) +begin + if (corr_i_cnt == 6'd0) + begin + jam_counter <= jam_counter + 1; + jam_signal <= jam_counter[1] ^ jam_counter[3]; + end +end + // Antenna drivers reg pwr_hi, pwr_oe4; @@ -272,10 +285,15 @@ begin pwr_hi = ck_1356meg & ~ssp_dout; pwr_oe4 = 1'b0; end + else if (minor_mode == `FPGA_HF_READER_MODE_SEND_JAM) + begin + pwr_hi = ck_1356meg & jam_signal; + pwr_oe4 = 1'b0; + end else if (minor_mode == `FPGA_HF_READER_MODE_SNIFF_IQ || minor_mode == `FPGA_HF_READER_MODE_SNIFF_AMPLITUDE || minor_mode == `FPGA_HF_READER_MODE_SNIFF_PHASE) - begin + begin // all off pwr_hi = 1'b0; pwr_oe4 = 1'b0; end @@ -284,7 +302,7 @@ begin pwr_hi = ck_1356meg; pwr_oe4 = 1'b0; end -end +end // always on assign pwr_oe1 = 1'b0; diff --git a/fpga/hi_simulate.v b/fpga/hi_simulate.v index 5fc2e113..7627e932 100644 --- a/fpga/hi_simulate.v +++ b/fpga/hi_simulate.v @@ -31,7 +31,7 @@ module hi_simulate( input ssp_dout; output ssp_frame, ssp_din, ssp_clk; output dbg; - input [2:0] mod_type; + input [3:0] mod_type; assign adc_clk = ck_1356meg;