MAJOR update, added hitag2 reader, emulation and eavesdropping, lots of new code, including FPGA tweaks, part 2

This commit is contained in:
roel@libnfc.org 2012-09-18 13:53:17 +00:00
parent db09cb3adb
commit d19929cbe8
18 changed files with 1355 additions and 454 deletions

View file

@ -10,7 +10,7 @@ APP_INCLUDES = apps.h
#remove one of the following defines and comment out the relevant line
#in the next section to remove that particular feature from compilation
APP_CFLAGS = -O2 -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF
APP_CFLAGS = -O2 -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG
#-DWITH_LCD
#SRC_LCD = fonts.c LCD.c

View file

@ -19,6 +19,7 @@
#include <stdarg.h>
#include "legicrf.h"
#include <hitag2.h>
#ifdef WITH_LCD
# include "fonts.h"
@ -125,23 +126,27 @@ void Dbprintf(const char *fmt, ...) {
}
// prints HEX & ASCII
void Dbhexdump(int len, uint8_t *d) {
void Dbhexdump(int len, uint8_t *d, bool bAsci) {
int l=0,i;
char ascii[9];
while (len>0) {
if (len>8) l=8;
else l=len;
memcpy(ascii,d,l);
ascii[l]=0;
ascii[l]=0;
// filter safe ascii
for (i=0;i<l;i++)
for (i=0;i<l;i++)
if (ascii[i]<32 || ascii[i]>126) ascii[i]='.';
Dbprintf("%-8s %*D",ascii,l,d," ");
if (bAsci) {
Dbprintf("%-8s %*D",ascii,l,d," ");
} else {
Dbprintf("%*D",l,d," ");
}
len-=8;
d+=8;
}
@ -185,14 +190,15 @@ int AvgAdc(int ch) // was static - merlok
void MeasureAntennaTuning(void)
{
uint8_t *dest = (uint8_t *)BigBuf;
uint8_t *dest = (uint8_t *)BigBuf+FREE_BUFFER_OFFSET;
int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0
int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV
UsbCommand c;
DbpString("Measuring antenna characteristics, please wait.");
memset(BigBuf,0,sizeof(BigBuf));
LED_B_ON();
DbpString("Measuring antenna characteristics, please wait...");
memset(dest,0,sizeof(FREE_BUFFER_SIZE));
/*
* Sweeps the useful LF range of the proxmark from
@ -202,8 +208,10 @@ void MeasureAntennaTuning(void)
* the resonating frequency of your LF antenna
* ( hopefully around 95 if it is tuned to 125kHz!)
*/
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_READER);
for (i=255; i>19; i--) {
WDT_HIT();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
SpinDelay(20);
// Vref = 3.3V, and a 10000:240 voltage divider on the input
@ -221,6 +229,7 @@ void MeasureAntennaTuning(void)
}
}
LED_A_ON();
// Let the FPGA drive the high-frequency antenna around 13.56 MHz.
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
SpinDelay(20);
@ -232,7 +241,14 @@ void MeasureAntennaTuning(void)
c.arg[0] = (vLf125 << 0) | (vLf134 << 16);
c.arg[1] = vHf;
c.arg[2] = peakf | (peakv << 16);
DbpString("Measuring complete, sending report back to host");
UsbSendPacket((uint8_t *)&c, sizeof(c));
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_A_OFF();
LED_B_OFF();
return;
}
void MeasureAntennaTuningHf(void)
@ -258,8 +274,7 @@ void MeasureAntennaTuningHf(void)
void SimulateTagHfListen(void)
{
uint8_t *dest = (uint8_t *)BigBuf;
int n = sizeof(BigBuf);
uint8_t *dest = (uint8_t *)BigBuf+FREE_BUFFER_OFFSET;
uint8_t v = 0;
int i;
int p = 0;
@ -293,7 +308,7 @@ void SimulateTagHfListen(void)
p = 0;
i++;
if(i >= n) {
if(i >= FREE_BUFFER_SIZE) {
break;
}
}
@ -644,6 +659,18 @@ void UsbPacketReceived(uint8_t *packet, int len)
break;
#endif
#ifdef WITH_HITAG
case CMD_SNOOP_HITAG: // Eavesdrop Hitag tag, args = type
SnoopHitag(c->arg[0]);
break;
case CMD_SIMULATE_HITAG: // Simulate Hitag tag, args = memory content
SimulateHitagTag((bool)c->arg[0],(byte_t*)c->d.asBytes);
break;
case CMD_READER_HITAG: // Reader for Hitag tags, args = type and function
ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
break;
#endif
#ifdef WITH_ISO15693
case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:
AcquireRawAdcSamplesIso15693();
@ -822,16 +849,14 @@ void UsbPacketReceived(uint8_t *packet, int len)
LED_B_ON();
UsbSendPacket((uint8_t *)&n, sizeof(n));
LED_B_OFF();
break;
}
} break;
case CMD_DOWNLOADED_SIM_SAMPLES_125K: {
uint8_t *b = (uint8_t *)BigBuf;
memcpy(b+c->arg[0], c->d.asBytes, 48);
//Dbprintf("copied 48 bytes to %i",b+c->arg[0]);
UsbSendPacket((uint8_t*)&ack, sizeof(ack));
break;
}
} break;
case CMD_READ_MEM:
ReadMem(c->arg[0]);
@ -854,10 +879,6 @@ void UsbPacketReceived(uint8_t *packet, int len)
SendVersion();
break;
#ifdef WITH_LF
#endif
#ifdef WITH_LCD
case CMD_LCD_RESET:
LCDReset();
@ -868,7 +889,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
#endif
case CMD_SETUP_WRITE:
case CMD_FINISH_WRITE:
case CMD_HARDWARE_RESET:
case CMD_HARDWARE_RESET: {
USB_D_PLUS_PULLUP_OFF();
SpinDelay(1000);
SpinDelay(1000);
@ -876,16 +897,16 @@ void UsbPacketReceived(uint8_t *packet, int len)
for(;;) {
// We're going to reset, and the bootrom will take control.
}
break;
} break;
case CMD_START_FLASH:
case CMD_START_FLASH: {
if(common_area.flags.bootrom_present) {
common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE;
}
USB_D_PLUS_PULLUP_OFF();
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
for(;;);
break;
} break;
case CMD_DEVICE_INFO: {
UsbCommand c;
@ -893,11 +914,11 @@ void UsbPacketReceived(uint8_t *packet, int len)
c.arg[0] = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS;
if(common_area.flags.bootrom_present) c.arg[0] |= DEVICE_INFO_FLAG_BOOTROM_PRESENT;
UsbSendPacket((uint8_t*)&c, sizeof(c));
}
break;
default:
} break;
default: {
Dbprintf("%s: 0x%04x","unknown command:",c->cmd);
break;
} break;
}
}

