mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-09-20 15:26:13 +08:00
ADD: marshmellows new lf command and DetectClock. (works great!)
FIX: a suggested patch for "hf mf csetuid" (https://github.com/Proxmark/proxmark3/issues/35) FIX: fixed a bug in iso14443a_select_card where the len variable wasnt set, this made desfire/magic cards not work.
This commit is contained in:
parent
3bc3598e88
commit
1b492a97af
|
@ -394,7 +394,11 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
|
|||
} else if (Uart.len & 0x0007) { // there are some parity bits to store
|
||||
Uart.parityBits <<= (8 - (Uart.len & 0x0007)); // left align remaining parity bits
|
||||
Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store them
|
||||
}
|
||||
if ( Uart.len) {
|
||||
return TRUE; // we are finished with decoding the raw data sequence
|
||||
} else {
|
||||
UartReset(); // Nothing receiver - start over
|
||||
}
|
||||
}
|
||||
if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
|
||||
|
@ -556,6 +560,8 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non
|
|||
} else if (Demod.len & 0x0007) { // there are some parity bits to store
|
||||
Demod.parityBits <<= (8 - (Demod.len & 0x0007)); // left align remaining parity bits
|
||||
Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them
|
||||
}
|
||||
if (Demod.len) {
|
||||
return TRUE; // we are finished with decoding the raw data sequence
|
||||
} else { // nothing received. Start over
|
||||
DemodReset();
|
||||
|
@ -1627,7 +1633,7 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
|
|||
//-----------------------------------------------------------------------------
|
||||
static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset)
|
||||
{
|
||||
uint16_t c;
|
||||
uint32_t c;
|
||||
|
||||
// Set FPGA mode to "reader listen mode", no modulation (listen
|
||||
// only, since we are receiving, not transmitting).
|
||||
|
@ -1716,8 +1722,6 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity)
|
|||
* fills resp_data unless NULL */
|
||||
int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, uint32_t* cuid_ptr) {
|
||||
|
||||
iso14a_set_timeout(10500); // 10ms default 10*105 =
|
||||
|
||||
//uint8_t deselect[] = {0xc2}; //DESELECT
|
||||
//uint8_t halt[] = { 0x50, 0x00, 0x57, 0xCD }; // HALT
|
||||
uint8_t wupa[] = { 0x52 }; // WAKE-UP
|
||||
|
@ -1732,7 +1736,7 @@ int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, u
|
|||
size_t uid_resp_len;
|
||||
uint8_t sak = 0x04; // cascade uid
|
||||
int cascade_level = 0;
|
||||
int len;
|
||||
int len =0;
|
||||
|
||||
// test for the SKYLANDERS TOY.
|
||||
// ReaderTransmit(deselect,sizeof(deselect), NULL);
|
||||
|
@ -1812,7 +1816,11 @@ int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, u
|
|||
ReaderTransmit(sel_uid,sizeof(sel_uid), NULL);
|
||||
|
||||
// Receive the SAK
|
||||
if (!ReaderReceive(resp, resp_par)) return 0;
|
||||
if (!ReaderReceive(resp, resp_par)){
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
sak = resp[0];
|
||||
|
||||
// Test if more parts of the uid are coming
|
||||
|
@ -1841,21 +1849,15 @@ int iso14443a_select_card(byte_t* uid_ptr, iso14a_card_select_t* p_hi14a_card, u
|
|||
p_hi14a_card->ats_len = 0;
|
||||
}
|
||||
|
||||
if( (sak & 0x20) == 0) {
|
||||
return 2; // non iso14443a compliant tag
|
||||
}
|
||||
// non iso14443a compliant tag
|
||||
if( (sak & 0x20) == 0) return 2;
|
||||
|
||||
// Request for answer to select
|
||||
AppendCrc14443a(rats, 2);
|
||||
ReaderTransmit(rats, sizeof(rats), NULL);
|
||||
|
||||
if (!(len = ReaderReceive(resp, resp_par))) return 0;
|
||||
|
||||
len = ReaderReceive(resp, resp_par);
|
||||
Dbprintf("RATS Reponse: %d", len);
|
||||
if(!len) {
|
||||
Dbprintf("RATS: %02x %02x %02x", resp[0], resp[1], resp[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(p_hi14a_card) {
|
||||
memcpy(p_hi14a_card->ats, resp, sizeof(p_hi14a_card->ats));
|
||||
|
|
|
@ -721,14 +721,28 @@ void CmdHIDsimTAG(int hi, int lo, uint8_t ledcontrol)
|
|||
LED_A_OFF();
|
||||
}
|
||||
|
||||
//translate wave to 11111100000 (1 for each short wave 0 for each long wave)
|
||||
size_t fsk_demod(uint8_t * dest, size_t size)
|
||||
{
|
||||
uint32_t last_transition = 0;
|
||||
uint32_t idx = 1;
|
||||
uint32_t maxVal=0;
|
||||
// // 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
|
||||
|
||||
// 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;
|
||||
// we do care about the actual 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 size;
|
||||
for(idx=1; idx<100; idx++){
|
||||
if(maxVal<dest[idx]) maxVal = dest[idx];
|
||||
}
|
||||
// set close to the top of the wave threshold with 13% 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)
|
||||
uint32_t threshold_value = (uint32_t)(maxVal*.87); idx=1;
|
||||
//uint8_t threshold_value = 127;
|
||||
|
||||
// sync to first lo-hi transition, and threshold
|
||||
|
||||
|
@ -754,8 +768,14 @@ size_t fsk_demod(uint8_t * dest, size_t size)
|
|||
return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0
|
||||
}
|
||||
|
||||
uint32_t myround(float f)
|
||||
{
|
||||
if (f >= 2000) return 2000;//something bad happened
|
||||
return (uint32_t) (f + (float)0.5);
|
||||
}
|
||||
|
||||
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 )
|
||||
//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 h2l_crossing_value,uint8_t l2h_crossing_value,
|
||||
{
|
||||
uint8_t lastval=dest[0];
|
||||
uint32_t idx=0;
|
||||
|
@ -769,10 +789,12 @@ size_t aggregate_bits(uint8_t *dest,size_t size, uint8_t h2l_crossing_value,uint
|
|||
continue;
|
||||
}
|
||||
//if lastval was 1, we have a 1->0 crossing
|
||||
if ( dest[idx-1] ) {
|
||||
n=(n+1) / h2l_crossing_value;
|
||||
if ( dest[idx-1]==1 ) {
|
||||
n=myround((float)(n+1)/((float)(rfLen)/(float)8));
|
||||
//n=(n+1) / h2l_crossing_value;
|
||||
} else {// 0->1 crossing
|
||||
n=(n+1) / l2h_crossing_value;
|
||||
n=myround((float)(n+1)/((float)(rfLen-2)/(float)10));
|
||||
//n=(n+1) / l2h_crossing_value;
|
||||
}
|
||||
if (n == 0) n = 1;
|
||||
|
||||
|
@ -792,7 +814,7 @@ size_t aggregate_bits(uint8_t *dest,size_t size, uint8_t h2l_crossing_value,uint
|
|||
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 = get_bigbufptr_recvrespbuf();
|
||||
|
@ -817,7 +839,7 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
|||
// 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);
|
||||
size = aggregate_bits(dest,size, 50,5,0); //6,5,5,0
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
|
@ -826,8 +848,11 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
|||
uint8_t frame_marker_mask[] = {1,1,1,0,0,0};
|
||||
int numshifts = 0;
|
||||
idx = 0;
|
||||
//one scan
|
||||
uint8_t sameCardCount =0;
|
||||
while( idx + sizeof(frame_marker_mask) < size) {
|
||||
// search for a start of frame marker
|
||||
if (sameCardCount>2) break; //only up to 2 valid sets of data for the same read of looping card data
|
||||
if ( memcmp(dest+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0)
|
||||
{ // frame marker found
|
||||
idx+=sizeof(frame_marker_mask);
|
||||
|
@ -905,6 +930,7 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
|||
(unsigned int) hi, (unsigned int) lo, (unsigned int) (lo>>1) & 0xFFFF,
|
||||
(unsigned int) bitlen, (unsigned int) fc, (unsigned int) cardnum);
|
||||
}
|
||||
sameCardCount++;
|
||||
if (findone){
|
||||
if (ledcontrol) LED_A_OFF();
|
||||
return;
|
||||
|
@ -955,14 +981,24 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
|||
|
||||
DoAcquisition125k_internal(-1,true);
|
||||
size = sizeof(BigBuf);
|
||||
|
||||
//make sure buffer has data
|
||||
if (size < 64) return;
|
||||
//test samples are not just noise
|
||||
uint8_t testMax=0;
|
||||
for(idx=0;idx<64;idx++){
|
||||
if (testMax<dest[idx]) testMax=dest[idx];
|
||||
}
|
||||
idx=0;
|
||||
//if not just noise
|
||||
if (testMax>170){
|
||||
//Dbprintf("testMax: %d",testMax);
|
||||
// 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
|
||||
|
||||
size = aggregate_bits(dest, size, 64, 13, 1); //13 max Consecutive should be ok as most 0s in row should be 10 for init seq - invert bits
|
||||
WDT_HIT();
|
||||
//Index map
|
||||
//0 10 20 30 40 50 60
|
||||
//| | | | | | |
|
||||
|
@ -972,12 +1008,14 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
|||
//
|
||||
//XSF(version)facility:codeone+codetwo
|
||||
//Handle the data
|
||||
|
||||
uint8_t sameCardCount=0;
|
||||
uint8_t mask[] = {0,0,0,0,0,0,0,0,0,1};
|
||||
|
||||
for( idx=0; idx < (size - 64); idx++) {
|
||||
for( idx=0; idx < (size - 74); idx++) {
|
||||
if (sameCardCount>2) break;
|
||||
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
|
||||
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]);
|
||||
|
@ -989,9 +1027,9 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
|||
}
|
||||
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
|
||||
short version = bytebits_to_byte(dest+idx+27,8); //14,4
|
||||
uint8_t facilitycode = bytebits_to_byte(dest+idx+19,8) ;
|
||||
uint16_t number = (bytebits_to_byte(dest+idx+36,8)<<8)|(bytebits_to_byte(dest+idx+45,8)); //36,9
|
||||
|
||||
Dbprintf("XSF(%02d)%02x:%d (%08x%08x)",version,facilitycode,number,code,code2);
|
||||
|
||||
|
@ -1001,6 +1039,9 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
|
|||
isFinish = 1;
|
||||
break;
|
||||
}
|
||||
sameCardCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
WDT_HIT();
|
||||
|
@ -1183,7 +1224,7 @@ void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
|
|||
dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
++i;
|
||||
LED_D_OFF();
|
||||
if (i > bufferlength) break;
|
||||
if (i >= bufferlength) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -601,7 +601,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
|
|||
nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160
|
||||
for (i = 141; i < 1200; i++) {
|
||||
nttmp = prng_successor(nttmp, 1);
|
||||
if (nttmp == nt2) {break;}
|
||||
if (nttmp == nt2) break;
|
||||
}
|
||||
|
||||
if (i != 1200) {
|
||||
|
@ -945,8 +945,8 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();
|
||||
uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
|
||||
|
||||
// reset FPGA and LED
|
||||
if (workFlags & 0x08) {
|
||||
// clear trace
|
||||
iso14a_clear_trace();
|
||||
iso14a_set_tracing(TRUE);
|
||||
|
||||
|
@ -956,16 +956,18 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
SpinDelay(300);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(100);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
//SpinDelay(300);
|
||||
//FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
//SpinDelay(100);
|
||||
//FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
|
||||
// get UID from chip
|
||||
if (workFlags & 0x01) {
|
||||
if(!iso14443a_select_card(uid, NULL, &cuid)) {
|
||||
Dbprintf("ICE");
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
break;
|
||||
};
|
||||
|
@ -1041,7 +1043,6 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
LED_B_OFF();
|
||||
|
||||
if ((workFlags & 0x10) || (!isOK)) {
|
||||
// Thats it...
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
}
|
||||
|
@ -1082,10 +1083,10 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
|
|||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
|
||||
SpinDelay(300);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
SpinDelay(100);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
// SpinDelay(300);
|
||||
// FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
// SpinDelay(100);
|
||||
// FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
|
|
|
@ -32,9 +32,7 @@ bool InitDesfireCard(){
|
|||
int len = iso14443a_select_card(NULL,card,NULL);
|
||||
|
||||
if (!len) {
|
||||
if (MF_DBGLEVEL >= 1) {
|
||||
Dbprintf("Can't select card");
|
||||
}
|
||||
if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
|
||||
OnError();
|
||||
return false;
|
||||
}
|
||||
|
|
640
client/cmddata.c
640
client/cmddata.c
|
@ -70,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;
|
||||
|
@ -118,6 +119,274 @@ int Cmdaskdemod(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
void printBitStream(int BitStream[], uint32_t bitLen){
|
||||
uint32_t i = 0;
|
||||
if (bitLen<16) 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;
|
||||
}
|
||||
void printBitStream2(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
|
||||
//takes 1s and 0s and searches for EM410x format - output EM ID
|
||||
int Em410xDecode(const char *Cmd)
|
||||
{
|
||||
//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=0;
|
||||
uint64_t lo=0; //hi=0,
|
||||
|
||||
uint32_t i = 0;
|
||||
uint32_t initLoopMax = 1000;
|
||||
if (initLoopMax>GraphTraceLen) initLoopMax=GraphTraceLen;
|
||||
|
||||
for (;i < initLoopMax; ++i) //1000 samples should be plenty to find high and low values
|
||||
{
|
||||
if (GraphBuffer[i] > high)
|
||||
high = GraphBuffer[i];
|
||||
else if (GraphBuffer[i] < low)
|
||||
low = GraphBuffer[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
|
||||
int 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) < GraphTraceLen) {
|
||||
restart:
|
||||
// search for a start of frame marker
|
||||
if ( memcmp(GraphBuffer+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 += GraphBuffer[(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)|(GraphBuffer[(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,GraphBuffer[idx+ii+(i*5)-5],GraphBuffer[idx+ii+(i*5)-4],GraphBuffer[idx+ii+(i*5)-3],GraphBuffer[idx+ii+(i*5)-2],GraphBuffer[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,GraphBuffer[idx+ii+(i*5)-5],GraphBuffer[idx+ii+(i*5)-4],GraphBuffer[idx+ii+(i*5)-3],GraphBuffer[idx+ii+(i*5)-2],GraphBuffer[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.
|
||||
|
||||
//get Unique ID
|
||||
uint64_t iii=1;
|
||||
uint64_t id2lo=0; //id2hi=0,
|
||||
//for (i=0;i<8;i++){ //for uint32 instead of uint64
|
||||
// id2hi=(id2hi<<1)|((hi & (iii<<(i)))>>i);
|
||||
//}
|
||||
for (ii=5; ii>0;ii--){
|
||||
for (i=0;i<8;i++){
|
||||
id2lo=(id2lo<<1LL)|((lo & (iii<<(i+((ii-1)*8))))>>(i+((ii-1)*8)));
|
||||
}
|
||||
}
|
||||
//output em id
|
||||
PrintAndLog("EM TAG ID : %010llx", lo);
|
||||
PrintAndLog("Unique TAG ID: %010llx", id2lo); //id2hi,
|
||||
PrintAndLog("DEZ 8 : %08lld",lo & 0xFFFFFF);
|
||||
PrintAndLog("DEZ 10 : %010lld",lo & 0xFFFFFF);
|
||||
PrintAndLog("DEZ 5.5 : %05lld.%05lld",(lo>>16LL) & 0xFFFF,(lo & 0xFFFF));
|
||||
PrintAndLog("DEZ 3.5A : %03lld.%05lld",(lo>>32ll),(lo & 0xFFFF));
|
||||
PrintAndLog("DEZ 14/IK2 : %014lld",lo);
|
||||
PrintAndLog("DEZ 15/IK3 : %015lld",id2lo);
|
||||
PrintAndLog("Other : %05lld_%03lld_%08lld",(lo&0xFFFF),((lo>>16LL) & 0xFF),(lo & 0xFFFFFF));
|
||||
return 0;
|
||||
}else{
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//by marshmellow
|
||||
//takes 2 arguments - clock and invert both as integers
|
||||
//prints binary found and saves in graphbuffer for further commands
|
||||
int Cmdaskmandemod(const char *Cmd)
|
||||
{
|
||||
uint32_t i;
|
||||
int invert=0; //invert default
|
||||
int high = 0, low = 0;
|
||||
int clk=DetectClock(0); //clock default
|
||||
uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0};
|
||||
sscanf(Cmd, "%i %i", &clk, &invert);
|
||||
if (clk<8) clk =64;
|
||||
if (clk<32) clk=32;
|
||||
if (invert != 0 && invert != 1) {
|
||||
PrintAndLog("Invalid argument: %s", Cmd);
|
||||
return 0;
|
||||
}
|
||||
uint32_t initLoopMax = 1000;
|
||||
if (initLoopMax>GraphTraceLen) initLoopMax=GraphTraceLen;
|
||||
// Detect high and lows
|
||||
PrintAndLog("Using Clock: %d and invert=%d",clk,invert);
|
||||
for (i = 0; i < initLoopMax; ++i) //1000 samples should be plenty to find high and low values
|
||||
{
|
||||
if (GraphBuffer[i] > high)
|
||||
high = GraphBuffer[i];
|
||||
else if (GraphBuffer[i] < low)
|
||||
low = GraphBuffer[i];
|
||||
}
|
||||
if ((high < 30) && ((high !=1)||(low !=-1))){ //throw away static - allow 1 and -1 (in case of threshold command first)
|
||||
PrintAndLog("no data found");
|
||||
return 0;
|
||||
}
|
||||
//13% fuzz in case highs and lows aren't clipped [marshmellow]
|
||||
high=(int)(0.75*high);
|
||||
low=(int)(0.75*low);
|
||||
|
||||
//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 = GraphTraceLen;
|
||||
if (gLen > 500) gLen=500;
|
||||
uint8_t errCnt =0;
|
||||
uint32_t bestStart = GraphTraceLen;
|
||||
uint32_t bestErrCnt = (GraphTraceLen/1000);
|
||||
//PrintAndLog("DEBUG - lastbit - %d",lastBit);
|
||||
//loop to find first wave that works
|
||||
for (iii=0; iii < gLen; ++iii){
|
||||
if ((GraphBuffer[iii]>=high)||(GraphBuffer[iii]<=low)){
|
||||
lastBit=iii-clk;
|
||||
//loop through to see if this start location works
|
||||
for (i = iii; i < GraphTraceLen; ++i) {
|
||||
if ((GraphBuffer[i] >= high) && ((i-lastBit)>(clk-tol))){
|
||||
lastBit+=clk;
|
||||
BitStream[bitnum] = invert;
|
||||
bitnum++;
|
||||
} else if ((GraphBuffer[i] <= low) && ((i-lastBit)>(clk-tol))){
|
||||
//low found and we are expecting a bar
|
||||
lastBit+=clk;
|
||||
BitStream[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){
|
||||
BitStream[bitnum]=77;
|
||||
bitnum++;
|
||||
}
|
||||
|
||||
|
||||
errCnt++;
|
||||
lastBit+=clk;//skip over until hit too many errors
|
||||
if (errCnt>((GraphTraceLen/1000))){ //allow 1 error for every 1000 samples else start over
|
||||
errCnt=0;
|
||||
bitnum=0;//start over
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//we got more than 64 good bits and not all errors
|
||||
if ((bitnum > (64+errCnt)) && (errCnt<(GraphTraceLen/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 < (GraphTraceLen/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 GraphBuffer
|
||||
ClearGraph(0);
|
||||
for (i=0; i < bitnum; ++i){
|
||||
GraphBuffer[i]=BitStream[i];
|
||||
}
|
||||
GraphTraceLen=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);
|
||||
Em410xDecode(Cmd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdAutoCorr(const char *Cmd)
|
||||
{
|
||||
static int CorrelBuffer[MAX_GRAPH_TRACE_LEN];
|
||||
|
@ -263,7 +532,370 @@ int CmdDetectClockRate(const char *Cmd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int CmdFSKdemod(const char *Cmd)
|
||||
//by marshmellow
|
||||
//demod GraphBuffer wave to 0s and 1s for each wave - 0s for short waves 1s for long waves
|
||||
size_t fsk_wave_demod(int size)
|
||||
{
|
||||
uint32_t last_transition = 0;
|
||||
uint32_t idx = 1;
|
||||
uint32_t maxVal = 0;
|
||||
// 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
|
||||
for(idx=1; idx<size; idx++){
|
||||
if(maxVal<GraphBuffer[idx]) maxVal = GraphBuffer[idx];
|
||||
}
|
||||
// set close to the top of the wave threshold with 13% 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)
|
||||
uint32_t threshold_value = (uint32_t)(maxVal*.87);
|
||||
idx=1;
|
||||
// int threshold_value = 100;
|
||||
|
||||
// sync to first lo-hi transition, and threshold
|
||||
// PrintAndLog("FSK init complete size: %d",size);//debug
|
||||
// Need to threshold first sample
|
||||
if(GraphBuffer[0] < threshold_value) GraphBuffer[0] = 0;
|
||||
else GraphBuffer[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 (GraphBuffer[idx] < threshold_value) GraphBuffer[idx] = 0;
|
||||
else GraphBuffer[idx] = 1;
|
||||
// Check for 0->1 transition
|
||||
if (GraphBuffer[idx-1] < GraphBuffer[idx]) { // 0 -> 1 transition
|
||||
if (idx-last_transition<6){
|
||||
// do nothing with extra garbage (shouldn't be any) noise tolerance?
|
||||
} else if(idx-last_transition < 9) {
|
||||
GraphBuffer[numBits]=1;
|
||||
// Other fsk demods reverse this making the short waves 1 and long waves 0
|
||||
// this is really backwards... smaller waves will typically be 0 and larger 1 [marshmellow]
|
||||
// but will leave as is and invert when needed later
|
||||
} else{
|
||||
GraphBuffer[numBits]=0;
|
||||
}
|
||||
last_transition = idx;
|
||||
numBits++;
|
||||
// PrintAndLog("numbits %d",numBits);
|
||||
}
|
||||
}
|
||||
return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0
|
||||
}
|
||||
uint32_t myround(float f)
|
||||
{
|
||||
if (f >= UINT_MAX) return UINT_MAX;
|
||||
return (uint32_t) (f + (float)0.5);
|
||||
}
|
||||
|
||||
//by marshmellow (from holiman's base)
|
||||
//translate 11111100000 to 10
|
||||
size_t aggregate_bits(int size, uint8_t rfLen, uint8_t maxConsequtiveBits, uint8_t invert) //,uint8_t l2h_crossing_value
|
||||
{
|
||||
int lastval=GraphBuffer[0];
|
||||
uint32_t idx=0;
|
||||
size_t numBits=0;
|
||||
uint32_t n=1;
|
||||
uint32_t n2=0;
|
||||
for( idx=1; idx < size; idx++) {
|
||||
|
||||
if (GraphBuffer[idx]==lastval) {
|
||||
n++;
|
||||
continue;
|
||||
}
|
||||
// if lastval was 1, we have a 1->0 crossing
|
||||
if ( GraphBuffer[idx-1]==1 ) {
|
||||
n=myround((float)(n+1)/((float)(rfLen)/(float)8)); //-2 noise tolerance
|
||||
|
||||
// n=(n+1) / h2l_crossing_value;
|
||||
//truncating could get us into trouble
|
||||
//now we will try with actual clock (RF/64 or RF/50) variable instead
|
||||
//then devide with float casting then truncate after more acurate division
|
||||
//and round to nearest int
|
||||
//like n = (((float)n)/(float)rfLen/(float)10);
|
||||
} else {// 0->1 crossing
|
||||
n=myround((float)(n+1)/((float)(rfLen-2)/(float)10)); // as int 120/6 = 20 as float 120/(64/10) = 18 (18.75)
|
||||
//n=(n+1) / l2h_crossing_value;
|
||||
}
|
||||
if (n == 0) n = 1; //this should never happen... should we error if it does?
|
||||
|
||||
if (n < maxConsequtiveBits) // Consecutive //when the consecutive bits are low - the noise tolerance can be high
|
||||
//if it is high then we must be careful how much noise tolerance we allow
|
||||
{
|
||||
if (invert==0){ // do not invert bits
|
||||
for (n2=0; n2<n; n2++){
|
||||
GraphBuffer[numBits+n2]=GraphBuffer[idx-1];
|
||||
}
|
||||
//memset(GraphBuffer+numBits, GraphBuffer[idx-1] , n);
|
||||
}else{ // invert bits
|
||||
for (n2=0; n2<n; n2++){
|
||||
GraphBuffer[numBits+n2]=GraphBuffer[idx-1]^1;
|
||||
}
|
||||
//memset(GraphBuffer+numBits, GraphBuffer[idx-1]^1 , n);
|
||||
}
|
||||
numBits += n;
|
||||
}
|
||||
n=0;
|
||||
lastval=GraphBuffer[idx];
|
||||
}//end for
|
||||
return numBits;
|
||||
}
|
||||
|
||||
//by marshmellow (from holiman's base)
|
||||
// full fsk demod from GraphBuffer wave to decoded 1s and 0s (no mandemod)
|
||||
size_t fskdemod(uint8_t rfLen, uint8_t invert)
|
||||
{
|
||||
//uint8_t h2l_crossing_value = 6;
|
||||
//uint8_t l2h_crossing_value = 5;
|
||||
|
||||
// if (rfLen==64) //currently only know settings for RF/64 change from default if option entered
|
||||
// {
|
||||
// h2l_crossing_value=8; //or 8 as 64/8 = 8
|
||||
// l2h_crossing_value=6; //or 6.4 as 64/10 = 6.4
|
||||
// }
|
||||
size_t size = GraphTraceLen;
|
||||
// FSK demodulator
|
||||
size = fsk_wave_demod(size);
|
||||
size = aggregate_bits(size,rfLen,192,invert);
|
||||
// size = aggregate_bits(size, h2l_crossing_value, l2h_crossing_value,192, invert); //192=no limit to same values
|
||||
//done messing with GraphBuffer - repaint
|
||||
RepaintGraphWindow();
|
||||
return size;
|
||||
}
|
||||
uint32_t bytebits_to_byte(int* src, int numbits)
|
||||
{
|
||||
uint32_t num = 0;
|
||||
for(int i = 0 ; i < numbits ; i++)
|
||||
{
|
||||
num = (num << 1) | (*src);
|
||||
src++;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
//fsk demod and print binary
|
||||
int CmdFSKrawdemod(const char *Cmd)
|
||||
{
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
//set defaults
|
||||
uint8_t rfLen = 50;
|
||||
uint8_t invert=0;
|
||||
//set options from parameters entered with the command
|
||||
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;
|
||||
}
|
||||
if (strlen(Cmd)>2) {
|
||||
rfLen=param_get8(Cmd, 0); //if both options are used
|
||||
invert=param_get8(Cmd,1);
|
||||
}
|
||||
PrintAndLog("Args invert: %d \nClock:%d",invert,rfLen);
|
||||
|
||||
size_t size = fskdemod(rfLen,invert);
|
||||
|
||||
PrintAndLog("FSK decoded bitstream:");
|
||||
// Now output the bitstream to the scrollback by line of 16 bits
|
||||
if(size > (7*32)+2) size = (7*32)+2; //only output a max of 7 blocks of 32 bits most tags will have full bit stream inside that sample size
|
||||
printBitStream(GraphBuffer,size);
|
||||
|
||||
ClearGraph(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
int CmdFSKdemodHID(const char *Cmd)
|
||||
{
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
//set defaults
|
||||
uint8_t rfLen = 50;
|
||||
uint8_t invert=0;//param_get8(Cmd, 0);
|
||||
size_t idx=0;
|
||||
uint32_t hi2=0, hi=0, lo=0;
|
||||
|
||||
//get binary from fsk wave
|
||||
size_t size = fskdemod(rfLen,invert);
|
||||
|
||||
// final loop, go over previously decoded fsk data and now manchester decode into usable tag ID
|
||||
// 111000 bit pattern represent start of frame, 01 pattern represents a 1 and 10 represents a 0
|
||||
int frame_marker_mask[] = {1,1,1,0,0,0};
|
||||
int numshifts = 0;
|
||||
idx = 0;
|
||||
while( idx + 6 < size) {
|
||||
// search for a start of frame marker
|
||||
|
||||
if ( memcmp(GraphBuffer+idx, frame_marker_mask, sizeof(frame_marker_mask)) == 0)
|
||||
{ // frame marker found
|
||||
idx+=6;//sizeof(frame_marker_mask); //size of int is >6
|
||||
while(GraphBuffer[idx] != GraphBuffer[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 (GraphBuffer[idx] && !GraphBuffer[idx+1]) // 1 0
|
||||
lo=(lo<<1)|0;
|
||||
else // 0 1
|
||||
lo=(lo<<1)|1;
|
||||
numshifts++;
|
||||
idx += 2;
|
||||
}
|
||||
|
||||
//PrintAndLog("Num shifts: %d ", numshifts);
|
||||
// Hopefully, we read a tag and hit upon the next frame marker
|
||||
if(idx + 6 < size)
|
||||
{
|
||||
if ( memcmp(GraphBuffer+(idx), frame_marker_mask, sizeof(frame_marker_mask)) == 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);
|
||||
}
|
||||
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 & 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++;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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) bitlen, (unsigned int) fc, (unsigned int) cardnum);
|
||||
ClearGraph(1);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// reset
|
||||
hi2 = hi = lo = 0;
|
||||
numshifts = 0;
|
||||
}else
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
if (idx + sizeof(frame_marker_mask) >= size){
|
||||
PrintAndLog("start bits for hid not found");
|
||||
PrintAndLog("FSK decoded bitstream:");
|
||||
// Now output the bitstream to the scrollback by line of 16 bits
|
||||
printBitStream(GraphBuffer,size);
|
||||
|
||||
}
|
||||
ClearGraph(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//by marshmellow
|
||||
int CmdFSKdemodIO(const char *Cmd)
|
||||
{
|
||||
//raw fsk demod no manchester decoding no start bit finding just get binary from wave
|
||||
//set defaults
|
||||
uint8_t rfLen = 64;
|
||||
uint8_t invert=1;
|
||||
size_t idx=0;
|
||||
uint8_t testMax=0;
|
||||
//test samples are not just noise
|
||||
if (GraphTraceLen < 64) return 0;
|
||||
for(idx=0;idx<64;idx++){
|
||||
if (testMax<GraphBuffer[idx]) testMax=GraphBuffer[idx];
|
||||
}
|
||||
idx=0;
|
||||
//get full binary from fsk wave
|
||||
size_t size = fskdemod(rfLen,invert);
|
||||
|
||||
//if not just noise
|
||||
//PrintAndLog("testMax %d",testMax);
|
||||
if (testMax>40){
|
||||
//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
|
||||
int mask[] = {0,0,0,0,0,0,0,0,0,1};
|
||||
for( idx=0; idx < (size - 74); idx++) {
|
||||
if ( memcmp(GraphBuffer + idx, mask, sizeof(mask))==0) {
|
||||
//frame marker found
|
||||
if (GraphBuffer[idx+17]==1 && GraphBuffer[idx+26]==1 && GraphBuffer[idx+35]==1 && GraphBuffer[idx+44]==1 && GraphBuffer[idx+53]==1){
|
||||
//confirmed proper separator bits found
|
||||
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx], GraphBuffer[idx+1], GraphBuffer[idx+2], GraphBuffer[idx+3], GraphBuffer[idx+4], GraphBuffer[idx+5], GraphBuffer[idx+6], GraphBuffer[idx+7], GraphBuffer[idx+8]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx+9], GraphBuffer[idx+10], GraphBuffer[idx+11],GraphBuffer[idx+12],GraphBuffer[idx+13],GraphBuffer[idx+14],GraphBuffer[idx+15],GraphBuffer[idx+16],GraphBuffer[idx+17]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx+18], GraphBuffer[idx+19], GraphBuffer[idx+20],GraphBuffer[idx+21],GraphBuffer[idx+22],GraphBuffer[idx+23],GraphBuffer[idx+24],GraphBuffer[idx+25],GraphBuffer[idx+26]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx+27], GraphBuffer[idx+28], GraphBuffer[idx+29],GraphBuffer[idx+30],GraphBuffer[idx+31],GraphBuffer[idx+32],GraphBuffer[idx+33],GraphBuffer[idx+34],GraphBuffer[idx+35]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx+36], GraphBuffer[idx+37], GraphBuffer[idx+38],GraphBuffer[idx+39],GraphBuffer[idx+40],GraphBuffer[idx+41],GraphBuffer[idx+42],GraphBuffer[idx+43],GraphBuffer[idx+44]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d",GraphBuffer[idx+45], GraphBuffer[idx+46], GraphBuffer[idx+47],GraphBuffer[idx+48],GraphBuffer[idx+49],GraphBuffer[idx+50],GraphBuffer[idx+51],GraphBuffer[idx+52],GraphBuffer[idx+53]);
|
||||
PrintAndLog("%d%d%d%d%d%d%d%d %d%d",GraphBuffer[idx+54],GraphBuffer[idx+55],GraphBuffer[idx+56],GraphBuffer[idx+57],GraphBuffer[idx+58],GraphBuffer[idx+59],GraphBuffer[idx+60],GraphBuffer[idx+61],GraphBuffer[idx+62],GraphBuffer[idx+63]);
|
||||
|
||||
uint32_t code = bytebits_to_byte(GraphBuffer+idx,32);
|
||||
uint32_t code2 = bytebits_to_byte(GraphBuffer+idx+32,32);
|
||||
short version = bytebits_to_byte(GraphBuffer+idx+27,8); //14,4
|
||||
uint8_t facilitycode = bytebits_to_byte(GraphBuffer+idx+19,8) ;
|
||||
uint16_t number = (bytebits_to_byte(GraphBuffer+idx+36,8)<<8)|(bytebits_to_byte(GraphBuffer+idx+45,8)); //36,9
|
||||
|
||||
PrintAndLog("XSF(%02d)%02x:%d (%08x%08x)",version,facilitycode,number,code,code2);
|
||||
ClearGraph(1);
|
||||
return 0;
|
||||
} else {
|
||||
PrintAndLog("thought we had a valid tag but did not match format");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (idx >= (size-74)){
|
||||
PrintAndLog("start bits for io prox not found");
|
||||
PrintAndLog("FSK decoded bitstream:");
|
||||
// Now output the bitstream to the scrollback by line of 16 bits
|
||||
printBitStream(GraphBuffer,size);
|
||||
}
|
||||
}
|
||||
ClearGraph(1);
|
||||
return 0;
|
||||
}
|
||||
int CmdFSKdemod(const char *Cmd) //old CmdFSKdemod needs updating
|
||||
{
|
||||
static const int LowTone[] = {
|
||||
1, 1, 1, 1, 1, -1, -1, -1, -1, -1,
|
||||
|
@ -320,7 +952,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;
|
||||
|
@ -954,6 +1586,7 @@ static command_t CommandTable[] =
|
|||
{"help", CmdHelp, 1, "This help"},
|
||||
{"amp", CmdAmp, 1, "Amplify peaks"},
|
||||
{"askdemod", Cmdaskdemod, 1, "<0|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])"},
|
||||
{"autocorr", CmdAutoCorr, 1, "<window length> -- Autocorrelation over window"},
|
||||
{"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"},
|
||||
{"bitstream", CmdBitstream, 1, "[clock rate] -- Convert waveform into a bitstream"},
|
||||
|
@ -962,6 +1595,9 @@ static command_t CommandTable[] =
|
|||
{"detectclock", CmdDetectClockRate, 1, "Detect clock rate"},
|
||||
{"dirthreshold", CmdDirectionalThreshold, 1, "<thres up> <thres down> -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."},
|
||||
{"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] Demodulate graph window from FSK to binary (clock = 64 or 50)(invert = 1 or 0)"},
|
||||
{"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"},
|
||||
|
|
|
@ -17,6 +17,7 @@ int CmdData(const char *Cmd);
|
|||
|
||||
int CmdAmp(const char *Cmd);
|
||||
int Cmdaskdemod(const char *Cmd);
|
||||
int Cmdaskrawdemod(const char *Cmd);
|
||||
int CmdAutoCorr(const char *Cmd);
|
||||
int CmdBitsamples(const char *Cmd);
|
||||
int CmdBitstream(const char *Cmd);
|
||||
|
@ -24,6 +25,9 @@ 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);
|
||||
|
|
|
@ -232,7 +232,6 @@ int CmdHF14AReader(const char *Cmd)
|
|||
c.arg[2] = 0;
|
||||
SendCommand(&c);
|
||||
|
||||
|
||||
if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes
|
||||
bool ta1 = 0, tb1 = 0, tc1 = 0;
|
||||
int pos;
|
||||
|
|
|
@ -1465,6 +1465,7 @@ int CmdHF14AMfCSetUID(const char *Cmd)
|
|||
}
|
||||
|
||||
PrintAndLog("old UID:%s", sprint_hex(oldUid, 4));
|
||||
PrintAndLog("new UID:%s", sprint_hex(uid, 4));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -371,6 +371,9 @@ int CmdLFRead(const char *Cmd)
|
|||
}
|
||||
SendCommand(&c);
|
||||
WaitForResponse(CMD_ACK,NULL);
|
||||
|
||||
// load samples
|
||||
CmdSamples("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include "proxmark3.h"
|
||||
#include "ui.h"
|
||||
//#include "graph.h"
|
||||
|
@ -43,22 +44,25 @@ int CmdClone(const char *Cmd)
|
|||
// char block2 = "00107060";
|
||||
// char block3 = "00107060";
|
||||
|
||||
unsigned char buf[10] = {0x00};
|
||||
unsigned char *resp = buf;
|
||||
|
||||
|
||||
awid26_hex_to_uid(resp, "");
|
||||
// PrintAndLog("Writing block %d with data %08X", Block, Data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// convert 96 bit AWID FSK data to 8 digit BCD UID
|
||||
bool awid26_hex_to_uid(unsigned char *response, unsigned char *awid26)
|
||||
bool awid26_hex_to_uid(unsigned char *response, char *awid26)
|
||||
{
|
||||
// uint8_t i, tmp[96], tmp1[7];
|
||||
// int site;
|
||||
// int id;
|
||||
uint8_t i, tmp[96], tmp1[7];
|
||||
int site;
|
||||
int id;
|
||||
|
||||
// if(!hextobinarray(tmp, awid26))
|
||||
// return false;
|
||||
if(!hextobinarray(tmp, awid26))
|
||||
return false;
|
||||
|
||||
// // data is in blocks of 4 bits - every 4th bit is parity, except the first
|
||||
// // block which is all zeros
|
||||
|
@ -71,7 +75,7 @@ bool awid26_hex_to_uid(unsigned char *response, unsigned char *awid26)
|
|||
|
||||
// // check and strip parity on the rest
|
||||
// for(i= 1 ; i < 23 ; ++i)
|
||||
// if(tmp[(i * 4) - 1] != parity(tmp + (i - 1) * 4, ODD, 3))
|
||||
// if(tmp[(i * 4) - 1] != GetParity(tmp + (i - 1) * 4, ODD, 3))
|
||||
// return false;
|
||||
// else
|
||||
// memcpy((tmp + (i - 1) * 3), tmp + (i - 1) * 4, 3);
|
||||
|
@ -86,9 +90,9 @@ bool awid26_hex_to_uid(unsigned char *response, unsigned char *awid26)
|
|||
// memcpy(tmp, tmp +8, 58);
|
||||
|
||||
// // standard wiegand parity check - even for 1st 12 bits, odd for 2nd 12
|
||||
// if(tmp[0] != parity(tmp + 1, EVEN, 12))
|
||||
// if(tmp[0] != GetParity(tmp + 1, EVEN, 12))
|
||||
// return false;
|
||||
// if(tmp[25] != parity(tmp + 13, ODD, 12))
|
||||
// if(tmp[25] != GetParity(tmp + 13, ODD, 12))
|
||||
// return false;
|
||||
|
||||
// // convert to hex, ignoring parity bits
|
||||
|
@ -146,7 +150,7 @@ bool bcd_to_awid26_bin(unsigned char *awid26, unsigned char *bcd)
|
|||
|
||||
// // add parity bits
|
||||
// for(i= 1 ; i < 24 ; ++i)
|
||||
// awid26[((i + 1) * 4) - 1]= parity(&awid26[i * 4], ODD, 3);
|
||||
// awid26[((i + 1) * 4) - 1]= GetParity(&awid26[i * 4], ODD, 3);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
int CmdLFAWID26(const char *Cmd);
|
||||
|
||||
int CmdClone(const char *Cmd);
|
||||
bool awid26_hex_to_uid(unsigned char *response, unsigned char *awid26);
|
||||
bool awid26_hex_to_uid(unsigned char *response, char *awid26);
|
||||
bool bcd_to_awid26_bin(unsigned char *awid26, unsigned char *bcd);
|
||||
#endif
|
||||
|
|
|
@ -58,6 +58,7 @@ int CmdHIDSim(const char *Cmd)
|
|||
}
|
||||
|
||||
PrintAndLog("Emulating tag with ID %x%16x", hi, lo);
|
||||
PrintAndLog("Press pm3-button to abort simulation");
|
||||
|
||||
UsbCommand c = {CMD_HID_SIM_TAG, {hi, lo, 0}};
|
||||
SendCommand(&c);
|
||||
|
|
|
@ -55,7 +55,7 @@ int CmdIOClone(const char *Cmd)
|
|||
}
|
||||
|
||||
PrintAndLog("Cloning tag with ID %08x %08x", hi, lo);
|
||||
|
||||
PrintAndLog("Press pm3-button to abort simulation");
|
||||
c.cmd = CMD_IO_CLONE_TAG;
|
||||
c.arg[0] = hi;
|
||||
c.arg[1] = lo;
|
||||
|
|
|
@ -51,13 +51,15 @@ int ClearGraph(int redraw)
|
|||
/*
|
||||
* Detect clock rate
|
||||
*/
|
||||
int DetectClock(int peak)
|
||||
//decommissioned - has difficulty detecting rf/32 and only works if data is manchester encoded
|
||||
/*
|
||||
int DetectClock2(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)
|
||||
|
@ -65,36 +67,90 @@ int DetectClock(int peak)
|
|||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
int clockmod = clock%8;
|
||||
if ( clockmod == 0)
|
||||
return clock;
|
||||
}
|
||||
*/
|
||||
|
||||
// When detected clock is 31 or 33 then return 32
|
||||
|
||||
printf("Found clock at %d ", clock);
|
||||
switch( clockmod )
|
||||
// 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 DetectClock(int peak)
|
||||
{
|
||||
case 7: clock++; break;
|
||||
case 6: clock += 2 ; break;
|
||||
case 1: clock--; break;
|
||||
case 2: clock -= 2; break;
|
||||
int i=0;
|
||||
int low=0;
|
||||
int clk[]={16,32,40,50,64,100,128,256};
|
||||
if (!peak){
|
||||
for (i=0;i<GraphTraceLen;++i){
|
||||
if(GraphBuffer[i]>peak){
|
||||
peak = GraphBuffer[i];
|
||||
}
|
||||
if(GraphBuffer[i]<low){
|
||||
low = GraphBuffer[i];
|
||||
}
|
||||
}
|
||||
peak=(int)(peak*.75);
|
||||
low= (int)(low*.75);
|
||||
}
|
||||
//int numbits;
|
||||
int ii;
|
||||
int loopCnt = 256;
|
||||
if (GraphTraceLen<loopCnt) loopCnt = GraphTraceLen;
|
||||
int clkCnt;
|
||||
int tol = 0;
|
||||
int bestErr=1000;
|
||||
int errCnt[]={0,0,0,0,0,0,0,0};
|
||||
// int good;
|
||||
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)){
|
||||
//numbits=0;
|
||||
//good=1;
|
||||
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){
|
||||
//numbits++;
|
||||
}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
|
||||
//numbits=0;
|
||||
//good=0;
|
||||
errCnt[clkCnt]++;
|
||||
//break;
|
||||
}
|
||||
}
|
||||
if(errCnt[clkCnt]==0) return clk[clkCnt];
|
||||
if(errCnt[clkCnt]<bestErr) bestErr=errCnt[clkCnt];
|
||||
}
|
||||
}
|
||||
errCnt[clkCnt]=bestErr;
|
||||
}
|
||||
int iii=0;
|
||||
int best=0;
|
||||
for (iii=0; iii<6;++iii){
|
||||
if (errCnt[iii]<errCnt[best]){
|
||||
best = iii;
|
||||
}
|
||||
}
|
||||
PrintAndLog("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];
|
||||
}
|
||||
if ( clock < 32)
|
||||
clock = 32;
|
||||
|
||||
printf("- adjusted it to %d \n", clock);
|
||||
return clock;
|
||||
}
|
||||
|
||||
/* Get or auto-detect clock rate */
|
||||
int GetClock(const char *str, int peak, int verbose)
|
||||
|
@ -109,6 +165,7 @@ int GetClock(const char *str, int peak, int verbose)
|
|||
if (!clock)
|
||||
{
|
||||
clock = DetectClock(peak);
|
||||
//clock2 = DetectClock2(peak);
|
||||
/* Only print this message if we're not looping something */
|
||||
if (!verbose)
|
||||
PrintAndLog("Auto-detected clock rate: %d", clock);
|
||||
|
|
|
@ -232,8 +232,7 @@ int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
|
|||
// "MAGIC" CARD
|
||||
|
||||
int mfCSetUID(uint8_t *uid, uint8_t *oldUID, bool wantWipe) {
|
||||
uint8_t block0[16];
|
||||
memset(block0, 0, 16);
|
||||
uint8_t block0[16] = {0x00};
|
||||
memcpy(block0, uid, 4);
|
||||
block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // Mifare UID BCC
|
||||
// mifare classic SAK(byte 5) and ATQA(byte 6 and 7)
|
||||
|
@ -245,8 +244,8 @@ int mfCSetUID(uint8_t *uid, uint8_t *oldUID, bool wantWipe) {
|
|||
}
|
||||
|
||||
int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uint8_t params) {
|
||||
uint8_t isOK = 0;
|
||||
|
||||
uint8_t isOK = 0;
|
||||
UsbCommand c = {CMD_MIFARE_EML_CSETBLOCK, {wantWipe, params & (0xFE | (uid == NULL ? 0:1)), blockNo}};
|
||||
memcpy(c.d.asBytes, data, 16);
|
||||
SendCommand(&c);
|
||||
|
@ -341,12 +340,14 @@ int loadTraceCard(uint8_t *tuid) {
|
|||
memset(buf, 0, sizeof(buf));
|
||||
if (fgets(buf, sizeof(buf), f) == NULL) {
|
||||
PrintAndLog("File reading error.");
|
||||
fclose(f);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (strlen(buf) < 32){
|
||||
if (feof(f)) break;
|
||||
PrintAndLog("File content error. Block data must include 32 HEX symbols");
|
||||
fclose(f);
|
||||
return 2;
|
||||
}
|
||||
for (i = 0; i < 32; i += 2)
|
||||
|
|
|
@ -73,6 +73,7 @@ serial_port uart_open(const char* pcPortName)
|
|||
// Does the system allows us to place a lock on this file descriptor
|
||||
if (fcntl(sp->fd, F_SETLK, &fl) == -1) {
|
||||
// A conflicting lock is held by another process
|
||||
free(sp);
|
||||
return CLAIMED_SERIAL_PORT;
|
||||
}
|
||||
|
||||
|
|
|
@ -372,7 +372,7 @@ void binarraytobinstring(char *target, char *source, int length)
|
|||
}
|
||||
|
||||
// return parity bit required to match type
|
||||
uint8_t parity( char *bits, uint8_t type, int length)
|
||||
uint8_t GetParity( char *bits, uint8_t type, int length)
|
||||
{
|
||||
int x;
|
||||
|
||||
|
@ -386,8 +386,8 @@ uint8_t parity( char *bits, uint8_t type, int length)
|
|||
// add HID parity to binary array: EVEN prefix for 1st half of ID, ODD suffix for 2nd half
|
||||
void wiegand_add_parity(char *target, char *source, char length)
|
||||
{
|
||||
*(target++)= parity(source, EVEN, length / 2);
|
||||
*(target++)= GetParity(source, EVEN, length / 2);
|
||||
memcpy(target, source, length);
|
||||
target += length;
|
||||
*(target)= parity(source + length / 2, ODD, length / 2);
|
||||
*(target)= GetParity(source + length / 2, ODD, length / 2);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,6 @@ int param_getstr(const char *line, int paramnum, char * str);
|
|||
int hextobinstring( char *target, char *source);
|
||||
int binarraytohex( char *target, char *source, int length);
|
||||
void binarraytobinstring(char *target, char *source, int length);
|
||||
uint8_t parity( char *string, uint8_t type, int length);
|
||||
uint8_t GetParity( char *string, uint8_t type, int length);
|
||||
void wiegand_add_parity(char *target, char *source, char length);
|
||||
|
||||
|
|
Loading…
Reference in a new issue