mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-07-21 06:51:29 +00:00
Merge pull request #34 from marshmellow42/master
Fsk demod fixes and additions to client for offline demoding
This commit is contained in:
@@ -35,6 +35,7 @@ ARMSRC = fpgaloader.c \
|
||||
legicrf.c \
|
||||
iso14443crc.c \
|
||||
crc16.c \
|
||||
lfdemod.c \
|
||||
$(SRC_ISO14443a) \
|
||||
$(SRC_ISO14443b) \
|
||||
$(SRC_CRAPTO1) \
|
||||
|
||||
@@ -649,6 +649,9 @@ void UsbPacketReceived(uint8_t *packet, int len)
|
||||
case CMD_IO_CLONE_TAG: // Clone IO tag by ID to T55x7
|
||||
CopyIOtoT55x7(c->arg[0], c->arg[1], c->d.asBytes[0]);
|
||||
break;
|
||||
case CMD_EM410X_DEMOD:
|
||||
CmdEM410xdemod(c->arg[0], 0, 0, 1);
|
||||
break;
|
||||
case CMD_EM410X_WRITE_TAG:
|
||||
WriteEM410x(c->arg[0], c->arg[1], c->arg[2]);
|
||||
break;
|
||||
|
||||
@@ -132,6 +132,7 @@ void AcquireRawBitsTI(void);
|
||||
void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
|
||||
void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
|
||||
void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol);
|
||||
void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol);
|
||||
void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol);
|
||||
void CopyIOtoT55x7(uint32_t hi, uint32_t lo, uint8_t longFMT); // Clone an ioProx card to T5557/T5567
|
||||
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
|
||||
|
||||
+161
-232
@@ -14,6 +14,7 @@
|
||||
#include "hitag2.h"
|
||||
#include "crc16.h"
|
||||
#include "string.h"
|
||||
#include "lfdemod.h"
|
||||
|
||||
|
||||
/**
|
||||
@@ -630,87 +631,12 @@ void CmdHIDsimTAG(int hi, int lo, int ledcontrol)
|
||||
LED_A_OFF();
|
||||
}
|
||||
|
||||
size_t fsk_demod(uint8_t * dest, size_t size)
|
||||
{
|
||||
uint32_t last_transition = 0;
|
||||
uint32_t idx = 1;
|
||||
// we don't care about actual value, only if it's more or less than a
|
||||
// threshold essentially we capture zero crossings for later analysis
|
||||
uint8_t threshold_value = 127;
|
||||
|
||||
// sync to first lo-hi transition, and threshold
|
||||
|
||||
//Need to threshold first sample
|
||||
if(dest[0] < threshold_value) dest[0] = 0;
|
||||
else dest[0] = 1;
|
||||
|
||||
size_t numBits = 0;
|
||||
// count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
|
||||
// or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere
|
||||
// between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
|
||||
for(idx = 1; idx < size; idx++) {
|
||||
// threshold current value
|
||||
if (dest[idx] < threshold_value) dest[idx] = 0;
|
||||
else dest[idx] = 1;
|
||||
|
||||
// Check for 0->1 transition
|
||||
if (dest[idx-1] < dest[idx]) { // 0 -> 1 transition
|
||||
|
||||
if (idx-last_transition < 9) {
|
||||
dest[numBits]=1;
|
||||
} else {
|
||||
dest[numBits]=0;
|
||||
}
|
||||
last_transition = idx;
|
||||
numBits++;
|
||||
}
|
||||
}
|
||||
return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0
|
||||
}
|
||||
|
||||
|
||||
size_t aggregate_bits(uint8_t *dest,size_t size, uint8_t h2l_crossing_value,uint8_t l2h_crossing_value, uint8_t maxConsequtiveBits, uint8_t invert )
|
||||
{
|
||||
uint8_t lastval=dest[0];
|
||||
uint32_t idx=0;
|
||||
size_t numBits=0;
|
||||
uint32_t n=1;
|
||||
|
||||
for( idx=1; idx < size; idx++) {
|
||||
|
||||
if (dest[idx]==lastval) {
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
//if lastval was 1, we have a 1->0 crossing
|
||||
if ( dest[idx-1]==1 ) {
|
||||
n=(n+1) / h2l_crossing_value;
|
||||
} else {// 0->1 crossing
|
||||
n=(n+1) / l2h_crossing_value;
|
||||
}
|
||||
if (n == 0) n = 1;
|
||||
|
||||
if(n < maxConsequtiveBits) //Consecutive
|
||||
{
|
||||
if(invert==0){ //invert bits
|
||||
memset(dest+numBits, dest[idx-1] , n);
|
||||
}else{
|
||||
memset(dest+numBits, dest[idx-1]^1 , n);
|
||||
}
|
||||
|
||||
numBits += n;
|
||||
}
|
||||
n=0;
|
||||
lastval=dest[idx];
|
||||
}//end for
|
||||
return numBits;
|
||||
}
|
||||
// loop to capture raw HID waveform then FSK demodulate the TAG ID from it
|
||||
// loop to get raw HID waveform then FSK demodulate the TAG ID from it
|
||||
void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||
{
|
||||
uint8_t *dest = (uint8_t *)BigBuf;
|
||||
|
||||
size_t size=0,idx=0; //, found=0;
|
||||
size_t size=0; //, found=0;
|
||||
uint32_t hi2=0, hi=0, lo=0;
|
||||
|
||||
// Configure to go in 125Khz listen mode
|
||||
@@ -723,139 +649,143 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||
|
||||
DoAcquisition125k_internal(-1,true);
|
||||
size = sizeof(BigBuf);
|
||||
|
||||
if (size < 2000) continue;
|
||||
// FSK demodulator
|
||||
size = fsk_demod(dest, size);
|
||||
|
||||
// we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns
|
||||
// 1->0 : fc/8 in sets of 6 (RF/50 / 8 = 6.25)
|
||||
// 0->1 : fc/10 in sets of 5 (RF/50 / 10= 5)
|
||||
// do not invert
|
||||
size = aggregate_bits(dest,size, 6,5,5,0);
|
||||
|
||||
int bitLen = HIDdemodFSK(dest,size,&hi2,&hi,&lo);
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
if (bitLen>0 && lo>0){
|
||||
// final loop, go over previously decoded manchester data and decode into usable tag ID
|
||||
// 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0
|
||||
uint8_t frame_marker_mask[] = {1,1,1,0,0,0};
|
||||
int numshifts = 0;
|
||||
idx = 0;
|
||||
while( idx + sizeof(frame_marker_mask) < size) {
|
||||
// search for a start of frame marker
|
||||
if ( memcmp(dest+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0)
|
||||
{ // frame marker found
|
||||
idx+=sizeof(frame_marker_mask);
|
||||
while(dest[idx] != dest[idx+1] && idx < size-2)
|
||||
{
|
||||
// Keep going until next frame marker (or error)
|
||||
// Shift in a bit. Start by shifting high registers
|
||||
hi2 = (hi2<<1)|(hi>>31);
|
||||
hi = (hi<<1)|(lo>>31);
|
||||
//Then, shift in a 0 or one into low
|
||||
if (dest[idx] && !dest[idx+1]) // 1 0
|
||||
lo=(lo<<1)|0;
|
||||
else // 0 1
|
||||
lo=(lo<<1)|
|
||||
1;
|
||||
numshifts++;
|
||||
idx += 2;
|
||||
}
|
||||
//Dbprintf("Num shifts: %d ", numshifts);
|
||||
// Hopefully, we read a tag and hit upon the next frame marker
|
||||
if(idx + sizeof(frame_marker_mask) < size)
|
||||
{
|
||||
if ( memcmp(dest+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0)
|
||||
{
|
||||
if (hi2 != 0){ //extra large HID tags
|
||||
Dbprintf("TAG ID: %x%08x%08x (%d)",
|
||||
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
|
||||
}
|
||||
else { //standard HID tags <38 bits
|
||||
//Dbprintf("TAG ID: %x%08x (%d)",(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); //old print cmd
|
||||
uint8_t bitlen = 0;
|
||||
uint32_t fc = 0;
|
||||
uint32_t cardnum = 0;
|
||||
if (((hi>>5)&1)==1){//if bit 38 is set then < 37 bit format is used
|
||||
uint32_t lo2=0;
|
||||
lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit
|
||||
uint8_t idx3 = 1;
|
||||
while(lo2>1){ //find last bit set to 1 (format len bit)
|
||||
lo2=lo2>>1;
|
||||
idx3++;
|
||||
}
|
||||
bitlen =idx3+19;
|
||||
fc =0;
|
||||
cardnum=0;
|
||||
if(bitlen==26){
|
||||
cardnum = (lo>>1)&0xFFFF;
|
||||
fc = (lo>>17)&0xFF;
|
||||
}
|
||||
if(bitlen==37){
|
||||
cardnum = (lo>>1)&0x7FFFF;
|
||||
fc = ((hi&0xF)<<12)|(lo>>20);
|
||||
}
|
||||
if(bitlen==34){
|
||||
cardnum = (lo>>1)&0xFFFF;
|
||||
fc= ((hi&1)<<15)|(lo>>17);
|
||||
}
|
||||
if(bitlen==35){
|
||||
cardnum = (lo>>1)&0xFFFFF;
|
||||
fc = ((hi&1)<<11)|(lo>>21);
|
||||
}
|
||||
}
|
||||
else { //if bit 38 is not set then 37 bit format is used
|
||||
bitlen= 37;
|
||||
fc =0;
|
||||
cardnum=0;
|
||||
if(bitlen==37){
|
||||
cardnum = (lo>>1)&0x7FFFF;
|
||||
fc = ((hi&0xF)<<12)|(lo>>20);
|
||||
}
|
||||
}
|
||||
//Dbprintf("TAG ID: %x%08x (%d)",
|
||||
// (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
|
||||
Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
|
||||
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
(unsigned int) bitlen, (unsigned int) fc, (unsigned int) cardnum);
|
||||
}
|
||||
if (findone){
|
||||
if (ledcontrol) LED_A_OFF();
|
||||
return;
|
||||
}
|
||||
if (hi2 != 0){ //extra large HID tags
|
||||
Dbprintf("TAG ID: %x%08x%08x (%d)",
|
||||
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
|
||||
}else { //standard HID tags <38 bits
|
||||
//Dbprintf("TAG ID: %x%08x (%d)",(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); //old print cmd
|
||||
uint8_t bitlen = 0;
|
||||
uint32_t fc = 0;
|
||||
uint32_t cardnum = 0;
|
||||
if (((hi>>5)&1)==1){//if bit 38 is set then < 37 bit format is used
|
||||
uint32_t lo2=0;
|
||||
lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit
|
||||
uint8_t idx3 = 1;
|
||||
while(lo2>1){ //find last bit set to 1 (format len bit)
|
||||
lo2=lo2>>1;
|
||||
idx3++;
|
||||
}
|
||||
bitlen =idx3+19;
|
||||
fc =0;
|
||||
cardnum=0;
|
||||
if(bitlen==26){
|
||||
cardnum = (lo>>1)&0xFFFF;
|
||||
fc = (lo>>17)&0xFF;
|
||||
}
|
||||
if(bitlen==37){
|
||||
cardnum = (lo>>1)&0x7FFFF;
|
||||
fc = ((hi&0xF)<<12)|(lo>>20);
|
||||
}
|
||||
if(bitlen==34){
|
||||
cardnum = (lo>>1)&0xFFFF;
|
||||
fc= ((hi&1)<<15)|(lo>>17);
|
||||
}
|
||||
if(bitlen==35){
|
||||
cardnum = (lo>>1)&0xFFFFF;
|
||||
fc = ((hi&1)<<11)|(lo>>21);
|
||||
}
|
||||
}
|
||||
// reset
|
||||
hi2 = hi = lo = 0;
|
||||
numshifts = 0;
|
||||
}else
|
||||
{
|
||||
idx++;
|
||||
else { //if bit 38 is not set then 37 bit format is used
|
||||
bitlen= 37;
|
||||
fc =0;
|
||||
cardnum=0;
|
||||
if(bitlen==37){
|
||||
cardnum = (lo>>1)&0x7FFFF;
|
||||
fc = ((hi&0xF)<<12)|(lo>>20);
|
||||
}
|
||||
}
|
||||
//Dbprintf("TAG ID: %x%08x (%d)",
|
||||
// (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
|
||||
Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
|
||||
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
(unsigned int) bitlen, (unsigned int) fc, (unsigned int) cardnum);
|
||||
}
|
||||
if (findone){
|
||||
if (ledcontrol) LED_A_OFF();
|
||||
return;
|
||||
}
|
||||
// reset
|
||||
hi2 = hi = lo = 0;
|
||||
}
|
||||
WDT_HIT();
|
||||
|
||||
}
|
||||
//SpinDelay(50);
|
||||
}
|
||||
DbpString("Stopped");
|
||||
if (ledcontrol) LED_A_OFF();
|
||||
}
|
||||
|
||||
uint32_t bytebits_to_byte(uint8_t* src, int numbits)
|
||||
void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
|
||||
{
|
||||
uint32_t num = 0;
|
||||
for(int i = 0 ; i < numbits ; i++)
|
||||
{
|
||||
num = (num << 1) | (*src);
|
||||
src++;
|
||||
}
|
||||
return num;
|
||||
uint8_t *dest = (uint8_t *)BigBuf;
|
||||
|
||||
size_t size=0; //, found=0;
|
||||
uint32_t bitLen=0;
|
||||
int clk=0, invert=0, errCnt=0;
|
||||
uint64_t lo=0;
|
||||
// Configure to go in 125Khz listen mode
|
||||
LFSetupFPGAForADC(95, true);
|
||||
|
||||
while(!BUTTON_PRESS()) {
|
||||
|
||||
WDT_HIT();
|
||||
if (ledcontrol) LED_A_ON();
|
||||
|
||||
DoAcquisition125k_internal(-1,true);
|
||||
size = sizeof(BigBuf);
|
||||
if (size < 2000) continue;
|
||||
// FSK demodulator
|
||||
//int askmandemod(uint8_t *BinStream,uint32_t *BitLen,int *clk, int *invert);
|
||||
bitLen=size;
|
||||
//Dbprintf("DEBUG: Buffer got");
|
||||
errCnt = askmandemod(dest,&bitLen,&clk,&invert); //HIDdemodFSK(dest,size,&hi2,&hi,&lo);
|
||||
//Dbprintf("DEBUG: ASK Got");
|
||||
WDT_HIT();
|
||||
|
||||
if (errCnt>=0){
|
||||
lo = Em410xDecode(dest,bitLen);
|
||||
//Dbprintf("DEBUG: EM GOT");
|
||||
//printEM410x(lo);
|
||||
if (lo>0){
|
||||
Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)",(uint32_t)(lo>>32),(uint32_t)lo,(uint32_t)(lo&0xFFFF),(uint32_t)((lo>>16LL) & 0xFF),(uint32_t)(lo & 0xFFFFFF));
|
||||
}
|
||||
if (findone){
|
||||
if (ledcontrol) LED_A_OFF();
|
||||
return;
|
||||
}
|
||||
} else{
|
||||
//Dbprintf("DEBUG: No Tag");
|
||||
}
|
||||
WDT_HIT();
|
||||
lo = 0;
|
||||
clk=0;
|
||||
invert=0;
|
||||
errCnt=0;
|
||||
size=0;
|
||||
//SpinDelay(50);
|
||||
}
|
||||
DbpString("Stopped");
|
||||
if (ledcontrol) LED_A_OFF();
|
||||
}
|
||||
|
||||
void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||
{
|
||||
uint8_t *dest = (uint8_t *)BigBuf;
|
||||
size_t size=0, idx=0;
|
||||
size_t size=0;
|
||||
int idx=0;
|
||||
uint32_t code=0, code2=0;
|
||||
|
||||
uint8_t version=0;
|
||||
uint8_t facilitycode=0;
|
||||
uint16_t number=0;
|
||||
// Configure to go in 125Khz listen mode
|
||||
LFSetupFPGAForADC(95, true);
|
||||
|
||||
@@ -864,51 +794,50 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
||||
if (ledcontrol) LED_A_ON();
|
||||
DoAcquisition125k_internal(-1,true);
|
||||
size = sizeof(BigBuf);
|
||||
|
||||
// FSK demodulator
|
||||
size = fsk_demod(dest, size);
|
||||
// we now have a set of cycle counts, loop over previous results and aggregate data into bit patterns
|
||||
// 1->0 : fc/8 in sets of 7 (RF/64 / 8 = 8)
|
||||
// 0->1 : fc/10 in sets of 6 (RF/64 / 10 = 6.4)
|
||||
size = aggregate_bits(dest, size, 7,6,13,1); //13 max Consecutive should be ok as most 0s in row should be 10 for init seq - invert bits
|
||||
//make sure buffer has data
|
||||
if (size < 2000) continue;
|
||||
//fskdemod and get start index
|
||||
WDT_HIT();
|
||||
//Index map
|
||||
//0 10 20 30 40 50 60
|
||||
//| | | | | | |
|
||||
//01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
|
||||
//-----------------------------------------------------------------------------
|
||||
//00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
|
||||
//
|
||||
//XSF(version)facility:codeone+codetwo
|
||||
//Handle the data
|
||||
uint8_t mask[] = {0,0,0,0,0,0,0,0,0,1};
|
||||
for( idx=0; idx < (size - 64); idx++) {
|
||||
if ( memcmp(dest + idx, mask, sizeof(mask))==0) {
|
||||
//frame marker found
|
||||
if(findone){ //only print binary if we are doing one
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);
|
||||
}
|
||||
code = bytebits_to_byte(dest+idx,32);
|
||||
code2 = bytebits_to_byte(dest+idx+32,32);
|
||||
short version = bytebits_to_byte(dest+idx+28,8); //14,4
|
||||
char facilitycode = bytebits_to_byte(dest+idx+19,8) ;
|
||||
uint16_t number = (bytebits_to_byte(dest+idx+37,8)<<8)|(bytebits_to_byte(dest+idx+46,8)); //36,9
|
||||
|
||||
Dbprintf("XSF(%02d)%02x:%d (%08x%08x)",version,facilitycode,number,code,code2);
|
||||
// if we're only looking for one tag
|
||||
if (findone){
|
||||
if (ledcontrol) LED_A_OFF();
|
||||
//LED_A_OFF();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
idx = IOdemodFSK(dest,size);
|
||||
if (idx>0){
|
||||
//valid tag found
|
||||
|
||||
//Index map
|
||||
//0 10 20 30 40 50 60
|
||||
//| | | | | | |
|
||||
//01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
|
||||
//-----------------------------------------------------------------------------
|
||||
//00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
|
||||
//
|
||||
//XSF(version)facility:codeone+codetwo
|
||||
//Handle the data
|
||||
if(findone){ //only print binary if we are doing one
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]);
|
||||
Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);
|
||||
}
|
||||
code = bytebits_to_byte(dest+idx,32);
|
||||
code2 = bytebits_to_byte(dest+idx+32,32);
|
||||
version = bytebits_to_byte(dest+idx+27,8); //14,4
|
||||
facilitycode = bytebits_to_byte(dest+idx+18,8) ;
|
||||
number = (bytebits_to_byte(dest+idx+36,8)<<8)|(bytebits_to_byte(dest+idx+45,8)); //36,9
|
||||
|
||||
Dbprintf("XSF(%02d)%02x:%05d (%08x%08x)",version,facilitycode,number,code,code2);
|
||||
// if we're only looking for one tag
|
||||
if (findone){
|
||||
if (ledcontrol) LED_A_OFF();
|
||||
//LED_A_OFF();
|
||||
return;
|
||||
}
|
||||
code=code2=0;
|
||||
version=facilitycode=0;
|
||||
number=0;
|
||||
idx=0;
|
||||
}
|
||||
WDT_HIT();
|
||||
}
|
||||
DbpString("Stopped");
|
||||
|
||||
@@ -70,6 +70,7 @@ CMDSRCS = nonce2key/crapto1.c\
|
||||
graph.c \
|
||||
ui.c \
|
||||
cmddata.c \
|
||||
lfdemod.c \
|
||||
cmdhf.c \
|
||||
cmdhf14a.c \
|
||||
cmdhf14b.c \
|
||||
|
||||
+497
-89
@@ -20,6 +20,7 @@
|
||||
#include "util.h"
|
||||
#include "cmdmain.h"
|
||||
#include "cmddata.h"
|
||||
#include "lfdemod.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
@@ -69,6 +70,7 @@ int CmdAmp(const char *Cmd)
|
||||
* Arguments:
|
||||
* c : 0 or 1
|
||||
*/
|
||||
//this method is dependant on all highs and lows to be the same(or clipped) this creates issues[marshmellow] it also ignores the clock
|
||||
int Cmdaskdemod(const char *Cmd)
|
||||
{
|
||||
int i;
|
||||
@@ -79,7 +81,7 @@ int Cmdaskdemod(const char *Cmd)
|
||||
sscanf(Cmd, "%i", &c);
|
||||
|
||||
/* Detect high and lows and clock */
|
||||
// (AL - clock???)
|
||||
// (AL - clock???)
|
||||
for (i = 0; i < GraphTraceLen; ++i)
|
||||
{
|
||||
if (GraphBuffer[i] > high)
|
||||
@@ -87,11 +89,13 @@ int Cmdaskdemod(const char *Cmd)
|
||||
else if (GraphBuffer[i] < low)
|
||||
low = GraphBuffer[i];
|
||||
}
|
||||
high=abs(high*.75);
|
||||
low=abs(low*.75);
|
||||
if (c != 0 && c != 1) {
|
||||
PrintAndLog("Invalid argument: %s", Cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//prime loop
|
||||
if (GraphBuffer[0] > 0) {
|
||||
GraphBuffer[0] = 1-c;
|
||||
} else {
|
||||
@@ -106,6 +110,7 @@ int Cmdaskdemod(const char *Cmd)
|
||||
* low for long periods, others just reach the peak and go
|
||||
* down)
|
||||
*/
|
||||
//[marhsmellow] change == to >= for high and <= for low for fuzz
|
||||
if ((GraphBuffer[i] == high) && (GraphBuffer[i - 1] == c)) {
|
||||
GraphBuffer[i] = 1 - c;
|
||||
} else if ((GraphBuffer[i] == low) && (GraphBuffer[i - 1] == (1 - c))){
|
||||
@@ -119,6 +124,250 @@ int Cmdaskdemod(const char *Cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
void printBitStream(uint8_t BitStream[], uint32_t bitLen)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
if (bitLen<16) {
|
||||
PrintAndLog("Too few bits found: %d",bitLen);
|
||||
return;
|
||||
}
|
||||
if (bitLen>512) bitLen=512;
|
||||
for (i = 0; i <= (bitLen-16); i+=16) {
|
||||
PrintAndLog("%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i",
|
||||
BitStream[i],
|
||||
BitStream[i+1],
|
||||
BitStream[i+2],
|
||||
BitStream[i+3],
|
||||
BitStream[i+4],
|
||||
BitStream[i+5],
|
||||
BitStream[i+6],
|
||||
BitStream[i+7],
|
||||
BitStream[i+8],
|
||||
BitStream[i+9],
|
||||
BitStream[i+10],
|
||||
BitStream[i+11],
|
||||
BitStream[i+12],
|
||||
BitStream[i+13],
|
||||
BitStream[i+14],
|
||||
BitStream[i+15]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
//by marshmellow
|
||||
void printEM410x(uint64_t id)
|
||||
{
|
||||
if (id !=0){
|
||||
uint64_t iii=1;
|
||||
uint64_t id2lo=0; //id2hi=0,
|
||||
uint32_t ii=0;
|
||||
uint32_t i=0;
|
||||
for (ii=5; ii>0;ii--){
|
||||
for (i=0;i<8;i++){
|
||||
id2lo=(id2lo<<1LL)|((id & (iii<<(i+((ii-1)*8))))>>(i+((ii-1)*8)));
|
||||
}
|
||||
}
|
||||
//output em id
|
||||
PrintAndLog("EM TAG ID : %010llx", id);
|
||||
PrintAndLog("Unique TAG ID: %010llx", id2lo); //id2hi,
|
||||
PrintAndLog("DEZ 8 : %08lld",id & 0xFFFFFF);
|
||||
PrintAndLog("DEZ 10 : %010lld",id & 0xFFFFFF);
|
||||
PrintAndLog("DEZ 5.5 : %05lld.%05lld",(id>>16LL) & 0xFFFF,(id & 0xFFFF));
|
||||
PrintAndLog("DEZ 3.5A : %03lld.%05lld",(id>>32ll),(id & 0xFFFF));
|
||||
PrintAndLog("DEZ 14/IK2 : %014lld",id);
|
||||
PrintAndLog("DEZ 15/IK3 : %015lld",id2lo);
|
||||
PrintAndLog("Other : %05lld_%03lld_%08lld",(id&0xFFFF),((id>>16LL) & 0xFF),(id & 0xFFFFFF));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
int CmdEm410xDecode(const char *Cmd)
|
||||
{
|
||||
uint64_t id=0;
|
||||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
|
||||
uint32_t i=0;
|
||||
i=getFromGraphBuf(BitStream);
|
||||
id = Em410xDecode(BitStream,i);
|
||||
printEM410x(id);
|
||||
if (id>0) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//by marshmellow
|
||||
//takes 2 arguments - clock and invert both as integers
|
||||
//attempts to demodulate ask while decoding manchester
|
||||
//prints binary found and saves in graphbuffer for further commands
|
||||
int Cmdaskmandemod(const char *Cmd)
|
||||
{
|
||||
int invert=0;
|
||||
int clk=0;
|
||||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
|
||||
sscanf(Cmd, "%i %i", &clk, &invert);
|
||||
if (invert != 0 && invert != 1) {
|
||||
PrintAndLog("Invalid argument: %s", Cmd);
|
||||
return 0;
|
||||
}
|
||||
uint32_t BitLen = getFromGraphBuf(BitStream);
|
||||
// PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen);
|
||||
int errCnt=0;
|
||||
errCnt = askmandemod(BitStream, &BitLen,&clk,&invert);
|
||||
if (errCnt<0){ //if fatal error (or -1)
|
||||
// PrintAndLog("no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk);
|
||||
return 0;
|
||||
}
|
||||
if (BitLen<16) return 0;
|
||||
PrintAndLog("\nUsing Clock: %d - Invert: %d - Bits Found: %d",clk,invert,BitLen);
|
||||
|
||||
//output
|
||||
if (errCnt>0){
|
||||
PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt);
|
||||
}
|
||||
PrintAndLog("ASK/Manchester decoded bitstream:");
|
||||
// Now output the bitstream to the scrollback by line of 16 bits
|
||||
printBitStream(BitStream,BitLen);
|
||||
uint64_t lo =0;
|
||||
lo = Em410xDecode(BitStream,BitLen);
|
||||
if (lo>0){
|
||||
//set GraphBuffer for clone or sim command
|
||||
setGraphBuf(BitStream,BitLen);
|
||||
PrintAndLog("EM410x pattern found: ");
|
||||
printEM410x(lo);
|
||||
return 1;
|
||||
}
|
||||
//if (BitLen>16) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//manchester decode
|
||||
//stricktly take 10 and 01 and convert to 0 and 1
|
||||
int Cmdmandecoderaw(const char *Cmd)
|
||||
{
|
||||
int i =0;
|
||||
int errCnt=0;
|
||||
int bitnum=0;
|
||||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
|
||||
int high=0,low=0;
|
||||
for (;i<GraphTraceLen;++i){
|
||||
if (GraphBuffer[i]>high) high=GraphBuffer[i];
|
||||
else if(GraphBuffer[i]<low) low=GraphBuffer[i];
|
||||
BitStream[i]=GraphBuffer[i];
|
||||
}
|
||||
if (high>1 || low <0 ){
|
||||
PrintAndLog("Error: please raw demod the wave first then mancheseter raw decode");
|
||||
return 0;
|
||||
}
|
||||
bitnum=i;
|
||||
errCnt=manrawdecode(BitStream,&bitnum);
|
||||
if (errCnt>=20){
|
||||
PrintAndLog("Too many errors: %d",errCnt);
|
||||
return 0;
|
||||
}
|
||||
PrintAndLog("Manchester Decoded - # errors:%d - data:",errCnt);
|
||||
printBitStream(BitStream,bitnum);
|
||||
if (errCnt==0){
|
||||
//put back in graphbuffer
|
||||
ClearGraph(0);
|
||||
for (i=0; i<bitnum;++i){
|
||||
GraphBuffer[i]=BitStream[i];
|
||||
}
|
||||
GraphTraceLen=bitnum;
|
||||
RepaintGraphWindow();
|
||||
uint64_t id = 0;
|
||||
id = Em410xDecode(BitStream,i);
|
||||
printEM410x(id);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//biphase decode
|
||||
//take 01 or 10 = 0 and 11 or 00 = 1
|
||||
//takes 1 argument "offset" default = 0 if 1 it will shift the decode by one bit
|
||||
// since it is not like manchester and doesn't have an incorrect bit pattern we
|
||||
// cannot determine if our decode is correct or if it should be shifted by one bit
|
||||
// the argument offset allows us to manually shift if the output is incorrect
|
||||
// (better would be to demod and decode at the same time so we can distinguish large
|
||||
// width waves vs small width waves to help the decode positioning) or askbiphdemod
|
||||
int CmdBiphaseDecodeRaw(const char *Cmd)
|
||||
{
|
||||
int i = 0;
|
||||
int errCnt=0;
|
||||
int bitnum=0;
|
||||
int offset=0;
|
||||
int high=0, low=0;
|
||||
sscanf(Cmd, "%i", &offset);
|
||||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
|
||||
//get graphbuffer & high and low
|
||||
for (;i<GraphTraceLen;++i){
|
||||
if(GraphBuffer[i]>high)high=GraphBuffer[i];
|
||||
else if(GraphBuffer[i]<low)low=GraphBuffer[i];
|
||||
BitStream[i]=GraphBuffer[i];
|
||||
}
|
||||
if (high>1 || low <0){
|
||||
PrintAndLog("Error: please raw demod the wave first then decode");
|
||||
return 0;
|
||||
}
|
||||
bitnum=i;
|
||||
errCnt=BiphaseRawDecode(BitStream,&bitnum, offset);
|
||||
if (errCnt>=20){
|
||||
PrintAndLog("Too many errors attempting to decode: %d",errCnt);
|
||||
return 0;
|
||||
}
|
||||
PrintAndLog("Biphase Decoded using offset: %d - # errors:%d - data:",offset,errCnt);
|
||||
printBitStream(BitStream,bitnum);
|
||||
PrintAndLog("\nif bitstream does not look right try offset=1");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//by marshmellow
|
||||
//takes 2 arguments - clock and invert both as integers
|
||||
//attempts to demodulate ask only
|
||||
//prints binary found and saves in graphbuffer for further commands
|
||||
int Cmdaskrawdemod(const char *Cmd)
|
||||
{
|
||||
uint32_t i;
|
||||
int invert=0;
|
||||
int clk=0;
|
||||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
|
||||
sscanf(Cmd, "%i %i", &clk, &invert);
|
||||
if (invert != 0 && invert != 1) {
|
||||
PrintAndLog("Invalid argument: %s", Cmd);
|
||||
return 0;
|
||||
}
|
||||
int BitLen = getFromGraphBuf(BitStream);
|
||||
int errCnt=0;
|
||||
errCnt = askrawdemod(BitStream, &BitLen,&clk,&invert);
|
||||
if (errCnt==-1){ //throw away static - allow 1 and -1 (in case of threshold command first)
|
||||
PrintAndLog("no data found");
|
||||
return 0;
|
||||
}
|
||||
if (BitLen<16) return 0;
|
||||
PrintAndLog("Using Clock: %d - invert: %d - Bits Found: %d",clk,invert,BitLen);
|
||||
//PrintAndLog("Data start pos:%d, lastBit:%d, stop pos:%d, numBits:%d",iii,lastBit,i,bitnum);
|
||||
//move BitStream back to GraphBuffer
|
||||
|
||||
ClearGraph(0);
|
||||
for (i=0; i < BitLen; ++i){
|
||||
GraphBuffer[i]=BitStream[i];
|
||||
}
|
||||
GraphTraceLen=BitLen;
|
||||
RepaintGraphWindow();
|
||||
|
||||
//output
|
||||
if (errCnt>0){
|
||||
PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt);
|
||||
}
|
||||
PrintAndLog("ASK demoded bitstream:");
|
||||
// Now output the bitstream to the scrollback by line of 16 bits
|
||||
printBitStream(BitStream,BitLen);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CmdAutoCorr(const char *Cmd)
|
||||
{
|
||||
static int CorrelBuffer[MAX_GRAPH_TRACE_LEN];
|
||||
@@ -228,10 +477,10 @@ int CmdBitstream(const char *Cmd)
|
||||
bit ^= 1;
|
||||
|
||||
AppendGraph(0, clock, bit);
|
||||
// for (j = 0; j < (int)(clock/2); j++)
|
||||
// GraphBuffer[(i * clock) + j] = bit ^ 1;
|
||||
// for (j = (int)(clock/2); j < clock; j++)
|
||||
// GraphBuffer[(i * clock) + j] = bit;
|
||||
// for (j = 0; j < (int)(clock/2); j++)
|
||||
// GraphBuffer[(i * clock) + j] = bit ^ 1;
|
||||
// for (j = (int)(clock/2); j < clock; j++)
|
||||
// GraphBuffer[(i * clock) + j] = bit;
|
||||
}
|
||||
|
||||
RepaintGraphWindow();
|
||||
@@ -257,14 +506,188 @@ int CmdDec(const char *Cmd)
|
||||
}
|
||||
|
||||
/* Print our clock rate */
|
||||
// uses data from graphbuffer
|
||||
int CmdDetectClockRate(const char *Cmd)
|
||||
{
|
||||
int clock = DetectClock(0);
|
||||
PrintAndLog("Auto-detected clock rate: %d", clock);
|
||||
GetClock("",0,0);
|
||||
//int clock = DetectASKClock(0);
|
||||
//PrintAndLog("Auto-detected clock rate: %d", clock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdFSKdemod(const char *Cmd)
|
||||
//by marshmellow
|
||||
//fsk raw demod and print binary
|
||||
//takes 4 arguments - Clock, invert, rchigh, rclow
|
||||
//defaults: clock = 50, invert=0, rchigh=10, rclow=8 (RF/10 RF/8 (fsk2a))
|
||||
int CmdFSKrawdemod(const char *Cmd)
|
||||
{
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
//set defaults
|
||||
int rfLen = 50;
|
||||
int invert=0;
|
||||
int fchigh=10;
|
||||
int fclow=8;
|
||||
//set options from parameters entered with the command
|
||||
sscanf(Cmd, "%i %i %i %i", &rfLen, &invert, &fchigh, &fclow);
|
||||
|
||||
if (strlen(Cmd)>0 && strlen(Cmd)<=2) {
|
||||
//rfLen=param_get8(Cmd, 0); //if rfLen option only is used
|
||||
if (rfLen==1){
|
||||
invert=1; //if invert option only is used
|
||||
rfLen = 50;
|
||||
} else if(rfLen==0) rfLen=50;
|
||||
}
|
||||
PrintAndLog("Args invert: %d - Clock:%d - fchigh:%d - fclow: %d",invert,rfLen,fchigh, fclow);
|
||||
uint32_t i=0;
|
||||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
|
||||
uint32_t BitLen = getFromGraphBuf(BitStream);
|
||||
int size = fskdemod(BitStream,BitLen,(uint8_t)rfLen,(uint8_t)invert,(uint8_t)fchigh,(uint8_t)fclow);
|
||||
if (size>0){
|
||||
PrintAndLog("FSK decoded bitstream:");
|
||||
ClearGraph(0);
|
||||
for (i=0;i<size;++i){
|
||||
GraphBuffer[i]=BitStream[i];
|
||||
}
|
||||
GraphTraceLen=size;
|
||||
RepaintGraphWindow();
|
||||
|
||||
// Now output the bitstream to the scrollback by line of 16 bits
|
||||
if(size > (8*32)+2) size = (8*32)+2; //only output a max of 8 blocks of 32 bits most tags will have full bit stream inside that sample size
|
||||
printBitStream(BitStream,size);
|
||||
} else{
|
||||
PrintAndLog("no FSK data found");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//by marshmellow (based on existing demod + holiman's refactor)
|
||||
//HID Prox demod - FSK RF/50 with preamble of 00011101 (then manchester encoded)
|
||||
//print full HID Prox ID and some bit format details if found
|
||||
int CmdFSKdemodHID(const char *Cmd)
|
||||
{
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
uint32_t hi2=0, hi=0, lo=0;
|
||||
|
||||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
|
||||
uint32_t BitLen = getFromGraphBuf(BitStream);
|
||||
//get binary from fsk wave
|
||||
size_t size = HIDdemodFSK(BitStream,BitLen,&hi2,&hi,&lo);
|
||||
if (size<0){
|
||||
PrintAndLog("Error demoding fsk");
|
||||
return 0;
|
||||
}
|
||||
if (hi2==0 && hi==0 && lo==0) return 0;
|
||||
if (hi2 != 0){ //extra large HID tags
|
||||
PrintAndLog("TAG ID: %x%08x%08x (%d)",
|
||||
(unsigned int) hi2, (unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF);
|
||||
setGraphBuf(BitStream,BitLen);
|
||||
return 1;
|
||||
}
|
||||
else { //standard HID tags <38 bits
|
||||
//Dbprintf("TAG ID: %x%08x (%d)",(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF); //old print cmd
|
||||
uint8_t fmtLen = 0;
|
||||
uint32_t fc = 0;
|
||||
uint32_t cardnum = 0;
|
||||
if (((hi>>5)&1)==1){//if bit 38 is set then < 37 bit format is used
|
||||
uint32_t lo2=0;
|
||||
lo2=(((hi & 15) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit
|
||||
uint8_t idx3 = 1;
|
||||
while(lo2>1){ //find last bit set to 1 (format len bit)
|
||||
lo2=lo2>>1;
|
||||
idx3++;
|
||||
}
|
||||
fmtLen =idx3+19;
|
||||
fc =0;
|
||||
cardnum=0;
|
||||
if(fmtLen==26){
|
||||
cardnum = (lo>>1)&0xFFFF;
|
||||
fc = (lo>>17)&0xFF;
|
||||
}
|
||||
if(fmtLen==37){
|
||||
cardnum = (lo>>1)&0x7FFFF;
|
||||
fc = ((hi&0xF)<<12)|(lo>>20);
|
||||
}
|
||||
if(fmtLen==34){
|
||||
cardnum = (lo>>1)&0xFFFF;
|
||||
fc= ((hi&1)<<15)|(lo>>17);
|
||||
}
|
||||
if(fmtLen==35){
|
||||
cardnum = (lo>>1)&0xFFFFF;
|
||||
fc = ((hi&1)<<11)|(lo>>21);
|
||||
}
|
||||
}
|
||||
else { //if bit 38 is not set then 37 bit format is used
|
||||
fmtLen= 37;
|
||||
fc =0;
|
||||
cardnum=0;
|
||||
if(fmtLen==37){
|
||||
cardnum = (lo>>1)&0x7FFFF;
|
||||
fc = ((hi&0xF)<<12)|(lo>>20);
|
||||
}
|
||||
}
|
||||
PrintAndLog("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d",
|
||||
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
(unsigned int) fmtLen, (unsigned int) fc, (unsigned int) cardnum);
|
||||
setGraphBuf(BitStream,BitLen);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//IO-Prox demod - FSK RF/64 with preamble of 000000001
|
||||
//print ioprox ID and some format details
|
||||
int CmdFSKdemodIO(const char *Cmd)
|
||||
{
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
//set defaults
|
||||
int idx=0;
|
||||
//something in graphbuffer
|
||||
if (GraphTraceLen < 65) return 0;
|
||||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
|
||||
uint32_t BitLen = getFromGraphBuf(BitStream);
|
||||
//get binary from fsk wave
|
||||
// PrintAndLog("DEBUG: got buff");
|
||||
idx = IOdemodFSK(BitStream,BitLen);
|
||||
if (idx<0){
|
||||
//PrintAndLog("Error demoding fsk");
|
||||
return 0;
|
||||
}
|
||||
// PrintAndLog("DEBUG: Got IOdemodFSK");
|
||||
if (idx==0){
|
||||
//PrintAndLog("IO Prox Data not found - FSK Data:");
|
||||
//if (BitLen > 92) printBitStream(BitStream,92);
|
||||
return 0;
|
||||
}
|
||||
//Index map
|
||||
//0 10 20 30 40 50 60
|
||||
//| | | | | | |
|
||||
//01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
|
||||
//-----------------------------------------------------------------------------
|
||||
//00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
|
||||
//
|
||||
//XSF(version)facility:codeone+codetwo (raw)
|
||||
//Handle the data
|
||||
if (idx+64>BitLen) return 0;
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d",BitStream[idx], BitStream[idx+1], BitStream[idx+2], BitStream[idx+3], BitStream[idx+4], BitStream[idx+5], BitStream[idx+6], BitStream[idx+7], BitStream[idx+8]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d",BitStream[idx+9], BitStream[idx+10], BitStream[idx+11],BitStream[idx+12],BitStream[idx+13],BitStream[idx+14],BitStream[idx+15],BitStream[idx+16],BitStream[idx+17]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d facility",BitStream[idx+18], BitStream[idx+19], BitStream[idx+20],BitStream[idx+21],BitStream[idx+22],BitStream[idx+23],BitStream[idx+24],BitStream[idx+25],BitStream[idx+26]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d version",BitStream[idx+27], BitStream[idx+28], BitStream[idx+29],BitStream[idx+30],BitStream[idx+31],BitStream[idx+32],BitStream[idx+33],BitStream[idx+34],BitStream[idx+35]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d code1",BitStream[idx+36], BitStream[idx+37], BitStream[idx+38],BitStream[idx+39],BitStream[idx+40],BitStream[idx+41],BitStream[idx+42],BitStream[idx+43],BitStream[idx+44]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d code2",BitStream[idx+45], BitStream[idx+46], BitStream[idx+47],BitStream[idx+48],BitStream[idx+49],BitStream[idx+50],BitStream[idx+51],BitStream[idx+52],BitStream[idx+53]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d%d checksum",BitStream[idx+54],BitStream[idx+55],BitStream[idx+56],BitStream[idx+57],BitStream[idx+58],BitStream[idx+59],BitStream[idx+60],BitStream[idx+61],BitStream[idx+62],BitStream[idx+63]);
|
||||
|
||||
uint32_t code = bytebits_to_byte(BitStream+idx,32);
|
||||
uint32_t code2 = bytebits_to_byte(BitStream+idx+32,32);
|
||||
uint8_t version = bytebits_to_byte(BitStream+idx+27,8); //14,4
|
||||
uint8_t facilitycode = bytebits_to_byte(BitStream+idx+18,8) ;
|
||||
uint16_t number = (bytebits_to_byte(BitStream+idx+36,8)<<8)|(bytebits_to_byte(BitStream+idx+45,8)); //36,9
|
||||
|
||||
PrintAndLog("XSF(%02d)%02x:%05d (%08x%08x)",version,facilitycode,number,code,code2);
|
||||
setGraphBuf(BitStream,BitLen);
|
||||
return 1;
|
||||
}
|
||||
int CmdFSKdemod(const char *Cmd) //old CmdFSKdemod needs updating
|
||||
{
|
||||
static const int LowTone[] = {
|
||||
1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
|
||||
@@ -284,12 +707,12 @@ int CmdFSKdemod(const char *Cmd)
|
||||
|
||||
int lowLen = sizeof (LowTone) / sizeof (int);
|
||||
int highLen = sizeof (HighTone) / sizeof (int);
|
||||
int convLen = (highLen > lowLen) ? highLen : lowLen;
|
||||
int convLen = (highLen > lowLen) ? highLen : lowLen; //if highlen > lowLen then highlen else lowlen
|
||||
uint32_t hi = 0, lo = 0;
|
||||
|
||||
int i, j;
|
||||
int minMark = 0, maxMark = 0;
|
||||
|
||||
|
||||
for (i = 0; i < GraphTraceLen - convLen; ++i) {
|
||||
int lowSum = 0, highSum = 0;
|
||||
|
||||
@@ -321,7 +744,7 @@ int CmdFSKdemod(const char *Cmd)
|
||||
GraphTraceLen -= (convLen + 16);
|
||||
RepaintGraphWindow();
|
||||
|
||||
// Find bit-sync (3 lo followed by 3 high)
|
||||
// Find bit-sync (3 lo followed by 3 high) (HID ONLY)
|
||||
int max = 0, maxPos = 0;
|
||||
for (i = 0; i < 6000; ++i) {
|
||||
int dec = 0;
|
||||
@@ -463,7 +886,7 @@ int CmdSamples(const char *Cmd)
|
||||
uint8_t got[40000];
|
||||
|
||||
n = strtol(Cmd, NULL, 0);
|
||||
if (n == 0) n = 512;
|
||||
if (n == 0) n = 6000;
|
||||
if (n > sizeof(got)) n = sizeof(got);
|
||||
|
||||
PrintAndLog("Reading %d samples\n", n);
|
||||
@@ -481,56 +904,24 @@ int CmdSamples(const char *Cmd)
|
||||
|
||||
int CmdTuneSamples(const char *Cmd)
|
||||
{
|
||||
int timeout = 0;
|
||||
printf("\nMeasuring antenna characteristics, please wait...");
|
||||
int cnt = 0;
|
||||
int n = 255;
|
||||
uint8_t got[255];
|
||||
|
||||
UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING};
|
||||
SendCommand(&c);
|
||||
|
||||
UsbCommand resp;
|
||||
while(!WaitForResponseTimeout(CMD_MEASURED_ANTENNA_TUNING,&resp,1000)) {
|
||||
timeout++;
|
||||
printf(".");
|
||||
if (timeout > 7) {
|
||||
PrintAndLog("\nNo response from Proxmark. Aborting...");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int peakv, peakf;
|
||||
int vLf125, vLf134, vHf;
|
||||
vLf125 = resp.arg[0] & 0xffff;
|
||||
vLf134 = resp.arg[0] >> 16;
|
||||
vHf = resp.arg[1] & 0xffff;;
|
||||
peakf = resp.arg[2] & 0xffff;
|
||||
peakv = resp.arg[2] >> 16;
|
||||
PrintAndLog("");
|
||||
PrintAndLog("# LF antenna: %5.2f V @ 125.00 kHz", vLf125/1000.0);
|
||||
PrintAndLog("# LF antenna: %5.2f V @ 134.00 kHz", vLf134/1000.0);
|
||||
PrintAndLog("# LF optimal: %5.2f V @%9.2f kHz", peakv/1000.0, 12000.0/(peakf+1));
|
||||
PrintAndLog("# HF antenna: %5.2f V @ 13.56 MHz", vHf/1000.0);
|
||||
if (peakv<2000)
|
||||
PrintAndLog("# Your LF antenna is unusable.");
|
||||
else if (peakv<10000)
|
||||
PrintAndLog("# Your LF antenna is marginal.");
|
||||
if (vHf<2000)
|
||||
PrintAndLog("# Your HF antenna is unusable.");
|
||||
else if (vHf<5000)
|
||||
PrintAndLog("# Your HF antenna is marginal.");
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
GraphBuffer[i] = resp.d.asBytes[i] - 128;
|
||||
}
|
||||
PrintAndLog("Reading %d samples\n", n);
|
||||
GetFromBigBuf(got,n,7256); // armsrc/apps.h: #define FREE_BUFFER_OFFSET 7256
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
for (int j = 0; j < n; j++) {
|
||||
GraphBuffer[cnt++] = ((int)got[j]) - 128;
|
||||
}
|
||||
|
||||
PrintAndLog("Done! Divisor 89 is 134khz, 95 is 125khz.\n");
|
||||
PrintAndLog("\n");
|
||||
GraphTraceLen = 256;
|
||||
ShowGraphWindow();
|
||||
|
||||
return 0;
|
||||
PrintAndLog("Done! Divisor 89 is 134khz, 95 is 125khz.\n");
|
||||
PrintAndLog("\n");
|
||||
GraphTraceLen = n;
|
||||
RepaintGraphWindow();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int CmdLoad(const char *Cmd)
|
||||
{
|
||||
FILE *f = fopen(Cmd, "r");
|
||||
@@ -562,6 +953,15 @@ int CmdLtrim(const char *Cmd)
|
||||
RepaintGraphWindow();
|
||||
return 0;
|
||||
}
|
||||
int CmdRtrim(const char *Cmd)
|
||||
{
|
||||
int ds = atoi(Cmd);
|
||||
|
||||
GraphTraceLen = ds;
|
||||
|
||||
RepaintGraphWindow();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Manchester demodulate a bitstream. The bitstream needs to be already in
|
||||
@@ -689,30 +1089,30 @@ int CmdManchesterDemod(const char *Cmd)
|
||||
{
|
||||
if (GraphBuffer[i-1] != GraphBuffer[i])
|
||||
{
|
||||
lc = i-lastval;
|
||||
lastval = i;
|
||||
lc = i-lastval;
|
||||
lastval = i;
|
||||
|
||||
// Error check: if bitidx becomes too large, we do not
|
||||
// have a Manchester encoded bitstream or the clock is really
|
||||
// wrong!
|
||||
if (bitidx > (GraphTraceLen*2/clock+8) ) {
|
||||
PrintAndLog("Error: the clock you gave is probably wrong, aborting.");
|
||||
return 0;
|
||||
}
|
||||
// Then switch depending on lc length:
|
||||
// Tolerance is 1/4 of clock rate (arbitrary)
|
||||
if (abs(lc-clock/2) < tolerance) {
|
||||
// Short pulse : either "1" or "0"
|
||||
BitStream[bitidx++]=GraphBuffer[i-1];
|
||||
} else if (abs(lc-clock) < tolerance) {
|
||||
// Long pulse: either "11" or "00"
|
||||
BitStream[bitidx++]=GraphBuffer[i-1];
|
||||
BitStream[bitidx++]=GraphBuffer[i-1];
|
||||
} else {
|
||||
// Error check: if bitidx becomes too large, we do not
|
||||
// have a Manchester encoded bitstream or the clock is really
|
||||
// wrong!
|
||||
if (bitidx > (GraphTraceLen*2/clock+8) ) {
|
||||
PrintAndLog("Error: the clock you gave is probably wrong, aborting.");
|
||||
return 0;
|
||||
}
|
||||
// Then switch depending on lc length:
|
||||
// Tolerance is 1/4 of clock rate (arbitrary)
|
||||
if (abs(lc-clock/2) < tolerance) {
|
||||
// Short pulse : either "1" or "0"
|
||||
BitStream[bitidx++]=GraphBuffer[i-1];
|
||||
} else if (abs(lc-clock) < tolerance) {
|
||||
// Long pulse: either "11" or "00"
|
||||
BitStream[bitidx++]=GraphBuffer[i-1];
|
||||
BitStream[bitidx++]=GraphBuffer[i-1];
|
||||
} else {
|
||||
// Error
|
||||
warnings++;
|
||||
PrintAndLog("Warning: Manchester decode error for pulse width detection.");
|
||||
PrintAndLog("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
|
||||
PrintAndLog("Warning: Manchester decode error for pulse width detection.");
|
||||
PrintAndLog("(too many of those messages mean either the stream is not Manchester encoded, or clock is wrong)");
|
||||
|
||||
if (warnings > 10)
|
||||
{
|
||||
@@ -729,15 +1129,15 @@ int CmdManchesterDemod(const char *Cmd)
|
||||
for (i = 0; i < bitidx; i += 2) {
|
||||
if ((BitStream[i] == 0) && (BitStream[i+1] == 1)) {
|
||||
BitStream[bit2idx++] = 1 ^ invert;
|
||||
} else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
|
||||
BitStream[bit2idx++] = 0 ^ invert;
|
||||
} else {
|
||||
// We cannot end up in this state, this means we are unsynchronized,
|
||||
// move up 1 bit:
|
||||
i++;
|
||||
} else if ((BitStream[i] == 1) && (BitStream[i+1] == 0)) {
|
||||
BitStream[bit2idx++] = 0 ^ invert;
|
||||
} else {
|
||||
// We cannot end up in this state, this means we are unsynchronized,
|
||||
// move up 1 bit:
|
||||
i++;
|
||||
warnings++;
|
||||
PrintAndLog("Unsynchronized, resync...");
|
||||
PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)");
|
||||
PrintAndLog("Unsynchronized, resync...");
|
||||
PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)");
|
||||
|
||||
if (warnings > 10)
|
||||
{
|
||||
@@ -940,20 +1340,28 @@ static command_t CommandTable[] =
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"amp", CmdAmp, 1, "Amplify peaks"},
|
||||
{"askdemod", Cmdaskdemod, 1, "<0 or 1> -- Attempt to demodulate simple ASK tags"},
|
||||
{"askmandemod", Cmdaskmandemod, 1, "[clock] [invert<0 or 1>] -- Attempt to demodulate ASK/Manchester tags and output binary (args optional[clock will try Auto-detect])"},
|
||||
{"askrawdemod", Cmdaskrawdemod, 1, "[clock] [invert<0 or 1>] -- Attempt to demodulate ASK tags and output binary (args optional[clock will try Auto-detect])"},
|
||||
{"autocorr", CmdAutoCorr, 1, "<window length> -- Autocorrelation over window"},
|
||||
{"biphaserawdecode",CmdBiphaseDecodeRaw,1,"[offset] Biphase decode binary stream already in graph buffer (offset = bit to start decode from)"},
|
||||
{"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"},
|
||||
{"bitstream", CmdBitstream, 1, "[clock rate] -- Convert waveform into a bitstream"},
|
||||
{"buffclear", CmdBuffClear, 1, "Clear sample buffer and graph window"},
|
||||
{"dec", CmdDec, 1, "Decimate samples"},
|
||||
{"detectclock", CmdDetectClockRate, 1, "Detect clock rate"},
|
||||
{"detectaskclock",CmdDetectClockRate, 1, "Detect ASK clock rate"},
|
||||
{"fskdemod", CmdFSKdemod, 1, "Demodulate graph window as a HID FSK"},
|
||||
{"fskhiddemod", CmdFSKdemodHID, 1, "Demodulate graph window as a HID FSK using raw"},
|
||||
{"fskiodemod", CmdFSKdemodIO, 1, "Demodulate graph window as an IO Prox FSK using raw"},
|
||||
{"fskrawdemod", CmdFSKrawdemod, 1, "[clock rate] [invert] [rchigh] [rclow] Demodulate graph window from FSK to binary (clock = 50)(invert = 1 or 0)(rchigh = 10)(rclow=8)"},
|
||||
{"grid", CmdGrid, 1, "<x> <y> -- overlay grid on graph window, use zero value to turn off either"},
|
||||
{"hexsamples", CmdHexsamples, 0, "<bytes> [<offset>] -- Dump big buffer as hex bytes"},
|
||||
{"hide", CmdHide, 1, "Hide graph window"},
|
||||
{"hpf", CmdHpf, 1, "Remove DC offset from trace"},
|
||||
{"load", CmdLoad, 1, "<filename> -- Load trace (to graph window"},
|
||||
{"ltrim", CmdLtrim, 1, "<samples> -- Trim samples from left of trace"},
|
||||
{"rtrim", CmdRtrim, 1, "<location to end trace> -- Trim samples from right of trace"},
|
||||
{"mandemod", CmdManchesterDemod, 1, "[i] [clock rate] -- Manchester demodulate binary stream (option 'i' to invert output)"},
|
||||
{"manrawdecode", Cmdmandecoderaw, 1, "Manchester decode binary stream already in graph buffer"},
|
||||
{"manmod", CmdManchesterMod, 1, "[clock rate] -- Manchester modulate a binary stream"},
|
||||
{"norm", CmdNorm, 1, "Normalize max/min to +/-500"},
|
||||
{"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"},
|
||||
|
||||
@@ -17,19 +17,27 @@ int CmdData(const char *Cmd);
|
||||
|
||||
int CmdAmp(const char *Cmd);
|
||||
int Cmdaskdemod(const char *Cmd);
|
||||
int Cmdaskrawdemod(const char *Cmd);
|
||||
int Cmdaskmandemod(const char *Cmd);
|
||||
int CmdAutoCorr(const char *Cmd);
|
||||
int CmdBiphaseDecodeRaw(const char *Cmd);
|
||||
int CmdBitsamples(const char *Cmd);
|
||||
int CmdBitstream(const char *Cmd);
|
||||
int CmdBuffClear(const char *Cmd);
|
||||
int CmdDec(const char *Cmd);
|
||||
int CmdDetectClockRate(const char *Cmd);
|
||||
int CmdFSKdemod(const char *Cmd);
|
||||
int CmdFSKdemodHID(const char *Cmd);
|
||||
int CmdFSKdemodIO(const char *Cmd);
|
||||
int CmdFSKrawdemod(const char *Cmd);
|
||||
int CmdGrid(const char *Cmd);
|
||||
int CmdHexsamples(const char *Cmd);
|
||||
int CmdHide(const char *Cmd);
|
||||
int CmdHpf(const char *Cmd);
|
||||
int CmdLoad(const char *Cmd);
|
||||
int CmdLtrim(const char *Cmd);
|
||||
int CmdRtrim(const char *Cmd);
|
||||
int Cmdmandecoderaw(const char *Cmd);
|
||||
int CmdManchesterDemod(const char *Cmd);
|
||||
int CmdManchesterMod(const char *Cmd);
|
||||
int CmdNorm(const char *Cmd);
|
||||
|
||||
+32
-5
@@ -142,7 +142,7 @@ int CmdIndalaDemod(const char *Cmd)
|
||||
uint8_t rawbits[4096];
|
||||
int rawbit = 0;
|
||||
int worst = 0, worstPos = 0;
|
||||
PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
|
||||
// PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
|
||||
for (i = 0; i < GraphTraceLen-1; i += 2) {
|
||||
count += 1;
|
||||
if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
|
||||
@@ -171,9 +171,10 @@ int CmdIndalaDemod(const char *Cmd)
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
PrintAndLog("Recovered %d raw bits", rawbit);
|
||||
PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
|
||||
|
||||
if (rawbit>0){
|
||||
PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32);
|
||||
PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
|
||||
} else return 0;
|
||||
// Finding the start of a UID
|
||||
int uidlen, long_wait;
|
||||
if (strcmp(Cmd, "224") == 0) {
|
||||
@@ -303,7 +304,7 @@ int CmdIndalaDemod(const char *Cmd)
|
||||
}
|
||||
|
||||
RepaintGraphWindow();
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int CmdIndalaClone(const char *Cmd)
|
||||
@@ -548,6 +549,31 @@ int CmdVchDemod(const char *Cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
int CmdLFfind(const char *Cmd)
|
||||
{
|
||||
int ans=0;
|
||||
if (!offline){
|
||||
ans=CmdLFRead("");
|
||||
ans=CmdSamples("20000");
|
||||
}
|
||||
if (GraphTraceLen<1000) return 0;
|
||||
PrintAndLog("Checking for known tags:");
|
||||
ans=Cmdaskmandemod("");
|
||||
if (ans>0) return 1;
|
||||
ans=CmdFSKdemodHID("");
|
||||
if (ans>0) return 1;
|
||||
ans=CmdFSKdemodIO("");
|
||||
if (ans>0) return 1;
|
||||
//add psk and indala
|
||||
ans=CmdIndalaDemod("");
|
||||
if (ans>0) return 1;
|
||||
ans=CmdIndalaDemod("224");
|
||||
if (ans>0) return 1;
|
||||
PrintAndLog("No Known Tags Found!\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
@@ -559,6 +585,7 @@ static command_t CommandTable[] =
|
||||
{"indalademod", CmdIndalaDemod, 1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
|
||||
{"indalaclone", CmdIndalaClone, 0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
|
||||
{"read", CmdLFRead, 0, "['h' or <divisor>] -- Read 125/134 kHz LF ID-only tag (option 'h' for 134, alternatively: f=12MHz/(divisor+1))"},
|
||||
{"search", CmdLFfind, 1, "Read and Search for valid known tag (in offline mode it you can load first then search)"},
|
||||
{"sim", CmdLFSim, 0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
|
||||
{"simbidir", CmdLFSimBidir, 0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
|
||||
{"simman", CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
|
||||
|
||||
@@ -23,5 +23,6 @@ int CmdLFSimBidir(const char *Cmd);
|
||||
int CmdLFSimManchester(const char *Cmd);
|
||||
int CmdLFSnoop(const char *Cmd);
|
||||
int CmdVchDemod(const char *Cmd);
|
||||
int CmdLFfind(const char *Cmd);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,20 @@
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
||||
|
||||
int CmdEMdemodASK(const char *Cmd)
|
||||
{
|
||||
int findone=0;
|
||||
UsbCommand c={CMD_EM410X_DEMOD};
|
||||
if(Cmd[0]=='1') findone=1;
|
||||
c.arg[0]=findone;
|
||||
SendCommand(&c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Read the ID of an EM410x tag.
|
||||
* Format:
|
||||
* 1111 1111 1 <-- standard non-repeatable header
|
||||
@@ -581,6 +595,7 @@ int CmdWriteWordPWD(const char *Cmd)
|
||||
static command_t CommandTable[] =
|
||||
{
|
||||
{"help", CmdHelp, 1, "This help"},
|
||||
{"em410xdemod", CmdEMdemodASK, 0, "[clock rate] -- Extract ID from EM410x tag"},
|
||||
{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
|
||||
{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
|
||||
{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
#define CMDLFEM4X_H__
|
||||
|
||||
int CmdLFEM4X(const char *Cmd);
|
||||
|
||||
int CmdEMdemodASK(const char *Cmd);
|
||||
int CmdEM410xRead(const char *Cmd);
|
||||
int CmdEM410xSim(const char *Cmd);
|
||||
int CmdEM410xWatch(const char *Cmd);
|
||||
|
||||
+102
-8
@@ -12,6 +12,7 @@
|
||||
#include <string.h>
|
||||
#include "ui.h"
|
||||
#include "graph.h"
|
||||
#include "lfdemod.h"
|
||||
|
||||
int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
||||
int GraphTraceLen;
|
||||
@@ -46,24 +47,27 @@ int ClearGraph(int redraw)
|
||||
/*
|
||||
* Detect clock rate
|
||||
*/
|
||||
int DetectClock(int peak)
|
||||
//decommissioned - has difficulty detecting rf/32
|
||||
/*
|
||||
int DetectClockOld(int peak)
|
||||
{
|
||||
int i;
|
||||
int clock = 0xFFFF;
|
||||
int lastpeak = 0;
|
||||
|
||||
/* Detect peak if we don't have one */
|
||||
// Detect peak if we don't have one
|
||||
if (!peak)
|
||||
for (i = 0; i < GraphTraceLen; ++i)
|
||||
if (GraphBuffer[i] > peak)
|
||||
peak = GraphBuffer[i];
|
||||
|
||||
// peak=(int)(peak*.75);
|
||||
for (i = 1; i < GraphTraceLen; ++i)
|
||||
{
|
||||
/* If this is the beginning of a peak */
|
||||
if (GraphBuffer[i - 1] != GraphBuffer[i] && GraphBuffer[i] == peak)
|
||||
// If this is the beginning of a peak
|
||||
if (GraphBuffer[i - 1] != GraphBuffer[i] && GraphBuffer[i] >= peak)
|
||||
{
|
||||
/* Find lowest difference between peaks */
|
||||
// Find lowest difference between peaks
|
||||
if (lastpeak && i - lastpeak < clock)
|
||||
clock = i - lastpeak;
|
||||
lastpeak = i;
|
||||
@@ -72,12 +76,97 @@ int DetectClock(int peak)
|
||||
|
||||
return clock;
|
||||
}
|
||||
*/
|
||||
/*
|
||||
NOW IN LFDEMOD.C
|
||||
|
||||
// by marshmellow
|
||||
// not perfect especially with lower clocks or VERY good antennas (heavy wave clipping)
|
||||
// maybe somehow adjust peak trimming value based on samples to fix?
|
||||
int DetectASKClock(int peak)
|
||||
{
|
||||
int i=0;
|
||||
int low=0;
|
||||
int clk[]={16,32,40,50,64,100,128,256};
|
||||
int loopCnt = 256;
|
||||
if (GraphTraceLen<loopCnt) loopCnt = GraphTraceLen;
|
||||
if (!peak){
|
||||
for (i=0;i<loopCnt;++i){
|
||||
if(GraphBuffer[i]>peak){
|
||||
peak = GraphBuffer[i];
|
||||
}
|
||||
if(GraphBuffer[i]<low){
|
||||
low = GraphBuffer[i];
|
||||
}
|
||||
}
|
||||
peak=(int)(peak*.75);
|
||||
low= (int)(low*.75);
|
||||
}
|
||||
int ii;
|
||||
int clkCnt;
|
||||
int tol = 0;
|
||||
int bestErr=1000;
|
||||
int errCnt[]={0,0,0,0,0,0,0,0};
|
||||
for(clkCnt=0; clkCnt<6;++clkCnt){
|
||||
if (clk[clkCnt]==32){
|
||||
tol=1;
|
||||
}else{
|
||||
tol=0;
|
||||
}
|
||||
bestErr=1000;
|
||||
for (ii=0; ii<loopCnt; ++ii){
|
||||
if ((GraphBuffer[ii]>=peak) || (GraphBuffer[ii]<=low)){
|
||||
errCnt[clkCnt]=0;
|
||||
for (i=0; i<((int)(GraphTraceLen/clk[clkCnt])-1); ++i){
|
||||
if (GraphBuffer[ii+(i*clk[clkCnt])]>=peak || GraphBuffer[ii+(i*clk[clkCnt])]<=low){
|
||||
}else if(GraphBuffer[ii+(i*clk[clkCnt])-tol]>=peak || GraphBuffer[ii+(i*clk[clkCnt])-tol]<=low){
|
||||
}else if(GraphBuffer[ii+(i*clk[clkCnt])+tol]>=peak || GraphBuffer[ii+(i*clk[clkCnt])+tol]<=low){
|
||||
}else{ //error no peak detected
|
||||
errCnt[clkCnt]++;
|
||||
}
|
||||
}
|
||||
if(errCnt[clkCnt]==0) return clk[clkCnt];
|
||||
if(errCnt[clkCnt]<bestErr) bestErr=errCnt[clkCnt];
|
||||
}
|
||||
}
|
||||
}
|
||||
int iii=0;
|
||||
int best=0;
|
||||
for (iii=0; iii<6;++iii){
|
||||
if (errCnt[iii]<errCnt[best]){
|
||||
best = iii;
|
||||
}
|
||||
}
|
||||
// PrintAndLog("DEBUG: clkCnt: %d, ii: %d, i: %d peak: %d, low: %d, errcnt: %d, errCnt64: %d",clkCnt,ii,i,peak,low,errCnt[best],errCnt[4]);
|
||||
return clk[best];
|
||||
}
|
||||
*/
|
||||
void setGraphBuf(uint8_t *buff,int size)
|
||||
{
|
||||
int i=0;
|
||||
ClearGraph(0);
|
||||
for (; i < size; ++i){
|
||||
GraphBuffer[i]=buff[i];
|
||||
}
|
||||
GraphTraceLen=size;
|
||||
RepaintGraphWindow();
|
||||
return;
|
||||
}
|
||||
int getFromGraphBuf(uint8_t *buff)
|
||||
{
|
||||
uint32_t i;
|
||||
for (i=0;i<GraphTraceLen;++i){
|
||||
if (GraphBuffer[i]>127) GraphBuffer[i]=127; //trim
|
||||
if (GraphBuffer[i]<-127) GraphBuffer[i]=-127; //trim
|
||||
buff[i]=(uint8_t)(GraphBuffer[i]+128);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
/* Get or auto-detect clock rate */
|
||||
int GetClock(const char *str, int peak, int verbose)
|
||||
{
|
||||
int clock;
|
||||
|
||||
// int clock2;
|
||||
sscanf(str, "%i", &clock);
|
||||
if (!strcmp(str, ""))
|
||||
clock = 0;
|
||||
@@ -85,10 +174,15 @@ int GetClock(const char *str, int peak, int verbose)
|
||||
/* Auto-detect clock */
|
||||
if (!clock)
|
||||
{
|
||||
clock = DetectClock(peak);
|
||||
uint8_t grph[MAX_GRAPH_TRACE_LEN]={0};
|
||||
int size = getFromGraphBuf(grph);
|
||||
clock = DetectASKClock(grph,size,0);
|
||||
//clock2 = DetectClock2(peak);
|
||||
/* Only print this message if we're not looping something */
|
||||
if (!verbose)
|
||||
if (!verbose){
|
||||
PrintAndLog("Auto-detected clock rate: %d", clock);
|
||||
//PrintAndLog("clock2: %d",clock2);
|
||||
}
|
||||
}
|
||||
|
||||
return clock;
|
||||
|
||||
+4
-1
@@ -10,11 +10,14 @@
|
||||
|
||||
#ifndef GRAPH_H__
|
||||
#define GRAPH_H__
|
||||
#include <stdint.h>
|
||||
|
||||
void AppendGraph(int redraw, int clock, int bit);
|
||||
int ClearGraph(int redraw);
|
||||
int DetectClock(int peak);
|
||||
//int DetectClock(int peak);
|
||||
int getFromGraphBuf(uint8_t *buff);
|
||||
int GetClock(const char *str, int peak, int verbose);
|
||||
void setGraphBuf(uint8_t *buff,int size);
|
||||
|
||||
#define MAX_GRAPH_TRACE_LEN (1024*128)
|
||||
extern int GraphBuffer[MAX_GRAPH_TRACE_LEN];
|
||||
|
||||
@@ -47,6 +47,9 @@ local _commands = {
|
||||
CMD_PCF7931_READ = 0x0217,
|
||||
CMD_EM4X_READ_WORD = 0x0218,
|
||||
CMD_EM4X_WRITE_WORD = 0x0219,
|
||||
CMD_IO_DEMOD_FSK = 0x021A,
|
||||
CMD_IO_CLONE_TAG = 0x021B,
|
||||
CMD_EM410X_DEMOD = 0x021C,
|
||||
--/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||
|
||||
--// For the 13.56 MHz tags
|
||||
|
||||
@@ -0,0 +1,701 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2014
|
||||
//
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Low frequency commands
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "lfdemod.h"
|
||||
|
||||
//by marshmellow
|
||||
//takes 1s and 0s and searches for EM410x format - output EM ID
|
||||
uint64_t Em410xDecode(uint8_t *BitStream,uint32_t BitLen)
|
||||
{
|
||||
//no arguments needed - built this way in case we want this to be a direct call from "data " cmds in the future
|
||||
// otherwise could be a void with no arguments
|
||||
//set defaults
|
||||
int high=0, low=128;
|
||||
uint64_t lo=0; //hi=0,
|
||||
|
||||
uint32_t i = 0;
|
||||
uint32_t initLoopMax = 65;
|
||||
if (initLoopMax>BitLen) initLoopMax=BitLen;
|
||||
|
||||
for (;i < initLoopMax; ++i) //65 samples should be plenty to find high and low values
|
||||
{
|
||||
if (BitStream[i] > high)
|
||||
high = BitStream[i];
|
||||
else if (BitStream[i] < low)
|
||||
low = BitStream[i];
|
||||
}
|
||||
if (((high !=1)||(low !=0))){ //allow only 1s and 0s
|
||||
// PrintAndLog("no data found");
|
||||
return 0;
|
||||
}
|
||||
uint8_t parityTest=0;
|
||||
// 111111111 bit pattern represent start of frame
|
||||
uint8_t frame_marker_mask[] = {1,1,1,1,1,1,1,1,1};
|
||||
uint32_t idx = 0;
|
||||
uint32_t ii=0;
|
||||
uint8_t resetCnt = 0;
|
||||
while( (idx + 64) < BitLen) {
|
||||
restart:
|
||||
// search for a start of frame marker
|
||||
if ( memcmp(BitStream+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0)
|
||||
{ // frame marker found
|
||||
idx+=9;//sizeof(frame_marker_mask);
|
||||
for (i=0; i<10;i++){
|
||||
for(ii=0; ii<5; ++ii){
|
||||
parityTest += BitStream[(i*5)+ii+idx];
|
||||
}
|
||||
if (parityTest== ((parityTest>>1)<<1)){
|
||||
parityTest=0;
|
||||
for (ii=0; ii<4;++ii){
|
||||
//hi = (hi<<1)|(lo>>31);
|
||||
lo=(lo<<1LL)|(BitStream[(i*5)+ii+idx]);
|
||||
}
|
||||
//PrintAndLog("DEBUG: EM parity passed parity val: %d, i:%d, ii:%d,idx:%d, Buffer: %d%d%d%d%d,lo: %d",parityTest,i,ii,idx,BitStream[idx+ii+(i*5)-5],BitStream[idx+ii+(i*5)-4],BitStream[idx+ii+(i*5)-3],BitStream[idx+ii+(i*5)-2],BitStream[idx+ii+(i*5)-1],lo);
|
||||
}else {//parity failed
|
||||
//PrintAndLog("DEBUG: EM parity failed parity val: %d, i:%d, ii:%d,idx:%d, Buffer: %d%d%d%d%d",parityTest,i,ii,idx,BitStream[idx+ii+(i*5)-5],BitStream[idx+ii+(i*5)-4],BitStream[idx+ii+(i*5)-3],BitStream[idx+ii+(i*5)-2],BitStream[idx+ii+(i*5)-1]);
|
||||
parityTest=0;
|
||||
idx-=8;
|
||||
if (resetCnt>5)return 0;
|
||||
resetCnt++;
|
||||
goto restart;//continue;
|
||||
}
|
||||
}
|
||||
//skip last 5 bit parity test for simplicity.
|
||||
return lo;
|
||||
}else{
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//takes 2 arguments - clock and invert both as integers
|
||||
//attempts to demodulate ask while decoding manchester
|
||||
//prints binary found and saves in graphbuffer for further commands
|
||||
int askmandemod(uint8_t * BinStream,uint32_t *BitLen,int *clk, int *invert)
|
||||
{
|
||||
int i;
|
||||
int high = 0, low = 128;
|
||||
*clk=DetectASKClock(BinStream,(size_t)*BitLen,*clk); //clock default
|
||||
|
||||
if (*clk<8) *clk =64;
|
||||
if (*clk<32) *clk=32;
|
||||
if (*invert != 0 && *invert != 1) *invert=0;
|
||||
uint32_t initLoopMax = 200;
|
||||
if (initLoopMax>*BitLen) initLoopMax=*BitLen;
|
||||
// Detect high and lows
|
||||
for (i = 0; i < initLoopMax; ++i) //200 samples should be enough to find high and low values
|
||||
{
|
||||
if (BinStream[i] > high)
|
||||
high = BinStream[i];
|
||||
else if (BinStream[i] < low)
|
||||
low = BinStream[i];
|
||||
}
|
||||
if ((high < 158) ){ //throw away static
|
||||
//PrintAndLog("no data found");
|
||||
return -2;
|
||||
}
|
||||
//25% fuzz in case highs and lows aren't clipped [marshmellow]
|
||||
high=(int)((high-128)*.75)+128;
|
||||
low= (int)((low-128)*.75)+128;
|
||||
|
||||
//PrintAndLog("DEBUG - valid high: %d - valid low: %d",high,low);
|
||||
int lastBit = 0; //set first clock check
|
||||
uint32_t bitnum = 0; //output counter
|
||||
int tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
|
||||
if (*clk==32)tol=1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
|
||||
int iii = 0;
|
||||
uint32_t gLen = *BitLen;
|
||||
if (gLen > 3000) gLen=3000;
|
||||
uint8_t errCnt =0;
|
||||
uint32_t bestStart = *BitLen;
|
||||
uint32_t bestErrCnt = (*BitLen/1000);
|
||||
uint32_t maxErr = (*BitLen/1000);
|
||||
//PrintAndLog("DEBUG - lastbit - %d",lastBit);
|
||||
//loop to find first wave that works
|
||||
for (iii=0; iii < gLen; ++iii){
|
||||
if ((BinStream[iii]>=high)||(BinStream[iii]<=low)){
|
||||
lastBit=iii-*clk;
|
||||
errCnt=0;
|
||||
//loop through to see if this start location works
|
||||
for (i = iii; i < *BitLen; ++i) {
|
||||
if ((BinStream[i] >= high) && ((i-lastBit)>(*clk-tol))){
|
||||
lastBit+=*clk;
|
||||
} else if ((BinStream[i] <= low) && ((i-lastBit)>(*clk-tol))){
|
||||
//low found and we are expecting a bar
|
||||
lastBit+=*clk;
|
||||
} else {
|
||||
//mid value found or no bar supposed to be here
|
||||
if ((i-lastBit)>(*clk+tol)){
|
||||
//should have hit a high or low based on clock!!
|
||||
|
||||
//debug
|
||||
//PrintAndLog("DEBUG - no wave in expected area - location: %d, expected: %d-%d, lastBit: %d - resetting search",i,(lastBit+(clk-((int)(tol)))),(lastBit+(clk+((int)(tol)))),lastBit);
|
||||
|
||||
errCnt++;
|
||||
lastBit+=*clk;//skip over until hit too many errors
|
||||
if (errCnt>(maxErr)) break; //allow 1 error for every 1000 samples else start over
|
||||
}
|
||||
}
|
||||
if ((i-iii) >(400 * *clk)) break; //got plenty of bits
|
||||
}
|
||||
//we got more than 64 good bits and not all errors
|
||||
if ((((i-iii)/ *clk) > (64+errCnt)) && (errCnt<maxErr)) {
|
||||
//possible good read
|
||||
if (errCnt==0){
|
||||
bestStart=iii;
|
||||
bestErrCnt=errCnt;
|
||||
break; //great read - finish
|
||||
}
|
||||
if (errCnt<bestErrCnt){ //set this as new best run
|
||||
bestErrCnt=errCnt;
|
||||
bestStart = iii;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestErrCnt<maxErr){
|
||||
//best run is good enough set to best run and set overwrite BinStream
|
||||
iii=bestStart;
|
||||
lastBit=bestStart-*clk;
|
||||
bitnum=0;
|
||||
for (i = iii; i < *BitLen; ++i) {
|
||||
if ((BinStream[i] >= high) && ((i-lastBit)>(*clk-tol))){
|
||||
lastBit+=*clk;
|
||||
BinStream[bitnum] = *invert;
|
||||
bitnum++;
|
||||
} else if ((BinStream[i] <= low) && ((i-lastBit)>(*clk-tol))){
|
||||
//low found and we are expecting a bar
|
||||
lastBit+=*clk;
|
||||
BinStream[bitnum] = 1-*invert;
|
||||
bitnum++;
|
||||
} else {
|
||||
//mid value found or no bar supposed to be here
|
||||
if ((i-lastBit)>(*clk+tol)){
|
||||
//should have hit a high or low based on clock!!
|
||||
|
||||
//debug
|
||||
//PrintAndLog("DEBUG - no wave in expected area - location: %d, expected: %d-%d, lastBit: %d - resetting search",i,(lastBit+(clk-((int)(tol)))),(lastBit+(clk+((int)(tol)))),lastBit);
|
||||
if (bitnum > 0){
|
||||
BinStream[bitnum]=77;
|
||||
bitnum++;
|
||||
}
|
||||
|
||||
lastBit+=*clk;//skip over error
|
||||
}
|
||||
}
|
||||
if (bitnum >=400) break;
|
||||
}
|
||||
*BitLen=bitnum;
|
||||
} else{
|
||||
*invert=bestStart;
|
||||
*clk=iii;
|
||||
return -1;
|
||||
}
|
||||
return bestErrCnt;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//take 10 and 01 and manchester decode
|
||||
//run through 2 times and take least errCnt
|
||||
int manrawdecode(uint8_t * BitStream, int *bitLen)
|
||||
{
|
||||
int bitnum=0;
|
||||
int errCnt =0;
|
||||
int i=1;
|
||||
int bestErr = 1000;
|
||||
int bestRun = 0;
|
||||
int ii=1;
|
||||
for (ii=1;ii<3;++ii){
|
||||
i=1;
|
||||
for (i=i+ii;i<*bitLen-2;i+=2){
|
||||
if(BitStream[i]==1 && (BitStream[i+1]==0)){
|
||||
} else if((BitStream[i]==0)&& BitStream[i+1]==1){
|
||||
} else {
|
||||
errCnt++;
|
||||
}
|
||||
if(bitnum>300) break;
|
||||
}
|
||||
if (bestErr>errCnt){
|
||||
bestErr=errCnt;
|
||||
bestRun=ii;
|
||||
}
|
||||
errCnt=0;
|
||||
}
|
||||
errCnt=bestErr;
|
||||
if (errCnt<20){
|
||||
ii=bestRun;
|
||||
i=1;
|
||||
for (i=i+ii;i<*bitLen-2;i+=2){
|
||||
if(BitStream[i]==1 && (BitStream[i+1]==0)){
|
||||
BitStream[bitnum++]=0;
|
||||
} else if((BitStream[i]==0)&& BitStream[i+1]==1){
|
||||
BitStream[bitnum++]=1;
|
||||
} else {
|
||||
BitStream[bitnum++]=77;
|
||||
//errCnt++;
|
||||
}
|
||||
if(bitnum>300) break;
|
||||
}
|
||||
*bitLen=bitnum;
|
||||
}
|
||||
return errCnt;
|
||||
}
|
||||
|
||||
|
||||
//by marshmellow
|
||||
//take 01 or 10 = 0 and 11 or 00 = 1
|
||||
int BiphaseRawDecode(uint8_t * BitStream, int *bitLen, int offset)
|
||||
{
|
||||
uint8_t bitnum=0;
|
||||
uint32_t errCnt =0;
|
||||
uint32_t i=1;
|
||||
i=offset;
|
||||
for (;i<*bitLen-2;i+=2){
|
||||
if((BitStream[i]==1 && BitStream[i+1]==0)||(BitStream[i]==0 && BitStream[i+1]==1)){
|
||||
BitStream[bitnum++]=1;
|
||||
} else if((BitStream[i]==0 && BitStream[i+1]==0)||(BitStream[i]==1 && BitStream[i+1]==1)){
|
||||
BitStream[bitnum++]=0;
|
||||
} else {
|
||||
BitStream[bitnum++]=77;
|
||||
errCnt++;
|
||||
}
|
||||
if(bitnum>250) break;
|
||||
}
|
||||
*bitLen=bitnum;
|
||||
return errCnt;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//takes 2 arguments - clock and invert both as integers
|
||||
//attempts to demodulate ask only
|
||||
//prints binary found and saves in graphbuffer for further commands
|
||||
int askrawdemod(uint8_t *BinStream, int *bitLen,int *clk, int *invert)
|
||||
{
|
||||
uint32_t i;
|
||||
// int invert=0; //invert default
|
||||
int high = 0, low = 128;
|
||||
*clk=DetectASKClock(BinStream,*bitLen,*clk); //clock default
|
||||
uint8_t BitStream[502] = {0};
|
||||
|
||||
if (*clk<8) *clk =64;
|
||||
if (*clk<32) *clk=32;
|
||||
if (*invert != 0 && *invert != 1) *invert =0;
|
||||
uint32_t initLoopMax = 200;
|
||||
if (initLoopMax>*bitLen) initLoopMax=*bitLen;
|
||||
// Detect high and lows
|
||||
for (i = 0; i < initLoopMax; ++i) //200 samples should be plenty to find high and low values
|
||||
{
|
||||
if (BinStream[i] > high)
|
||||
high = BinStream[i];
|
||||
else if (BinStream[i] < low)
|
||||
low = BinStream[i];
|
||||
}
|
||||
if ((high < 158)){ //throw away static
|
||||
// PrintAndLog("no data found");
|
||||
return -2;
|
||||
}
|
||||
//25% fuzz in case highs and lows aren't clipped [marshmellow]
|
||||
high=(int)((high-128)*.75)+128;
|
||||
low= (int)((low-128)*.75)+128;
|
||||
|
||||
//PrintAndLog("DEBUG - valid high: %d - valid low: %d",high,low);
|
||||
int lastBit = 0; //set first clock check
|
||||
uint32_t bitnum = 0; //output counter
|
||||
uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
|
||||
if (*clk==32)tol=1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely
|
||||
uint32_t iii = 0;
|
||||
uint32_t gLen = *bitLen;
|
||||
if (gLen > 500) gLen=500;
|
||||
uint8_t errCnt =0;
|
||||
uint32_t bestStart = *bitLen;
|
||||
uint32_t bestErrCnt = (*bitLen/1000);
|
||||
uint8_t midBit=0;
|
||||
//PrintAndLog("DEBUG - lastbit - %d",lastBit);
|
||||
//loop to find first wave that works
|
||||
for (iii=0; iii < gLen; ++iii){
|
||||
if ((BinStream[iii]>=high)||(BinStream[iii]<=low)){
|
||||
lastBit=iii-*clk;
|
||||
//loop through to see if this start location works
|
||||
for (i = iii; i < *bitLen; ++i) {
|
||||
if ((BinStream[i] >= high) && ((i-lastBit)>(*clk-tol))){
|
||||
lastBit+=*clk;
|
||||
BitStream[bitnum] = *invert;
|
||||
bitnum++;
|
||||
midBit=0;
|
||||
} else if ((BinStream[i] <= low) && ((i-lastBit)>(*clk-tol))){
|
||||
//low found and we are expecting a bar
|
||||
lastBit+=*clk;
|
||||
BitStream[bitnum] = 1-*invert;
|
||||
bitnum++;
|
||||
midBit=0;
|
||||
} else if ((BinStream[i]<=low) && (midBit==0) && ((i-lastBit)>((*clk/2)-tol))){
|
||||
//mid bar?
|
||||
midBit=1;
|
||||
BitStream[bitnum]= 1-*invert;
|
||||
bitnum++;
|
||||
} else if ((BinStream[i]>=high)&&(midBit==0) && ((i-lastBit)>((*clk/2)-tol))){
|
||||
//mid bar?
|
||||
midBit=1;
|
||||
BitStream[bitnum]= *invert;
|
||||
bitnum++;
|
||||
} else if ((i-lastBit)>((*clk/2)+tol)&&(midBit==0)){
|
||||
//no mid bar found
|
||||
midBit=1;
|
||||
BitStream[bitnum]= BitStream[bitnum-1];
|
||||
bitnum++;
|
||||
} else {
|
||||
//mid value found or no bar supposed to be here
|
||||
|
||||
if ((i-lastBit)>(*clk+tol)){
|
||||
//should have hit a high or low based on clock!!
|
||||
//debug
|
||||
//PrintAndLog("DEBUG - no wave in expected area - location: %d, expected: %d-%d, lastBit: %d - resetting search",i,(lastBit+(clk-((int)(tol)))),(lastBit+(clk+((int)(tol)))),lastBit);
|
||||
if (bitnum > 0){
|
||||
BitStream[bitnum]=77;
|
||||
bitnum++;
|
||||
}
|
||||
|
||||
|
||||
errCnt++;
|
||||
lastBit+=*clk;//skip over until hit too many errors
|
||||
if (errCnt>((*bitLen/1000))){ //allow 1 error for every 1000 samples else start over
|
||||
errCnt=0;
|
||||
bitnum=0;//start over
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bitnum>500) break;
|
||||
}
|
||||
//we got more than 64 good bits and not all errors
|
||||
if ((bitnum > (64+errCnt)) && (errCnt<(*bitLen/1000))) {
|
||||
//possible good read
|
||||
if (errCnt==0) break; //great read - finish
|
||||
if (bestStart == iii) break; //if current run == bestErrCnt run (after exhausted testing) then finish
|
||||
if (errCnt<bestErrCnt){ //set this as new best run
|
||||
bestErrCnt=errCnt;
|
||||
bestStart = iii;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (iii>=gLen){ //exhausted test
|
||||
//if there was a ok test go back to that one and re-run the best run (then dump after that run)
|
||||
if (bestErrCnt < (*bitLen/1000)) iii=bestStart;
|
||||
}
|
||||
}
|
||||
if (bitnum>16){
|
||||
|
||||
// PrintAndLog("Data start pos:%d, lastBit:%d, stop pos:%d, numBits:%d",iii,lastBit,i,bitnum);
|
||||
//move BitStream back to BinStream
|
||||
// ClearGraph(0);
|
||||
for (i=0; i < bitnum; ++i){
|
||||
BinStream[i]=BitStream[i];
|
||||
}
|
||||
*bitLen=bitnum;
|
||||
// RepaintGraphWindow();
|
||||
//output
|
||||
// if (errCnt>0){
|
||||
// PrintAndLog("# Errors during Demoding (shown as 77 in bit stream): %d",errCnt);
|
||||
// }
|
||||
// PrintAndLog("ASK decoded bitstream:");
|
||||
// Now output the bitstream to the scrollback by line of 16 bits
|
||||
// printBitStream2(BitStream,bitnum);
|
||||
//int errCnt=0;
|
||||
//errCnt=manrawdemod(BitStream,bitnum);
|
||||
|
||||
// Em410xDecode(Cmd);
|
||||
} else return -1;
|
||||
return errCnt;
|
||||
}
|
||||
//translate wave to 11111100000 (1 for each short wave 0 for each long wave)
|
||||
size_t fsk_wave_demod(uint8_t * dest, size_t size, uint8_t fchigh, uint8_t fclow)
|
||||
{
|
||||
uint32_t last_transition = 0;
|
||||
uint32_t idx = 1;
|
||||
uint32_t maxVal=0;
|
||||
if (fchigh==0) fchigh=10;
|
||||
if (fclow==0) fclow=8;
|
||||
// we do care about the actual theshold value as sometimes near the center of the
|
||||
// wave we may get static that changes direction of wave for one value
|
||||
// if our value is too low it might affect the read. and if our tag or
|
||||
// antenna is weak a setting too high might not see anything. [marshmellow]
|
||||
if (size<100) return 0;
|
||||
for(idx=1; idx<100; idx++){
|
||||
if(maxVal<dest[idx]) maxVal = dest[idx];
|
||||
}
|
||||
// set close to the top of the wave threshold with 25% margin for error
|
||||
// less likely to get a false transition up there.
|
||||
// (but have to be careful not to go too high and miss some short waves)
|
||||
uint8_t threshold_value = (uint8_t)(((maxVal-128)*.75)+128);
|
||||
// idx=1;
|
||||
//uint8_t threshold_value = 127;
|
||||
|
||||
// sync to first lo-hi transition, and threshold
|
||||
|
||||
// Need to threshold first sample
|
||||
|
||||
if(dest[0] < threshold_value) dest[0] = 0;
|
||||
else dest[0] = 1;
|
||||
|
||||
size_t numBits = 0;
|
||||
// count cycles between consecutive lo-hi transitions, there should be either 8 (fc/8)
|
||||
// or 10 (fc/10) cycles but in practice due to noise etc we may end up with with anywhere
|
||||
// between 7 to 11 cycles so fuzz it by treat anything <9 as 8 and anything else as 10
|
||||
for(idx = 1; idx < size; idx++) {
|
||||
// threshold current value
|
||||
|
||||
if (dest[idx] < threshold_value) dest[idx] = 0;
|
||||
else dest[idx] = 1;
|
||||
|
||||
// Check for 0->1 transition
|
||||
if (dest[idx-1] < dest[idx]) { // 0 -> 1 transition
|
||||
if ((idx-last_transition)<(fclow-2)){ //0-5 = garbage noise
|
||||
//do nothing with extra garbage
|
||||
} else if ((idx-last_transition) < (fchigh-1)) { //6-8 = 8 waves
|
||||
dest[numBits]=1;
|
||||
} else { //9+ = 10 waves
|
||||
dest[numBits]=0;
|
||||
}
|
||||
last_transition = idx;
|
||||
numBits++;
|
||||
}
|
||||
}
|
||||
return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0
|
||||
}
|
||||
|
||||
uint32_t myround2(float f)
|
||||
{
|
||||
if (f >= 2000) return 2000;//something bad happened
|
||||
return (uint32_t) (f + (float)0.5);
|
||||
}
|
||||
|
||||
//translate 11111100000 to 10
|
||||
size_t aggregate_bits(uint8_t *dest,size_t size, uint8_t rfLen, uint8_t maxConsequtiveBits, uint8_t invert,uint8_t fchigh,uint8_t fclow )// uint8_t h2l_crossing_value,uint8_t l2h_crossing_value,
|
||||
{
|
||||
uint8_t lastval=dest[0];
|
||||
uint32_t idx=0;
|
||||
size_t numBits=0;
|
||||
uint32_t n=1;
|
||||
|
||||
for( idx=1; idx < size; idx++) {
|
||||
|
||||
if (dest[idx]==lastval) {
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
//if lastval was 1, we have a 1->0 crossing
|
||||
if ( dest[idx-1]==1 ) {
|
||||
n=myround2((float)(n+1)/((float)(rfLen)/(float)fclow));
|
||||
//n=(n+1) / h2l_crossing_value;
|
||||
} else {// 0->1 crossing
|
||||
n=myround2((float)(n+1)/((float)(rfLen-2)/(float)fchigh)); //-2 for fudge factor
|
||||
//n=(n+1) / l2h_crossing_value;
|
||||
}
|
||||
if (n == 0) n = 1;
|
||||
|
||||
if(n < maxConsequtiveBits) //Consecutive
|
||||
{
|
||||
if(invert==0){ //invert bits
|
||||
memset(dest+numBits, dest[idx-1] , n);
|
||||
}else{
|
||||
memset(dest+numBits, dest[idx-1]^1 , n);
|
||||
}
|
||||
numBits += n;
|
||||
}
|
||||
n=0;
|
||||
lastval=dest[idx];
|
||||
}//end for
|
||||
return numBits;
|
||||
}
|
||||
//by marshmellow (from holiman's base)
|
||||
// full fsk demod from GraphBuffer wave to decoded 1s and 0s (no mandemod)
|
||||
int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow)
|
||||
{
|
||||
// FSK demodulator
|
||||
size = fsk_wave_demod(dest, size, fchigh, fclow);
|
||||
size = aggregate_bits(dest, size,rfLen,192,invert,fchigh,fclow);
|
||||
return size;
|
||||
}
|
||||
// loop to get raw HID waveform then FSK demodulate the TAG ID from it
|
||||
int HIDdemodFSK(uint8_t *dest, size_t size, uint32_t *hi2, uint32_t *hi, uint32_t *lo)
|
||||
{
|
||||
|
||||
size_t idx=0; //, found=0; //size=0,
|
||||
// FSK demodulator
|
||||
size = fskdemod(dest, size,50,0,10,8);
|
||||
|
||||
// final loop, go over previously decoded manchester data and decode into usable tag ID
|
||||
// 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0
|
||||
uint8_t frame_marker_mask[] = {1,1,1,0,0,0};
|
||||
int numshifts = 0;
|
||||
idx = 0;
|
||||
//one scan
|
||||
while( idx + sizeof(frame_marker_mask) < size) {
|
||||
// search for a start of frame marker
|
||||
if ( memcmp(dest+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0)
|
||||
{ // frame marker found
|
||||
idx+=sizeof(frame_marker_mask);
|
||||
while(dest[idx] != dest[idx+1] && idx < size-2)
|
||||
{
|
||||
// Keep going until next frame marker (or error)
|
||||
// Shift in a bit. Start by shifting high registers
|
||||
*hi2 = (*hi2<<1)|(*hi>>31);
|
||||
*hi = (*hi<<1)|(*lo>>31);
|
||||
//Then, shift in a 0 or one into low
|
||||
if (dest[idx] && !dest[idx+1]) // 1 0
|
||||
*lo=(*lo<<1)|0;
|
||||
else // 0 1
|
||||
*lo=(*lo<<1)|1;
|
||||
numshifts++;
|
||||
idx += 2;
|
||||
}
|
||||
// Hopefully, we read a tag and hit upon the next frame marker
|
||||
if(idx + sizeof(frame_marker_mask) < size)
|
||||
{
|
||||
if ( memcmp(dest+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0)
|
||||
{
|
||||
//good return
|
||||
return idx;
|
||||
}
|
||||
}
|
||||
// reset
|
||||
*hi2 = *hi = *lo = 0;
|
||||
numshifts = 0;
|
||||
}else {
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t bytebits_to_byte(uint8_t* src, int numbits)
|
||||
{
|
||||
uint32_t num = 0;
|
||||
for(int i = 0 ; i < numbits ; i++)
|
||||
{
|
||||
num = (num << 1) | (*src);
|
||||
src++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
int IOdemodFSK(uint8_t *dest, size_t size)
|
||||
{
|
||||
uint32_t idx=0;
|
||||
//make sure buffer has data
|
||||
if (size < 66) return -1;
|
||||
//test samples are not just noise
|
||||
uint8_t testMax=0;
|
||||
for(idx=0;idx<65;idx++){
|
||||
if (testMax<dest[idx]) testMax=dest[idx];
|
||||
}
|
||||
idx=0;
|
||||
//if not just noise
|
||||
if (testMax>170){
|
||||
// FSK demodulator
|
||||
size = fskdemod(dest, size,64,1,10,8); // RF/64 and invert
|
||||
if (size < 65) return -1; //did we get a good demod?
|
||||
//Index map
|
||||
//0 10 20 30 40 50 60
|
||||
//| | | | | | |
|
||||
//01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
|
||||
//-----------------------------------------------------------------------------
|
||||
//00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
|
||||
//
|
||||
//XSF(version)facility:codeone+codetwo
|
||||
//Handle the data
|
||||
uint8_t mask[] = {0,0,0,0,0,0,0,0,0,1};
|
||||
for( idx=0; idx < (size - 65); idx++) {
|
||||
if ( memcmp(dest + idx, mask, sizeof(mask))==0) {
|
||||
//frame marker found
|
||||
if (!dest[idx+8] && dest[idx+17]==1 && dest[idx+26]==1 && dest[idx+35]==1 && dest[idx+44]==1 && dest[idx+53]==1){
|
||||
//confirmed proper separator bits found
|
||||
//return start position
|
||||
return (int) idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// by marshmellow
|
||||
// not perfect especially with lower clocks or VERY good antennas (heavy wave clipping)
|
||||
// maybe somehow adjust peak trimming value based on samples to fix?
|
||||
int DetectASKClock(uint8_t dest[], size_t size, int clock)
|
||||
{
|
||||
int i=0;
|
||||
int peak=0;
|
||||
int low=128;
|
||||
int clk[]={16,32,40,50,64,100,128,256};
|
||||
int loopCnt = 256; //don't need to loop through entire array...
|
||||
if (size<loopCnt) loopCnt = size;
|
||||
|
||||
//if we already have a valid clock quit
|
||||
for (;i<8;++i)
|
||||
if (clk[i]==clock) return clock;
|
||||
|
||||
//get high and low peak
|
||||
for (i=0;i<loopCnt;++i){
|
||||
if(dest[i]>peak){
|
||||
peak = dest[i];
|
||||
}
|
||||
if(dest[i]<low){
|
||||
low = dest[i];
|
||||
}
|
||||
}
|
||||
peak=(int)((peak-128)*.75)+128;
|
||||
low= (int)((low-128)*.75)+128;
|
||||
int ii;
|
||||
int clkCnt;
|
||||
int tol = 0;
|
||||
int bestErr=1000;
|
||||
int errCnt[]={0,0,0,0,0,0,0,0};
|
||||
//test each valid clock from smallest to greatest to see which lines up
|
||||
for(clkCnt=0; clkCnt<6;++clkCnt){
|
||||
if (clk[clkCnt]==32){
|
||||
tol=1;
|
||||
}else{
|
||||
tol=0;
|
||||
}
|
||||
bestErr=1000;
|
||||
//try lining up the peaks by moving starting point (try first 256)
|
||||
for (ii=0; ii<loopCnt; ++ii){
|
||||
if ((dest[ii]>=peak) || (dest[ii]<=low)){
|
||||
errCnt[clkCnt]=0;
|
||||
// now that we have the first one lined up test rest of wave array
|
||||
for (i=0; i<((int)(size/clk[clkCnt])-1); ++i){
|
||||
if (dest[ii+(i*clk[clkCnt])]>=peak || dest[ii+(i*clk[clkCnt])]<=low){
|
||||
}else if(dest[ii+(i*clk[clkCnt])-tol]>=peak || dest[ii+(i*clk[clkCnt])-tol]<=low){
|
||||
}else if(dest[ii+(i*clk[clkCnt])+tol]>=peak || dest[ii+(i*clk[clkCnt])+tol]<=low){
|
||||
}else{ //error no peak detected
|
||||
errCnt[clkCnt]++;
|
||||
}
|
||||
}
|
||||
//if we found no errors this is correct one - return this clock
|
||||
if(errCnt[clkCnt]==0) return clk[clkCnt];
|
||||
//if we found errors see if it is lowest so far and save it as best run
|
||||
if(errCnt[clkCnt]<bestErr) bestErr=errCnt[clkCnt];
|
||||
}
|
||||
}
|
||||
}
|
||||
int iii=0;
|
||||
int best=0;
|
||||
for (iii=0; iii<6;++iii){
|
||||
if (errCnt[iii]<errCnt[best]){
|
||||
best = iii;
|
||||
}
|
||||
}
|
||||
return clk[best];
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (C) 2014
|
||||
//
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Low frequency commands
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef LFDEMOD_H__
|
||||
#define LFDEMOD_H__
|
||||
#include <stdint.h>
|
||||
|
||||
int DetectASKClock(uint8_t dest[], size_t size, int clock);
|
||||
int askmandemod(uint8_t *BinStream,uint32_t *BitLen,int *clk, int *invert);
|
||||
uint64_t Em410xDecode(uint8_t *BitStream,uint32_t BitLen);
|
||||
int manrawdecode(uint8_t *BitStream, int *bitLen);
|
||||
int BiphaseRawDecode(uint8_t * BitStream, int *bitLen, int offset);
|
||||
int askrawdemod(uint8_t *BinStream, int *bitLen,int *clk, int *invert);
|
||||
int HIDdemodFSK(uint8_t *dest, size_t size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
|
||||
int IOdemodFSK(uint8_t *dest, size_t size);
|
||||
int fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow);
|
||||
uint32_t bytebits_to_byte(uint8_t* src, int numbits);
|
||||
|
||||
#endif
|
||||
@@ -81,6 +81,8 @@ typedef struct {
|
||||
#define CMD_EM4X_WRITE_WORD 0x0219
|
||||
#define CMD_IO_DEMOD_FSK 0x021A
|
||||
#define CMD_IO_CLONE_TAG 0x021B
|
||||
#define CMD_EM410X_DEMOD 0x021C
|
||||
|
||||
/* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */
|
||||
|
||||
// For the 13.56 MHz tags
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+40000
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user