hf 14a snoop optimized and added parameters. hf 14a sniff - not work.

This commit is contained in:
Merlokbr@gmail.com 2012-07-07 15:29:51 +00:00
parent b62a5a8444
commit 5cd9ec01e0
5 changed files with 197 additions and 186 deletions

View file

@ -706,7 +706,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
#ifdef WITH_ISO14443a #ifdef WITH_ISO14443a
case CMD_SNOOP_ISO_14443a: case CMD_SNOOP_ISO_14443a:
SnoopIso14443a(); SnoopIso14443a(c->arg[0]);
break; break;
case CMD_READER_ISO_14443a: case CMD_READER_ISO_14443a:
ReaderIso14443a(c, &ack); ReaderIso14443a(c, &ack);
@ -764,7 +764,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
// mifare sniffer // mifare sniffer
case CMD_MIFARE_SNIFFER: case CMD_MIFARE_SNIFFER:
SniffMifare(); SniffMifare(c->arg[0]);
break; break;
#endif #endif

View file

@ -126,16 +126,16 @@ void ReadSTMemoryIso14443(uint32_t parameter,uint32_t dwLast);
void RAMFUNC SnoopIso14443(void); void RAMFUNC SnoopIso14443(void);
/// iso14443a.h /// iso14443a.h
void RAMFUNC SnoopIso14443a(void); void RAMFUNC SnoopIso14443a(uint8_t param);
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd); // ## simulate iso14443a tag void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd); // ## simulate iso14443a tag
void ReaderIso14443a(UsbCommand * c, UsbCommand * ack); void ReaderIso14443a(UsbCommand * c, UsbCommand * ack);
// Also used in iclass.c // Also used in iclass.c
int LogTrace(const uint8_t * btBytes, int iLen, int iSamples, uint32_t dwParity, int bReader); 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); uint32_t GetParity(const uint8_t * pbtCmd, int iLen);
void iso14a_set_trigger(int enable); void iso14a_set_trigger(int enable);
void iso14a_clear_tracelen(void); void iso14a_clear_tracelen(void);
void iso14a_set_tracing(int enable); void iso14a_set_tracing(int enable);
void RAMFUNC SniffMifare(void); void RAMFUNC SniffMifare(uint8_t param);
// mifarecmd.h // mifarecmd.h
void ReaderMifare(uint32_t parameter); void ReaderMifare(uint32_t parameter);

View file