View file

@ -14,7 +14,8 @@
#include <stdint.h>
#include <stddef.h>
typedef unsigned char byte_t;
#include "common.h"
#include "hitag2.h"
// The large multi-purpose buffer, typically used to hold A/D samples,
// maybe processed in some way.
@ -49,7 +50,7 @@ void SamyRun(void);
//void DbpIntegers(int a, int b, int c);
void DbpString(char *str);
void Dbprintf(const char *fmt, ...);
void Dbhexdump(int len, uint8_t *d);
void Dbhexdump(int len, uint8_t *d, bool bAsci);
int AvgAdc(int ch);
@ -69,13 +70,9 @@ void FpgaDownloadAndGo(void);
void FpgaGatherVersion(char *dst, int len);
void FpgaSetupSsc(void);
void SetupSpi(int mode);
void FpgaSetupSscDma(uint8_t *buf, int len);
void inline FpgaDisableSscDma(void){
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
}
void inline FpgaEnableSscDma(void){
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
}
bool FpgaSetupSscDma(uint8_t *buf, int len);
#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
#define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
void SetAdcMuxFor(uint32_t whichGpio);
// Definitions for the FPGA commands.
@ -83,19 +80,21 @@ void SetAdcMuxFor(uint32_t whichGpio);
#define FPGA_CMD_SET_DIVISOR (2<<12)
// Definitions for the FPGA configuration word.
#define FPGA_MAJOR_MODE_LF_READER (0<<5)
#define FPGA_MAJOR_MODE_LF_SIMULATOR (1<<5)
#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5)
#define FPGA_MAJOR_MODE_HF_READER_TX (2<<5)
#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (3<<5)
#define FPGA_MAJOR_MODE_HF_SIMULATOR (4<<5)
#define FPGA_MAJOR_MODE_HF_ISO14443A (5<<5)
#define FPGA_MAJOR_MODE_LF_PASSTHRU (6<<5)
#define FPGA_MAJOR_MODE_OFF (7<<5)
// Options for LF_EDGE_DETECT
#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0)
// Options for the HF reader, tx to tag
#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0)
// Options for the HF reader, correlating against rx from tag
#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0)
#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1)
#define FPGA_HF_READER_RX_XCORR_QUARTER_FREQ (1<<2)
#define FPGA_HF_READER_RX_XCORR_QUARTER_FREQ (1<<2)
// Options for the HF simulated tag, how to modulate
#define FPGA_HF_SIMULATOR_NO_MODULATION (0<<0)
#define FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0)
@ -139,7 +138,7 @@ void ReaderIso14443a(UsbCommand * c, UsbCommand * ack);
int RAMFUNC LogTrace(const uint8_t * btBytes, int iLen, int iSamples, uint32_t dwParity, int bReader);
uint32_t GetParity(const uint8_t * pbtCmd, int iLen);
void iso14a_set_trigger(int enable);
void iso14a_clear_tracelen(void);
void iso14a_clear_trace(void);
void iso14a_set_tracing(int enable);
void RAMFUNC SniffMifare(uint8_t param);
@ -176,6 +175,11 @@ void RAMFUNC SnoopIClass(void);
void SimulateIClass(uint8_t arg0, uint8_t *datain);
void ReaderIClass(uint8_t arg0);
// hitag2.h
void SnoopHitag(uint32_t type);
void SimulateHitagTag(bool tag_mem_supplied, byte_t* data);
void ReaderHitag(hitag_function htf, hitag_data* htd);
/// util.h
#endif

View file

@ -136,18 +136,20 @@ void FpgaSetupSsc(void)
// ourselves, not to another buffer). The stuff to manipulate those buffers
// is in apps.h, because it should be inlined, for speed.
//-----------------------------------------------------------------------------
void FpgaSetupSscDma(uint8_t *buf, int len)
bool FpgaSetupSscDma(uint8_t *buf, int len)
{
if (buf == NULL) {
return false;
}
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) buf;
AT91C_BASE_PDC_SSC->PDC_RCR = len;
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) buf;
AT91C_BASE_PDC_SSC->PDC_RNCR = len;
if (buf != NULL) {
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
}
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
return true;
}
static void DownloadFPGA_byte(unsigned char w)

File diff suppressed because it is too large Load diff

View file

@ -691,7 +691,7 @@ void RAMFUNC SnoopIClass(void)
// reset traceLen to 0
iso14a_set_tracing(TRUE);
iso14a_clear_tracelen();
iso14a_clear_trace();
iso14a_set_trigger(FALSE);
// The DMA buffer, used to stream samples from the FPGA

View file

@ -21,7 +21,7 @@
#include "mifareutil.h"
static uint32_t iso14a_timeout;
uint8_t *trace = (uint8_t *) BigBuf;
uint8_t *trace = (uint8_t *) BigBuf+TRACE_OFFSET;
int traceLen = 0;
int rsamples = 0;
int tracing = TRUE;
@ -68,12 +68,15 @@ void iso14a_set_trigger(int enable) {
trigger = enable;
}
void iso14a_clear_tracelen(void) {
void iso14a_clear_trace(void) {
memset(trace, 0x44, TRACE_SIZE);
traceLen = 0;
}
void iso14a_set_tracing(int enable) {
tracing = enable;
}
void iso14a_set_timeout(uint32_t timeout) {
iso14a_timeout = timeout;
}
@ -580,8 +583,7 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
LEDsoff();
// init trace buffer
traceLen = 0;
memset(trace, 0x44, TRACE_SIZE);
iso14a_clear_trace();
// 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
@ -905,8 +907,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd)
{
// Enable and clear the trace
tracing = TRUE;
traceLen = 0;
memset(trace, 0x44, TRACE_SIZE);
iso14a_clear_trace();
// This function contains the tag emulation
uint8_t sak;
@ -2379,8 +2380,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
// C(red) A(yellow) B(green)
LEDsoff();
// init trace buffer
traceLen = 0;
memset(trace, 0x44, TRACE_SIZE);
iso14a_clear_trace();
// The command (reader -> tag) that we're receiving.
// The length of a received command will in most cases be no more than 18 bytes.

View file

@ -1102,7 +1102,7 @@ void ReaderIso15693(uint32_t parameter)
Dbprintf("%d octets read from IDENTIFY request:", answerLen1);
DbdecodeIso15693Answer(answerLen1,answer1);
Dbhexdump(answerLen1,answer1);
Dbhexdump(answerLen1,answer1,true);
// UID is reverse
if (answerLen1>=12)
@ -1113,11 +1113,11 @@ void ReaderIso15693(uint32_t parameter)
Dbprintf("%d octets read from SELECT request:", answerLen2);
DbdecodeIso15693Answer(answerLen2,answer2);
Dbhexdump(answerLen2,answer2);
Dbhexdump(answerLen2,answer2,true);
Dbprintf("%d octets read from XXX request:", answerLen3);
DbdecodeIso15693Answer(answerLen3,answer3);
Dbhexdump(answerLen3,answer3);
Dbhexdump(answerLen3,answer3,true);
// read all pages
@ -1130,7 +1130,7 @@ void ReaderIso15693(uint32_t parameter)
if (answerLen2>0) {
Dbprintf("READ SINGLE BLOCK %d returned %d octets:",i,answerLen2);
DbdecodeIso15693Answer(answerLen2,answer2);
Dbhexdump(answerLen2,answer2);
Dbhexdump(answerLen2,answer2,true);
if ( *((uint32_t*) answer2) == 0x07160101 ) break; // exit on NoPageErr
}
i++;
@ -1264,7 +1264,7 @@ void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8
if (DEBUG) {
Dbprintf("SEND");
Dbhexdump(datalen,data);
Dbhexdump(datalen,data,true);
}
recvlen=SendDataTag(data,datalen,1,speed,(recv?&recvbuf:NULL));
@ -1280,7 +1280,7 @@ void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8
if (DEBUG) {
Dbprintf("RECV");
DbdecodeIso15693Answer(recvlen,recvbuf);
Dbhexdump(recvlen,recvbuf);
Dbhexdump(recvlen,recvbuf,true);
}
}