@ -101,7 +101,7 @@ void AppendCrc14443a(uint8_t* data, int len)
} }
// The function LogTrace() is also used by the iClass implementation in iClass.c // The function LogTrace() is also used by the iClass implementation in iClass.c
int LogTrace(const uint8_t * btBytes, int iLen, int iSamples, uint32_t dwParity, int bReader) int RAMFUNC LogTrace(const uint8_t * btBytes, int iLen, int iSamples, uint32_t dwParity, int bReader)
{ {
// Return when trace is full // Return when trace is full
if (traceLen >= TRACE_SIZE) return FALSE; if (traceLen >= TRACE_SIZE) return FALSE;
@ -568,166 +568,149 @@ static RAMFUNC int ManchesterDecoding(int v)
// triggering so that we start recording at the point that the tag is moved // triggering so that we start recording at the point that the tag is moved
// near the reader. // near the reader.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void RAMFUNC SnoopIso14443a(void) void RAMFUNC SnoopIso14443a(uint8_t param) {
{ // param:
// #define RECV_CMD_OFFSET 2032 // original (working as of 21/2/09) values // bit 0 - trigger from first card answer
// #define RECV_RES_OFFSET 2096 // original (working as of 21/2/09) values // bit 1 - trigger from first reader 7-bit request
// #define DMA_BUFFER_OFFSET 2160 // original (working as of 21/2/09) values
// #define DMA_BUFFER_SIZE 4096 // original (working as of 21/2/09) values LEDsoff();
// #define TRACE_SIZE 2000 // original (working as of 21/2/09) values // init trace buffer
traceLen = 0;
memset(trace, 0x44, TRACE_SIZE);
// We won't start recording the frames that we acquire until we trigger; // 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 // a good trigger condition to get started is probably when we see a
// response from the tag. // response from the tag.
int triggered = FALSE; // FALSE to wait first for card // triggered == FALSE -- to wait first for card
int triggered = !(param & 0x03);
// The command (reader -> tag) that we're receiving. // The command (reader -> tag) that we're receiving.
// The length of a received command will in most cases be no more than 18 bytes. // The length of a received command will in most cases be no more than 18 bytes.
// So 32 should be enough! // So 32 should be enough!
uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET); uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
// The response (tag -> reader) that we're receiving. // The response (tag -> reader) that we're receiving.
uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET); uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET);
// As we receive stuff, we copy it from receivedCmd or receivedResponse // As we receive stuff, we copy it from receivedCmd or receivedResponse
// into trace, along with its length and other annotations. // into trace, along with its length and other annotations.
//uint8_t *trace = (uint8_t *)BigBuf; //uint8_t *trace = (uint8_t *)BigBuf;
traceLen = 0; // uncommented to fix ISSUE 15 - gerhard - jan2011 // The DMA buffer, used to stream samples from the FPGA
int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET;
int8_t *data = dmaBuf;
int maxDataLen = 0;
int dataLen = 0;
// The DMA buffer, used to stream samples from the FPGA // Set up the demodulator for tag -> reader responses.
int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET; Demod.output = receivedResponse;
int lastRxCounter; Demod.len = 0;
int8_t *upTo; Demod.state = DEMOD_UNSYNCD;
int smpl;
int maxBehindBy = 0;
// Count of samples received so far, so that we can include timing // Set up the demodulator for the reader -> tag commands
// information in the trace buffer. memset(&Uart, 0, sizeof(Uart));
int samples = 0; Uart.output = receivedCmd;
int rsamples = 0; Uart.byteCntMax = 32; // was 100 (greg)//////////////////
Uart.state = STATE_UNSYNCD;
memset(trace, 0x44, TRACE_SIZE); // Setup for the DMA.
FpgaSetupSsc();
FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
// Set up the demodulator for tag -> reader responses. // And put the FPGA in the appropriate mode
Demod.output = receivedResponse; // Signal field is off with the appropriate LED
Demod.len = 0; LED_D_OFF();
Demod.state = DEMOD_UNSYNCD; FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
// Setup for the DMA. // Count of samples received so far, so that we can include timing
FpgaSetupSsc(); // information in the trace buffer.
upTo = dmaBuf; rsamples = 0;
lastRxCounter = DMA_BUFFER_SIZE; // And now we loop, receiving samples.
FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); while(true) {
if(BUTTON_PRESS()) {
DbpString("cancelled by button");
goto done;
}
// And the reader -> tag commands LED_A_ON();
memset(&Uart, 0, sizeof(Uart)); WDT_HIT();
Uart.output = receivedCmd;
Uart.byteCntMax = 32; // was 100 (greg)////////////////////////////////////////////////////////////////////////
Uart.state = STATE_UNSYNCD;
// And put the FPGA in the appropriate mode int register readBufDataP = data - dmaBuf;
// Signal field is off with the appropriate LED int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
LED_D_OFF(); if (readBufDataP <= dmaBufDataP){
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER); dataLen = dmaBufDataP - readBufDataP;
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); } else {
dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP + 1;
}
// test for length of buffer
if(dataLen > maxDataLen) {
maxDataLen = dataLen;
if(dataLen > 400) {
Dbprintf("blew circular buffer! dataLen=0x%x", dataLen);
goto done;
}
}
if(dataLen < 1) continue;
// primary buffer was stopped( <-- we lost data!
if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
Dbprintf("RxEmpty ERROR!!! %d", dataLen); // temporary
}
// secondary buffer sets as primary, secondary buffer was stopped
if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
}
// And now we loop, receiving samples. LED_A_OFF();
for(;;) {
LED_A_ON(); rsamples += 4;
WDT_HIT(); if(MillerDecoding((data[0] & 0xF0) >> 4)) {
int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) & LED_C_ON();
(DMA_BUFFER_SIZE-1);
if(behindBy > maxBehindBy) {
maxBehindBy = behindBy;
if(behindBy > 400) {
Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
goto done;
}
}
if(behindBy < 1) continue;
LED_A_OFF(); // check - if there is a short 7bit request from reader
smpl = upTo[0]; if ((!triggered) && (param & 0x02) && (Uart.byteCnt == 1) && (Uart.bitCnt = 9)) triggered = TRUE;
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; if(triggered) {
if(MillerDecoding((smpl & 0xF0) >> 4)) { if (!LogTrace(receivedCmd, Uart.byteCnt, 0 - Uart.samples, Uart.parityBits, TRUE)) break;
rsamples = samples - Uart.samples; }
LED_C_ON(); /* And ready to receive another command. */
if(triggered) { Uart.state = STATE_UNSYNCD;
trace[traceLen++] = ((rsamples >> 0) & 0xff); /* And also reset the demod code, which might have been */
trace[traceLen++] = ((rsamples >> 8) & 0xff); /* false-triggered by the commands from the reader. */
trace[traceLen++] = ((rsamples >> 16) & 0xff); Demod.state = DEMOD_UNSYNCD;
trace[traceLen++] = ((rsamples >> 24) & 0xff); LED_B_OFF();
trace[traceLen++] = ((Uart.parityBits >> 0) & 0xff); }
trace[traceLen++] = ((Uart.parityBits >> 8) & 0xff);
trace[traceLen++] = ((Uart.parityBits >> 16) & 0xff);
trace[traceLen++] = ((Uart.parityBits >> 24) & 0xff);
trace[traceLen++] = Uart.byteCnt;
memcpy(trace+traceLen, receivedCmd, Uart.byteCnt);
traceLen += Uart.byteCnt;
if(traceLen > TRACE_SIZE) break;
}
/* 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;
LED_B_OFF();
}
if(ManchesterDecoding(smpl & 0x0F)) { if(ManchesterDecoding(data[0] & 0x0F)) {
rsamples = samples - Demod.samples; LED_B_ON();
LED_B_ON();
// timestamp, as a count of samples if (!LogTrace(receivedResponse, Demod.len, 0 - Demod.samples, Demod.parityBits, FALSE)) break;
trace[traceLen++] = ((rsamples >> 0) & 0xff);
trace[traceLen++] = ((rsamples >> 8) & 0xff);
trace[traceLen++] = ((rsamples >> 16) & 0xff);
trace[traceLen++] = 0x80 | ((rsamples >> 24) & 0xff);
trace[traceLen++] = ((Demod.parityBits >> 0) & 0xff);
trace[traceLen++] = ((Demod.parityBits >> 8) & 0xff);
trace[traceLen++] = ((Demod.parityBits >> 16) & 0xff);
trace[traceLen++] = ((Demod.parityBits >> 24) & 0xff);
// length
trace[traceLen++] = Demod.len;
memcpy(trace+traceLen, receivedResponse, Demod.len);
traceLen += Demod.len;
if(traceLen > TRACE_SIZE) break;
triggered = TRUE; if ((!triggered) && (param & 0x01)) triggered = TRUE;
// And ready to receive another response. // And ready to receive another response.
memset(&Demod, 0, sizeof(Demod)); memset(&Demod, 0, sizeof(Demod));
Demod.output = receivedResponse; Demod.output = receivedResponse;
Demod.state = DEMOD_UNSYNCD; Demod.state = DEMOD_UNSYNCD;
LED_C_OFF(); LED_C_OFF();
} }
if(BUTTON_PRESS()) { data++;
DbpString("cancelled_a"); if(data > dmaBuf + DMA_BUFFER_SIZE) {
goto done; data = dmaBuf;
} }
} } // main cycle
DbpString("COMMAND FINISHED"); DbpString("COMMAND FINISHED");
done: done:
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
Dbprintf("maxBehindBy=%x, Uart.state=%x, Uart.byteCnt=%x", maxBehindBy, Uart.state, Uart.byteCnt); Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.byteCnt=%x", maxDataLen, Uart.state, Uart.byteCnt);
Dbprintf("Uart.byteCntMax=%x, traceLen=%x, Uart.output[0]=%x", Uart.byteCntMax, traceLen, (int)Uart.output[0]); Dbprintf("Uart.byteCntMax=%x, traceLen=%x, Uart.output[0]=%08x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);
LED_A_OFF(); LEDsoff();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -2369,17 +2352,16 @@ lbWORK: if (len == 0) break;
// MIFARE sniffer. // MIFARE sniffer.
// //
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void RAMFUNC SniffMifare(void) { void RAMFUNC SniffMifare(uint8_t param) {
// param:
// bit 0 - trigger from first card answer
// bit 1 - trigger from first reader 7-bit request
LEDsoff(); LEDsoff();
// init trace buffer // init trace buffer
traceLen = 0; traceLen = 0;
memset(trace, 0x44, TRACE_SIZE); memset(trace, 0x44, TRACE_SIZE);
// 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 command (reader -> tag) that we're receiving.
// The length of a received command will in most cases be no more than 18 bytes. // The length of a received command will in most cases be no more than 18 bytes.
// So 32 should be enough! // So 32 should be enough!
@ -2393,10 +2375,10 @@ void RAMFUNC SniffMifare(void) {
// The DMA buffer, used to stream samples from the FPGA // The DMA buffer, used to stream samples from the FPGA
int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET; int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET;
int lastRxCounter; int8_t *data = dmaBuf;
int8_t *upTo; int maxDataLen = 0;
int smpl; int dataLen = 0;
int maxBehindBy = 0; // data = dmaBuf;
// Set up the demodulator for tag -> reader responses. // Set up the demodulator for tag -> reader responses.
Demod.output = receivedResponse; Demod.output = receivedResponse;
@ -2411,8 +2393,6 @@ void RAMFUNC SniffMifare(void) {
// Setup for the DMA. // Setup for the DMA.
FpgaSetupSsc(); FpgaSetupSsc();
upTo = dmaBuf;
lastRxCounter = DMA_BUFFER_SIZE;
FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
// And put the FPGA in the appropriate mode // And put the FPGA in the appropriate mode
@ -2426,37 +2406,54 @@ void RAMFUNC SniffMifare(void) {
rsamples = 0; rsamples = 0;
// And now we loop, receiving samples. // And now we loop, receiving samples.
while(true) { while(true) {
if(BUTTON_PRESS()) {
DbpString("cancelled by button");
goto done;
}
LED_A_ON(); LED_A_ON();
WDT_HIT(); WDT_HIT();
int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
(DMA_BUFFER_SIZE-1); int register readBufDataP = data - dmaBuf;
if(behindBy > maxBehindBy) { int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
maxBehindBy = behindBy; if (readBufDataP <= dmaBufDataP){
if(behindBy > 400) { dataLen = dmaBufDataP - readBufDataP;
Dbprintf("blew circular buffer! behindBy=0x%x", behindBy); } else {
dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP + 1;
}
// test for length of buffer
if(dataLen > maxDataLen) {
maxDataLen = dataLen;
if(dataLen > 400) {
Dbprintf("blew circular buffer! dataLen=0x%x", dataLen);
goto done; goto done;
} }
} }
if(behindBy < 1) continue; if(dataLen < 1) continue;
// primary buffer was stopped( <-- we lost data!
if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
Dbprintf("RxEmpty ERROR!!! %d", dataLen); // temporary
}
// secondary buffer sets as primary, secondary buffer was stopped
if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
}
LED_A_OFF(); 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;
}
rsamples += 4; rsamples += 4;
if(MillerDecoding((smpl & 0xF0) >> 4)) { if(MillerDecoding((data[0] & 0xF0) >> 4)) {
LED_C_ON(); LED_C_ON();
if(triggered) { // check - if there is a short 7bit request from reader
if (!LogTrace(receivedCmd, Uart.byteCnt, -1 * Uart.samples, Uart.parityBits, TRUE)) break; if ((Uart.byteCnt == 1) && (Uart.bitCnt = 9)) {
} }
if (!LogTrace(receivedCmd, Uart.byteCnt, 0 - Uart.samples, Uart.parityBits, TRUE)) break;
/* And ready to receive another command. */ /* And ready to receive another command. */
Uart.state = STATE_UNSYNCD; Uart.state = STATE_UNSYNCD;
/* And also reset the demod code, which might have been */ /* And also reset the demod code, which might have been */
@ -2465,12 +2462,10 @@ void RAMFUNC SniffMifare(void) {
LED_B_OFF(); LED_B_OFF();
} }
if(ManchesterDecoding(smpl & 0x0F)) { if(ManchesterDecoding(data[0] & 0x0F)) {
LED_B_ON(); LED_B_ON();
if (!LogTrace(receivedResponse, Demod.len, -1 * Demod.samples, Demod.parityBits, FALSE)) break; if (!LogTrace(receivedResponse, Demod.len, 0 - Demod.samples, Demod.parityBits, FALSE)) break;
triggered = TRUE;
// And ready to receive another response. // And ready to receive another response.
memset(&Demod, 0, sizeof(Demod)); memset(&Demod, 0, sizeof(Demod));
@ -2479,9 +2474,9 @@ void RAMFUNC SniffMifare(void) {
LED_C_OFF(); LED_C_OFF();
} }
if(BUTTON_PRESS()) { data++;
DbpString("button cancelled"); if(data > dmaBuf + DMA_BUFFER_SIZE) {
goto done; data = dmaBuf;
} }
} // main cycle } // main cycle
@ -2489,7 +2484,7 @@ void RAMFUNC SniffMifare(void) {
done: done:
AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
Dbprintf("maxBehindBy=%x, Uart.state=%x, Uart.byteCnt=%x", maxBehindBy, Uart.state, Uart.byteCnt); Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.byteCnt=%x", maxDataLen, Uart.state, Uart.byteCnt);
Dbprintf("Uart.byteCntMax=%x, traceLen=%x, Uart.output[0]=%x", Uart.byteCntMax, traceLen, (int)Uart.output[0]); Dbprintf("Uart.byteCntMax=%x, traceLen=%x, Uart.output[0]=%x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);
LEDsoff(); LEDsoff();
} }

View file

@ -93,6 +93,5 @@ extern void iso14a_set_trigger(int enable);
extern void iso14a_clear_tracelen(void); extern void iso14a_clear_tracelen(void);
extern void iso14a_set_tracing(int enable); extern void iso14a_set_tracing(int enable);
extern int LogTrace(const uint8_t * btBytes, int iLen, int iSamples, uint32_t dwParity, int bReader);
#endif /* __ISO14443A_H */ #endif /* __ISO14443A_H */

View file

@ -284,9 +284,26 @@ int CmdHF14ASim(const char *Cmd)
return 0; return 0;
} }
int CmdHF14ASnoop(const char *Cmd) int CmdHF14ASnoop(const char *Cmd) {
{ int param = 0;
UsbCommand c = {CMD_SNOOP_ISO_14443a};
if (param_getchar(Cmd, 0) == 'h') {
PrintAndLog("It get data from the field and saves it into command buffer.");
PrintAndLog("Buffer accessible from command hf 14a list.");
PrintAndLog("Usage: hf 14a snoop [c][r]");
PrintAndLog("c - triggered by first data from card");
PrintAndLog("r - triggered by first 7-bit request from reader (REQ,WUP,...)");
PrintAndLog("sample: hf 14a snoop c r");
return 0;
}
for (int i = 0; i < 2; i++) {
char ctmp = param_getchar(Cmd, i);
if (ctmp == 'c' || ctmp == 'C') param |= 0x01;
if (ctmp == 'r' || ctmp == 'R') param |= 0x02;
}
UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}};
SendCommand(&c); SendCommand(&c);
return 0; return 0;
} }