View file

@ -433,17 +433,17 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
{
int i;
uint8_t *tab = (uint8_t *)BigBuf;
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK;
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK;
#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
i = 0;
for(;;) {
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
@ -453,18 +453,18 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
}
WDT_HIT();
}
if (ledcontrol)
LED_D_ON();
if(tab[i])
OPEN_COIL();
else
SHORT_COIL();
if (ledcontrol)
LED_D_OFF();
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
if(BUTTON_PRESS()) {
DbpString("Stopped");
@ -472,7 +472,7 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
}
WDT_HIT();
}
i++;
if(i == period) {
i = 0;
@ -484,197 +484,9 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
}
}
/* Provides a framework for bidirectional LF tag communication
* Encoding is currently Hitag2, but the general idea can probably
* be transferred to other encodings.
*
* The new FPGA code will, for the LF simulator mode, give on SSC_FRAME
* (PA15) a thresholded version of the signal from the ADC. Setting the
* ADC path to the low frequency peak detection signal, will enable a
* somewhat reasonable receiver for modulation on the carrier signal
* that is generated by the reader. The signal is low when the reader
* field is switched off, and high when the reader field is active. Due
* to the way that the signal looks like, mostly only the rising edge is
* useful, your mileage may vary.
*
* Neat perk: PA15 can not only be used as a bit-banging GPIO, but is also
* TIOA1, which can be used as the capture input for timer 1. This should
* make it possible to measure the exact edge-to-edge time, without processor
* intervention.
*
* Arguments: divisor is the divisor to be sent to the FPGA (e.g. 95 for 125kHz)
* t0 is the carrier frequency cycle duration in terms of MCK (384 for 125kHz)
*
* The following defines are in carrier periods:
*/
#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */
#define HITAG_T_1_MIN 24 /* T[1] should be 26..30 */
#define HITAG_T_EOF 40 /* T_EOF should be > 36 */
#define HITAG_T_WRESP 208 /* T_wresp should be 204..212 */
static void hitag_handle_frame(int t0, int frame_len, char *frame);
//#define DEBUG_RA_VALUES 1
#define DEBUG_FRAME_CONTENTS 1
void SimulateTagLowFrequencyBidir(int divisor, int t0)
{
#if DEBUG_RA_VALUES || DEBUG_FRAME_CONTENTS
int i = 0;
#endif
char frame[10];
int frame_pos=0;
DbpString("Starting Hitag2 emulator, press button to end");
hitag2_init();
/* Set up simulator mode, frequency divisor which will drive the FPGA
* and analog mux selection.
*/
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_SIMULATOR);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor);
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF();
/* Set up Timer 1:
* Capture mode, timer source MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
* external trigger rising edge, load RA on rising edge of TIOA, load RB on rising
* edge of TIOA. Assign PA15 to TIOA1 (peripheral B)
*/
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK |
AT91C_TC_ETRGEDG_RISING |
AT91C_TC_ABETRG |
AT91C_TC_LDRA_RISING |
AT91C_TC_LDRB_RISING;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN |
AT91C_TC_SWTRG;
/* calculate the new value for the carrier period in terms of TC1 values */
t0 = t0/2;
int overflow = 0;
while(!BUTTON_PRESS()) {
WDT_HIT();
if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
int ra = AT91C_BASE_TC1->TC_RA;
if((ra > t0*HITAG_T_EOF) | overflow) ra = t0*HITAG_T_EOF+1;
#if DEBUG_RA_VALUES
if(ra > 255 || overflow) ra = 255;
((char*)BigBuf)[i] = ra;
i = (i+1) % 8000;
#endif
if(overflow || (ra > t0*HITAG_T_EOF) || (ra < t0*HITAG_T_0_MIN)) {
/* Ignore */
} else if(ra >= t0*HITAG_T_1_MIN ) {
/* '1' bit */
if(frame_pos < 8*sizeof(frame)) {
frame[frame_pos / 8] |= 1<<( 7-(frame_pos%8) );
frame_pos++;
}
} else if(ra >= t0*HITAG_T_0_MIN) {
/* '0' bit */
if(frame_pos < 8*sizeof(frame)) {
frame[frame_pos / 8] |= 0<<( 7-(frame_pos%8) );
frame_pos++;
}
}
overflow = 0;
LED_D_ON();
} else {
if(AT91C_BASE_TC1->TC_CV > t0*HITAG_T_EOF) {
/* Minor nuisance: In Capture mode, the timer can not be
* stopped by a Compare C. There's no way to stop the clock
* in software, so we'll just have to note the fact that an
* overflow happened and the next loaded timer value might
* have wrapped. Also, this marks the end of frame, and the
* still running counter can be used to determine the correct
* time for the start of the reply.
*/
overflow = 1;
if(frame_pos > 0) {
/* Have a frame, do something with it */
#if DEBUG_FRAME_CONTENTS
((char*)BigBuf)[i++] = frame_pos;
memcpy( ((char*)BigBuf)+i, frame, 7);
i+=7;
i = i % sizeof(BigBuf);
#endif
hitag_handle_frame(t0, frame_pos, frame);
memset(frame, 0, sizeof(frame));
}
frame_pos = 0;
}
LED_D_OFF();
}
}
DbpString("All done");
}
static void hitag_send_bit(int t0, int bit) {
if(bit == 1) {
/* Manchester: Loaded, then unloaded */
LED_A_ON();
SHORT_COIL();
while(AT91C_BASE_TC1->TC_CV < t0*15);
OPEN_COIL();
while(AT91C_BASE_TC1->TC_CV < t0*31);
LED_A_OFF();
} else if(bit == 0) {
/* Manchester: Unloaded, then loaded */
LED_B_ON();
OPEN_COIL();
while(AT91C_BASE_TC1->TC_CV < t0*15);
SHORT_COIL();
while(AT91C_BASE_TC1->TC_CV < t0*31);
LED_B_OFF();
}
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; /* Reset clock for the next bit */
}
static void hitag_send_frame(int t0, int frame_len, const char const * frame, int fdt)
{
OPEN_COIL();
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
/* Wait for HITAG_T_WRESP carrier periods after the last reader bit,
* not that since the clock counts since the rising edge, but T_wresp is
* with respect to the falling edge, we need to wait actually (T_wresp - T_g)
* periods. The gap time T_g varies (4..10).
*/
while(AT91C_BASE_TC1->TC_CV < t0*(fdt-8));
int saved_cmr = AT91C_BASE_TC1->TC_CMR;
AT91C_BASE_TC1->TC_CMR &= ~AT91C_TC_ETRGEDG; /* Disable external trigger for the clock */
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; /* Reset the clock and use it for response timing */
int i;
for(i=0; i<5; i++)
hitag_send_bit(t0, 1); /* Start of frame */
for(i=0; i<frame_len; i++) {
hitag_send_bit(t0, !!(frame[i/ 8] & (1<<( 7-(i%8) ))) );
}
OPEN_COIL();
AT91C_BASE_TC1->TC_CMR = saved_cmr;
}
/* Callback structure to cleanly separate tag emulation code from the radio layer. */
static int hitag_cb(const char* response_data, const int response_length, const int fdt, void *cb_cookie)
{
hitag_send_frame(*(int*)cb_cookie, response_length, response_data, fdt);
return 0;
}
/* Frame length in bits, frame contents in MSBit first format */
static void hitag_handle_frame(int t0, int frame_len, char *frame)
{
hitag2_handle_command(frame, frame_len, hitag_cb, &t0);
}
// compose fc/8 fc/10 waveform

View file

@ -35,7 +35,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
pcs = &mpcs;
// clear trace
iso14a_clear_tracelen();
iso14a_clear_trace();
// iso14a_set_tracing(false);
iso14443a_setup();
@ -115,7 +115,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
pcs = &mpcs;
// clear trace
iso14a_clear_tracelen();
iso14a_clear_trace();
// iso14a_set_tracing(false);
iso14443a_setup();
@ -213,7 +213,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
pcs = &mpcs;
// clear trace
iso14a_clear_tracelen();
iso14a_clear_trace();
// iso14a_set_tracing(false);
iso14443a_setup();
@ -311,7 +311,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain)
for (i = 0; i < NES_MAX_INFO + 1; i++) nvectorcount[i] = 11; // 11 - empty block;
// clear trace
iso14a_clear_tracelen();
iso14a_clear_trace();
iso14a_set_tracing(false);
iso14443a_setup();
@ -539,7 +539,7 @@ void MifareChkKeys(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
MF_DBGLEVEL = MF_DBG_NONE;
// clear trace
iso14a_clear_tracelen();
iso14a_clear_trace();
iso14a_set_tracing(TRUE);
iso14443a_setup();
@ -641,7 +641,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
uint8_t uid[8];
// clear trace
iso14a_clear_tracelen();
iso14a_clear_trace();
iso14a_set_tracing(false);
iso14443a_setup();
@ -759,7 +759,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
if (workFlags & 0x08) {
// clear trace
iso14a_clear_tracelen();
iso14a_clear_trace();
iso14a_set_tracing(TRUE);
iso14443a_setup();
@ -890,7 +890,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
if (workFlags & 0x08) {
// clear trace
iso14a_clear_tracelen();
iso14a_clear_trace();
iso14a_set_tracing(TRUE);
iso14443a_setup();

View file

@ -401,12 +401,15 @@ void UsbSendPacket(uint8_t *packet, int len)
}
AT91C_BASE_UDP->UDP_CSR[2] |= AT91C_UDP_TXPKTRDY;
while(!(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP))
;
while(!(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP)) {
WDT_HIT();
}
AT91C_BASE_UDP->UDP_CSR[2] &= ~AT91C_UDP_TXCOMP;
while(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP)
;
while(AT91C_BASE_UDP->UDP_CSR[2] & AT91C_UDP_TXCOMP) {
WDT_HIT();
}
len -= thisTime;
packet += thisTime;
@ -426,8 +429,9 @@ static void HandleRxdData(void)
}
AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK0;
while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0)
;
while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK0) {
WDT_HIT();
}
if(UsbSoFarCount >= 64) {
UsbPacketReceived(UsbBuffer, UsbSoFarCount);
@ -444,14 +448,17 @@ static void HandleRxdData(void)
}
AT91C_BASE_UDP->UDP_CSR[1] &= ~AT91C_UDP_RX_DATA_BK1;
while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1)
;
while(AT91C_BASE_UDP->UDP_CSR[1] & AT91C_UDP_RX_DATA_BK1) {
WDT_HIT();
}
if(UsbSoFarCount >= 64) {
UsbPacketReceived(UsbBuffer, UsbSoFarCount);
UsbSoFarCount = 0;
}
}
WDT_HIT();
}
void UsbStart(void)

View file

@ -6,7 +6,7 @@ clean:
$(DELETE) fpga.map fpga.ngc fpga_ngdbuild.xrpt fpga.pcf fpga-placed_pad.csv fpga-placed.ptwx fpga.rbt xlnx_auto_0_xdb
$(DELETE) fpga.bld fpga.mrp fpga.ngc_xst.xrpt fpga.ngm fpga-placed.ncd fpga-placed_pad.txt fpga-placed.unroutes fpga_summary.xml netlist.lst xst
fpga.ngc: fpga.v fpga.ucf xst.scr util.v lo_simulate.v lo_read.v lo_passthru.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v
fpga.ngc: fpga.v fpga.ucf xst.scr util.v lo_edge_detect.v lo_read.v lo_passthru.v hi_simulate.v hi_read_tx.v hi_read_rx_xcorr.v hi_iso14443a.v
$(DELETE) fpga.ngc
$(XILINX_TOOLS_PREFIX)xst -ifn xst.scr

Binary file not shown.

View file

@ -14,7 +14,7 @@
`include "lo_read.v"
`include "lo_passthru.v"
`include "lo_simulate.v"
`include "lo_edge_detect.v"
`include "hi_read_tx.v"
`include "hi_read_rx_xcorr.v"
`include "hi_simulate.v"
@ -111,6 +111,10 @@ assign hi_read_rx_xcorr_quarter = conf_word[2];
wire [2:0] hi_simulate_mod_type;
assign hi_simulate_mod_type = conf_word[2:0];
// For the high-frequency simulated tag: what kind of modulation to use.
wire lf_field;
assign lf_field = conf_word[0];
//-----------------------------------------------------------------------------
// And then we instantiate the modules corresponding to each of the FPGA's
// major modes, and use muxes to connect the outputs of the active mode to
@ -136,13 +140,14 @@ lo_passthru lp(
lp_dbg, divisor
);
lo_simulate ls(
lo_edge_detect ls(
pck0, ck_1356meg, ck_1356megb,
ls_pwr_lo, ls_pwr_hi, ls_pwr_oe1, ls_pwr_oe2, ls_pwr_oe3, ls_pwr_oe4,
adc_d, ls_adc_clk,
ls_ssp_frame, ls_ssp_din, ssp_dout, ls_ssp_clk,
cross_hi, cross_lo,
ls_dbg, divisor
ls_dbg, divisor,
lf_field
);
hi_read_tx ht(

90
fpga/lo_edge_detect.v Normal file
View file

@ -0,0 +1,90 @@
//-----------------------------------------------------------------------------
// The way that we connect things in low-frequency simulation mode. In this
// case just pass everything through to the ARM, which can bit-bang this
// (because it is so slow).
//
// Jonathan Westhues, April 2006
//-----------------------------------------------------------------------------
module lo_edge_detect(
pck0, ck_1356meg, ck_1356megb,
pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4,
adc_d, adc_clk,
ssp_frame, ssp_din, ssp_dout, ssp_clk,
cross_hi, cross_lo,
dbg,
divisor,
lf_field
);
input pck0, ck_1356meg, ck_1356megb;
output pwr_lo, pwr_hi, pwr_oe1, pwr_oe2, pwr_oe3, pwr_oe4;
input [7:0] adc_d;
output adc_clk;
input ssp_dout;
output ssp_frame, ssp_din, ssp_clk;
input cross_hi, cross_lo;
output dbg;
input [7:0] divisor;
input lf_field;
// Divide the clock to be used for the ADC
reg [7:0] pck_divider;
reg clk_state;
wire tag_modulation;
assign tag_modulation = ssp_dout & !lf_field;
wire reader_modulation;
assign reader_modulation = !ssp_dout & lf_field & clk_state;
// No logic, straight through.
assign pwr_oe1 = 1'b0; // not used in LF mode
assign pwr_oe2 = tag_modulation;
assign pwr_oe3 = tag_modulation;
assign pwr_oe4 = tag_modulation;
assign ssp_clk = cross_lo;
assign pwr_lo = reader_modulation;
assign pwr_hi = 1'b0;
assign dbg = ssp_frame;
always @(posedge pck0)
begin
if(pck_divider == divisor[7:0])
begin
pck_divider <= 8'd0;
clk_state = !clk_state;
end
else
begin
pck_divider <= pck_divider + 1;
end
end
assign adc_clk = ~clk_state;
// Toggle the output with hysteresis
// Set to high if the ADC value is above 200
// Set to low if the ADC value is below 64
reg is_high;
reg is_low;
reg output_state;
always @(posedge pck0)
begin
if((pck_divider == 8'd7) && !clk_state) begin
is_high = (adc_d >= 8'd190);
is_low = (adc_d <= 8'd70);
end
end
always @(posedge is_high or posedge is_low)
begin
if(is_high)
output_state <= 1'd1;
else if(is_low)
output_state <= 1'd0;
end
assign ssp_frame = output_state;
endmodule

View file

@ -13,6 +13,7 @@
#define __COMMON_H
#include <stdint.h>
typedef unsigned char byte_t;
//-----------------------------------------------------------------------------
// ISO 14443A

View file

@ -1,19 +1,33 @@
//-----------------------------------------------------------------------------
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
// (c) 2012 Roel Verdult
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// Hitag2 emulation public interface
// Hitag2 type prototyping
//-----------------------------------------------------------------------------
#ifndef __HITAG2_H
#define __HITAG2_H
#ifndef _HITAG2_H_
#define _HITAG2_H_
typedef int (*hitag2_response_callback_t)(const char* response_data, const int response_length, const int fdt, void *cb_cookie);
typedef enum {
RHT2F_PASSWORD = 21,
RHT2F_AUTHENTICATE = 22,
RHT2F_TEST_AUTH_ATTEMPTS = 25,
} hitag_function;
extern int hitag2_init(void);
extern int hitag2_handle_command(const char* data, const int length, hitag2_response_callback_t cb, void *cb_cookie);
typedef struct {
byte_t password[4];
} PACKED rht2d_password;
typedef struct {
byte_t NrAr[8];
} PACKED rht2d_authenticate;
typedef union {
rht2d_password pwd;
rht2d_authenticate auth;
} hitag_data;
#endif

View file

@ -86,6 +86,12 @@ typedef struct {
#define CMD_ISO_15693_COMMAND_DONE 0x0314
#define CMD_ISO_15693_FIND_AFI 0x0315
#define CMD_ISO_15693_DEBUG 0x0316
// For Hitag2 transponders
#define CMD_SNOOP_HITAG 0x0370
#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