From: Iceman Date: Wed, 5 Apr 2017 13:41:16 +0000 (+0200) Subject: Merge pull request #268 from marshmellow42/master X-Git-Tag: v3.0.0~18 X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/ebfb4447b867205750692ca9bb54bcb6d9dc41e6?hp=b3ec0b3d4f5e26a266c70a46d4aaafbfa2110731 Merge pull request #268 from marshmellow42/master various lf bug fixes and improvements --- diff --git a/CHANGELOG.md b/CHANGELOG.md index eb4a62de..345be224 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] ### Added +- Added experimental testmode write option for t55xx (danger) (marshmellow) +- Added t55xx p1detect to `lf search` chip detections (marshmellow) +- Added lf t55xx p1detect, detect page 1 of a t55xx tag based on E015 mfg code (marshmellow) - Added lf noralsy demod, read, clone, sim commands (iceman) - Added lf jablotron demod, read, clone, sim commands (iceman) - Added lf nexwatch read - reads a nexwatch tag from the antenna @@ -54,6 +57,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added option c to 'hf list' (mark CRC bytes) (piwi) ### Changed +- adjusted lf t5 chip timings to use WaitUS. and adjusted the readblock timings + appears to have more consistent results with more antennas. +- `lf t5 wakeup` has been adjusted to not need the p in front of the pwd arg. - `data psknexwatchdemod` has been moved to `lf nexwatch demod` (reads from graphbuffer) - `data fskparadoxdemod` has been moved to `lf paradox demod` (reads from graphbuffer) - `data fdxdemod` has been moved to `lf fdx demod` (reads from graphbuffer) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 75aa1342..9c6c9ed8 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1096,7 +1096,7 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol) void TurnReadLFOn(int delay) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); // Give it a bit of time for the resonant antenna to settle. - SpinDelayUs(delay); //155*8 //50*8 + WaitUS(delay); //155*8 //50*8 } // Write one bit to card @@ -1106,7 +1106,7 @@ void T55xxWriteBit(int bit) { else TurnReadLFOn(WRITE_1); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelayUs(WRITE_GAP); + WaitUS(WRITE_GAP); } // Send T5577 reset command then read stream (see if we can identify the start of the stream) @@ -1117,16 +1117,18 @@ void T55xxResetRead(void) { // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); - + StartTicks(); + // make sure tag is fully powered up... + WaitMS(5); + // Trigger T55x7 in mode. FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelayUs(START_GAP); + WaitUS(START_GAP); // reset tag - op code 00 T55xxWriteBit(0); T55xxWriteBit(0); - // Turn field on to read the response TurnReadLFOn(READ_GAP); // Acquisition @@ -1143,18 +1145,22 @@ void T55xxWriteBlockExt(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg LED_A_ON(); bool PwdMode = arg & 0x1; uint8_t Page = (arg & 0x2)>>1; + bool testMode = arg & 0x4; uint32_t i = 0; // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); - + StartTicks(); + // make sure tag is fully powered up... + WaitMS(5); // Trigger T55x7 in mode. FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelayUs(START_GAP); + WaitUS(START_GAP); - // Opcode 10 - T55xxWriteBit(1); - T55xxWriteBit(Page); //Page 0 + if (testMode) Dbprintf("TestMODE"); + // Std Opcode 10 + T55xxWriteBit(testMode ? 0 : 1); + T55xxWriteBit(testMode ? 1 : Page); //Page 0 if (PwdMode){ // Send Pwd for (i = 0x80000000; i != 0; i >>= 1) @@ -1173,11 +1179,31 @@ void T55xxWriteBlockExt(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t arg // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, // so wait a little more) - TurnReadLFOn(20 * 1000); + + // "there is a clock delay before programming" + // - programming takes ~5.6ms for t5577 ~18ms for E5550 + // so we should wait 1 clock + 5.6ms then read response? + // but we need to know we are dealing with t55x7 vs e5550 (or q5) marshmellow... + if (testMode) { + // Turn field on to read the response + TurnReadLFOn(READ_GAP); + + // Acquisition + // Now do the acquisition + // Now do the acquisition + DoPartialAcquisition(20, true, 12000); + + //doT55x7Acquisition(12000); + } else { + TurnReadLFOn(20 * 1000); + } //could attempt to do a read to confirm write took // as the tag should repeat back the new block // until it is reset, but to confirm it we would - // need to know the current block 0 config mode + // need to know the current block 0 config mode for + // modulation clock an other details to demod the response... + // response should be (for t55x7) a 0 bit then (ST if on) + // block data written in on repeat until reset. // turn field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -1196,7 +1222,7 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { bool PwdMode = arg0 & 0x1; uint8_t Page = (arg0 & 0x2) >> 1; uint32_t i = 0; - bool RegReadMode = (Block == 0xFF); + bool RegReadMode = (Block == 0xFF);//regular read mode //clear buffer now so it does not interfere with timing later BigBuf_Clear_ext(false); @@ -1206,10 +1232,12 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { // Set up FPGA, 125kHz to power up the tag LFSetupFPGAForADC(95, true); - + StartTicks(); + // make sure tag is fully powered up... + WaitMS(5); // Trigger T55x7 Direct Access Mode with start gap FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelayUs(START_GAP); + WaitUS(START_GAP); // Opcode 1[page] T55xxWriteBit(1); @@ -1229,10 +1257,15 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { T55xxWriteBit(Block & i); // Turn field on to read the response - TurnReadLFOn(READ_GAP); + // 137*8 seems to get to the start of data pretty well... + // but we want to go past the start and let the repeating data settle in... + TurnReadLFOn(210*8); // Acquisition - doT55x7Acquisition(12000); + // Now do the acquisition + DoPartialAcquisition(0, true, 12000); + + // doT55x7Acquisition(12000); // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off @@ -1246,10 +1279,13 @@ void T55xxWakeUp(uint32_t Pwd){ // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); + StartTicks(); + // make sure tag is fully powered up... + WaitMS(5); // Trigger T55x7 Direct Access Mode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelayUs(START_GAP); + WaitUS(START_GAP); // Opcode 10 T55xxWriteBit(1); @@ -1367,7 +1403,7 @@ void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t // clone viking tag to T55xx void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5) { uint32_t data[] = {T55x7_BITRATE_RF_32 | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT), block1, block2}; - if (Q5) data[0] = ( ((32-2)>>1) << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT; + if (Q5) data[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT; // Program the data blocks for supplied ID and the block 0 config WriteT55xx(data, 0, 3); LED_D_OFF(); @@ -1451,8 +1487,7 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) { } data[0] = clock | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT); } else { //t5555 (Q5) - clock = (clock-2)>>1; //n = (RF-2)/2 - data[0] = (clock << T5555_BITRATE_SHIFT) | T5555_MODULATION_MANCHESTER | (2 << T5555_MAXBLOCK_SHIFT); + data[0] = T5555_SET_BITRATE(clock) | T5555_MODULATION_MANCHESTER | (2 << T5555_MAXBLOCK_SHIFT); } WriteT55xx(data, 0, 3); diff --git a/client/cmddata.c b/client/cmddata.c index 0595dffa..b3e23cb6 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -51,6 +51,24 @@ void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx) return; } +// option '1' to save DemodBuffer any other to restore +void save_restoreDB(uint8_t saveOpt) +{ + static uint8_t SavedDB[MAX_GRAPH_TRACE_LEN]; + static size_t SavedDBlen; + static bool DB_Saved = false; + + if (saveOpt==1) { //save + memcpy(SavedDB, DemodBuffer, sizeof(DemodBuffer)); + SavedDBlen = DemodBufferLen; + DB_Saved=true; + } else if (DB_Saved){ //restore + memcpy(DemodBuffer, SavedDB, sizeof(DemodBuffer)); + DemodBufferLen = SavedDBlen; + } + return; +} + int CmdSetDebugMode(const char *Cmd) { int demod=0; @@ -200,6 +218,11 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, CursorCPos = ststart; CursorDPos = stend; if (verbose || g_debugMode) PrintAndLog("\nFound Sequence Terminator - First one is shown by orange and blue graph markers"); + //Graph ST trim (for testing) + //for (int i = 0; i < BitLen; i++) { + // GraphBuffer[i] = BitStream[i]-128; + //} + //RepaintGraphWindow(); } int errCnt = askdemod(BitStream, &BitLen, &clk, &invert, maxErr, askamp, askType); if (errCnt<0 || BitLen<16){ //if fatal error (or -1) @@ -818,14 +841,6 @@ int PSKDemod(const char *Cmd, bool verbose) uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; size_t BitLen = getFromGraphBuf(BitStream); if (BitLen==0) return 0; - uint8_t carrier=countFC(BitStream, BitLen, 0); - if (carrier!=2 && carrier!=4 && carrier!=8){ - //invalid carrier - return 0; - } - if (g_debugMode){ - PrintAndLog("Carrier: rf/%d",carrier); - } int errCnt=0; errCnt = pskRawDemod(BitStream, &BitLen, &clk, &invert); if (errCnt > maxErr){ diff --git a/client/cmddata.h b/client/cmddata.h index e03ab02c..7e77d313 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -22,6 +22,7 @@ command_t * CmdDataCommands(); int CmdData(const char *Cmd); void printDemodBuff(void); void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx); +void save_restoreDB(uint8_t saveOpt);// option '1' to save DemodBuffer any other to restore int CmdPrintDemodBuff(const char *Cmd); int Cmdaskrawdemod(const char *Cmd); int Cmdaskmandemod(const char *Cmd); @@ -68,6 +69,8 @@ int getSamples(const char *Cmd, bool silent); extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN]; extern size_t DemodBufferLen; extern uint8_t g_debugMode; +//extern size_t g_demodStartIdx; +//extern uint8_t g_demodClock; #define BIGBUF_SIZE 40000 #endif diff --git a/client/cmdlf.c b/client/cmdlf.c index 005aa0e2..f78b3801 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -863,16 +863,25 @@ int CheckChipType(char cmdp) { //check for em4x05/em4x69 chips first save_restoreGB(1); + save_restoreDB(1); if ((!offline && (cmdp != '1')) && EM4x05Block0Test(&wordData)) { PrintAndLog("\nValid EM4x05/EM4x69 Chip Found\nTry lf em 4x05... commands\n"); save_restoreGB(0); + save_restoreDB(0); return 1; } //TODO check for t55xx chip... + if ((!offline && (cmdp != '1')) && tryDetectP1(true)) { + PrintAndLog("\nValid T55xx Chip Found\nTry lf t55xx ... commands\n"); + save_restoreGB(0); + save_restoreDB(0); + return 1; + } save_restoreGB(0); - return 1; + save_restoreDB(0); + return 0; } //by marshmellow @@ -924,7 +933,7 @@ int CmdLFfind(const char *Cmd) return 1; } ans=CmdCOTAGRead(""); - if (ans>0){ + if (ans>0) { PrintAndLog("\nValid COTAG ID Found!"); return 1; } @@ -932,6 +941,8 @@ int CmdLFfind(const char *Cmd) return 0; } + // TODO test for modulation then only test formats that use that modulation + ans=CmdFSKdemodIO(""); if (ans>0) { PrintAndLog("\nValid IO Prox ID Found!"); @@ -980,13 +991,13 @@ int CmdLFfind(const char *Cmd) return CheckChipType(cmdp); } - ans=CmdFdxDemod(""); + ans=CmdFdxDemod(""); //biphase if (ans>0) { PrintAndLog("\nValid FDX-B ID Found!"); return CheckChipType(cmdp); } - ans=EM4x50Read("", false); + ans=EM4x50Read("", false); //ask if (ans>0) { PrintAndLog("\nValid EM4x50 ID Found!"); return 1; @@ -1016,7 +1027,7 @@ int CmdLFfind(const char *Cmd) return CheckChipType(cmdp); } - ans=CmdIndalaDecode(""); + ans=CmdIndalaDecode(""); //psk if (ans>0) { PrintAndLog("\nValid Indala ID Found!"); return CheckChipType(cmdp); @@ -1029,14 +1040,14 @@ int CmdLFfind(const char *Cmd) } PrintAndLog("\nNo Known Tags Found!\n"); - if (testRaw=='u' || testRaw=='U'){ + if (testRaw=='u' || testRaw=='U') { ans=CheckChipType(cmdp); //test unknown tag formats (raw mode)0 PrintAndLog("\nChecking for Unknown tags:\n"); ans=AutoCorrelate(4000, false, false); if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans); ans=GetFskClock("",false,false); - if (ans != 0){ //fsk + if (ans != 0) { //fsk ans=FSKrawDemod("",true); if (ans>0) { PrintAndLog("\nUnknown FSK Modulated Tag Found!"); diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index db450a44..b806f292 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -111,7 +111,7 @@ int NoralsyDemod_AM(uint8_t *dest, size_t *size) { int CmdNoralsyDemod(const char *Cmd) { //ASK / Manchester - bool st = false; + bool st = true; if (!ASKDemod_ext("32 0 0", false, false, 1, &st)) { if (g_debugMode) PrintAndLog("DEBUG: Error - Noralsy: ASK/Manchester Demod failed"); return 0; diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index b287ce28..7999880c 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -24,6 +24,7 @@ #include "data.h" #include "lfdemod.h" #include "cmdhf14a.h" //for getTagInfo +#include "protocols.h" #define T55x7_CONFIGURATION_BLOCK 0x00 #define T55x7_PAGE0 0x00 @@ -78,12 +79,13 @@ int usage_t55xx_read(){ return 0; } int usage_t55xx_write(){ - PrintAndLog("Usage: lf t55xx write [b ] [d ] [p ] [1]"); + PrintAndLog("Usage: lf t55xx write [b ] [d ] [p ] [1] [t]"); PrintAndLog("Options:"); PrintAndLog(" b - block number to write. Between 0-7"); PrintAndLog(" d - 4 bytes of data to write (8 hex characters)"); PrintAndLog(" p - OPTIONAL password 4bytes (8 hex characters)"); PrintAndLog(" 1 - OPTIONAL write Page 1 instead of Page 0"); + PrintAndLog(" t - OPTIONAL test mode write - ****DANGER****"); PrintAndLog(""); PrintAndLog("Examples:"); PrintAndLog(" lf t55xx write b 3 d 11223344 - write 11223344 to block 3"); @@ -138,15 +140,29 @@ int usage_t55xx_detect(){ PrintAndLog(""); return 0; } +int usage_t55xx_detectP1(){ + PrintAndLog("Command: Detect Page 1 of a t55xx chip"); + PrintAndLog("Usage: lf t55xx p1detect [1] [p ]"); + PrintAndLog("Options:"); + PrintAndLog(" 1 - if set, use Graphbuffer otherwise read data from tag."); + PrintAndLog(" p - OPTIONAL password (8 hex characters)"); + PrintAndLog(""); + PrintAndLog("Examples:"); + PrintAndLog(" lf t55xx p1detect"); + PrintAndLog(" lf t55xx p1detect 1"); + PrintAndLog(" lf t55xx p1detect p 11223344"); + PrintAndLog(""); + return 0; +} int usage_t55xx_wakup(){ - PrintAndLog("Usage: lf t55xx wakeup [h] p "); + PrintAndLog("Usage: lf t55xx wakeup [h] "); PrintAndLog("This commands send the Answer-On-Request command and leaves the readerfield ON afterwards."); PrintAndLog("Options:"); PrintAndLog(" h - this help"); - PrintAndLog(" p - password 4bytes (8 hex symbols)"); + PrintAndLog(" - [required] password 4bytes (8 hex symbols)"); PrintAndLog(""); PrintAndLog("Examples:"); - PrintAndLog(" lf t55xx wakeup p 11223344 - send wakeup password"); + PrintAndLog(" lf t55xx wakeup 11223344 - send wakeup password"); return 0; } int usage_t55xx_bruteforce(){ @@ -490,9 +506,10 @@ bool tryDetectModulation(){ uint8_t hits = 0; t55xx_conf_block_t tests[15]; int bitRate=0; - uint8_t fc1 = 0, fc2 = 0, clk=0; - if (GetFskClock("", false, false)){ - fskClocks(&fc1, &fc2, &clk, false); + uint8_t fc1 = 0, fc2 = 0, ans = 0; + int clk=0; + ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, false); + if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { if ( FSKrawDemod("0 0", false) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { tests[hits].modulation = DEMOD_FSK; if (fc1==8 && fc2 == 5) @@ -553,10 +570,8 @@ bool tryDetectModulation(){ ++hits; } } - //undo trim from ask - //save_restoreGB(0); clk = GetNrzClock("", false, false); - if (clk>0) { + if (clk>8) { //clock of rf/8 is likely a false positive, so don't use it. if ( NRZrawDemod("0 0 1", false) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { tests[hits].modulation = DEMOD_NRZ; tests[hits].bitrate = bitRate; @@ -576,12 +591,12 @@ bool tryDetectModulation(){ } } - // allow undo - // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - save_restoreGB(1); - CmdLtrim("160"); clk = GetPskClock("", false, false); if (clk>0) { + // allow undo + save_restoreGB(1); + // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) + CmdLtrim("160"); if ( PSKDemod("0 0 6", false) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { tests[hits].modulation = DEMOD_PSK1; tests[hits].bitrate = bitRate; @@ -622,9 +637,9 @@ bool tryDetectModulation(){ ++hits; } } // inverse waves does not affect this demod + //undo trim samples + save_restoreGB(0); } - //undo trim samples - save_restoreGB(0); } if ( hits == 1) { config.modulation = tests[0].modulation; @@ -780,9 +795,7 @@ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5) // moved test to here, since this gets most faults first. if ( resv > 0x00) continue; - uint8_t xtRate = PackBits(si, 3, DemodBuffer); si += 3; //extended mode part of rate - int bitRate = PackBits(si, 3, DemodBuffer); si += 3; //bit rate - if (bitRate > 7) continue; + int bitRate = PackBits(si, 6, DemodBuffer); si += 6; //bit rate (includes extended mode part of rate) uint8_t extend = PackBits(si, 1, DemodBuffer); si += 1; //bit 15 extended mode uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //could check psk cr @@ -792,12 +805,14 @@ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5) //if extended mode bool extMode =( (safer == 0x6 || safer == 0x9) && extend) ? true : false; - if (!extMode){ - if (xtRate) continue; //nml01 || nml02 || caused issues on noralys tags + if (!extMode) { + if (bitRate > 7) continue; + if (!testBitRate(bitRate, clk)) continue; + } else { //extended mode bitrate = same function to calc bitrate as em4x05 + if (EM4x05_GET_BITRATE(bitRate) != clk) continue; } //test modulation if (!testModulation(mode, modread)) continue; - if (!testBitRate(bitRate, clk)) continue; *fndBitRate = bitRate; *offset = idx; *Q5 = false; @@ -854,7 +869,7 @@ int special(const char *Cmd) { int printConfiguration( t55xx_conf_block_t b){ PrintAndLog("Chip Type : %s", (b.Q5) ? "T5555(Q5)" : "T55x7"); PrintAndLog("Modulation : %s", GetSelectedModulationStr(b.modulation) ); - PrintAndLog("Bit Rate : %s", GetBitRateStr(b.bitrate) ); + PrintAndLog("Bit Rate : %s", GetBitRateStr(b.bitrate, (b.block0 & T55x7_X_MODE)) ); PrintAndLog("Inverted : %s", (b.inverted) ? "Yes" : "No" ); PrintAndLog("Offset : %d", b.offset); PrintAndLog("Seq. Term. : %s", (b.ST) ? "Yes" : "No" ); @@ -865,26 +880,11 @@ int printConfiguration( t55xx_conf_block_t b){ int CmdT55xxWakeUp(const char *Cmd) { uint32_t password = 0; - uint8_t cmdp = 0; - bool errors = true; - while(param_getchar(Cmd, cmdp) != 0x00) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_t55xx_wakup(); - case 'p': - case 'P': - password = param_get32ex(Cmd, cmdp+1, 0xFFFFFFFF, 16); - cmdp += 2; - errors = false; - break; - default: - PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - if (errors) return usage_t55xx_wakup(); + if ( strlen(Cmd) <= 0 ) return usage_t55xx_wakup(); + char cmdp = param_getchar(Cmd, 0); + if ( cmdp == 'h' || cmdp == 'H') return usage_t55xx_wakup(); + + password = param_get32ex(Cmd, 0, 0, 16); UsbCommand c = {CMD_T55XX_WAKEUP, {password, 0, 0}}; clearCommandBuffer(); @@ -900,6 +900,7 @@ int CmdT55xxWriteBlock(const char *Cmd) { bool usepwd = false; bool page1 = false; bool gotdata = false; + bool testMode = false; bool errors = false; uint8_t cmdp = 0; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { @@ -924,6 +925,11 @@ int CmdT55xxWriteBlock(const char *Cmd) { usepwd = true; cmdp += 2; break; + case 't': + case 'T': + testMode = true; + cmdp++; + break; case '1': page1 = true; cmdp++; @@ -944,6 +950,7 @@ int CmdT55xxWriteBlock(const char *Cmd) { UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {data, block, 0}}; UsbCommand resp; c.d.asBytes[0] = (page1) ? 0x2 : 0; + c.d.asBytes[0] |= (testMode) ? 0x4 : 0; char pwdStr[16] = {0}; snprintf(pwdStr, sizeof(pwdStr), "pwd: 0x%08X", password); @@ -1168,7 +1175,7 @@ int CmdT55xxInfo(const char *Cmd){ PrintAndLog("-------------------------------------------------------------"); PrintAndLog(" Safer key : %s", GetSaferStr(safer)); PrintAndLog(" reserved : %d", resv); - PrintAndLog(" Data bit rate : %s", GetBitRateStr(dbr)); + PrintAndLog(" Data bit rate : %s", GetBitRateStr(dbr, extend)); PrintAndLog(" eXtended mode : %s", (extend) ? "Yes - Warning":"No"); PrintAndLog(" Modulation : %s", GetModulationStr(datamod)); PrintAndLog(" PSK clock frequency : %d", pskcf); @@ -1195,7 +1202,7 @@ int CmdT55xxDump(const char *Cmd){ bool override = false; if ( cmdp == 'h' || cmdp == 'H') return usage_t55xx_dump(); - bool usepwd = ( strlen(Cmd) > 0); + bool usepwd = ( strlen(Cmd) > 0); if ( usepwd ){ password = param_get32ex(Cmd, 0, 0, 16); if (param_getchar(Cmd, 1) =='o' ) @@ -1234,20 +1241,24 @@ int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ){ return 1; } -char * GetBitRateStr(uint32_t id) { +char * GetBitRateStr(uint32_t id, bool xmode) { static char buf[25]; char *retStr = buf; - switch (id) { - case 0: snprintf(retStr,sizeof(buf),"%d - RF/8",id); break; - case 1: snprintf(retStr,sizeof(buf),"%d - RF/16",id); break; - case 2: snprintf(retStr,sizeof(buf),"%d - RF/32",id); break; - case 3: snprintf(retStr,sizeof(buf),"%d - RF/40",id); break; - case 4: snprintf(retStr,sizeof(buf),"%d - RF/50",id); break; - case 5: snprintf(retStr,sizeof(buf),"%d - RF/64",id); break; - case 6: snprintf(retStr,sizeof(buf),"%d - RF/100",id); break; - case 7: snprintf(retStr,sizeof(buf),"%d - RF/128",id); break; - default: snprintf(retStr,sizeof(buf),"%d - (Unknown)",id); break; + if (xmode) { //xmode bitrate calc is same as em4x05 calc + snprintf(retStr,sizeof(buf),"%d - RF/%d", id, EM4x05_GET_BITRATE(id)); + } else { + switch (id) { + case 0: snprintf(retStr,sizeof(buf),"%d - RF/8",id); break; + case 1: snprintf(retStr,sizeof(buf),"%d - RF/16",id); break; + case 2: snprintf(retStr,sizeof(buf),"%d - RF/32",id); break; + case 3: snprintf(retStr,sizeof(buf),"%d - RF/40",id); break; + case 4: snprintf(retStr,sizeof(buf),"%d - RF/50",id); break; + case 5: snprintf(retStr,sizeof(buf),"%d - RF/64",id); break; + case 6: snprintf(retStr,sizeof(buf),"%d - RF/100",id); break; + case 7: snprintf(retStr,sizeof(buf),"%d - RF/128",id); break; + default: snprintf(retStr,sizeof(buf),"%d - (Unknown)",id); break; + } } return buf; } @@ -1540,11 +1551,160 @@ int CmdT55xxBruteForce(const char *Cmd) { return 0; } +// note length of data returned is different for different chips. +// some return all page 1 (64 bits) and others return just that block (32 bits) +// unfortunately the 64 bits makes this more likely to get a false positive... +bool tryDetectP1(bool getData) { + uint8_t preamble[] = {1,1,1,0,0,0,0,0,0,0,0,1,0,1,0,1}; + size_t startIdx = 0; + uint8_t fc1 = 0, fc2 = 0, ans = 0; + int clk = 0; + bool st = true; + + if ( getData ) { + if ( !AquireData(T55x7_PAGE1, 1, false, 0) ) + return false; + } + + // try fsk clock detect. if successful it cannot be any other type of modulation... (in theory...) + ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, false); + if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { + if ( FSKrawDemod("0 0", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( FSKrawDemod("0 1", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + return false; + } + + // try psk clock detect. if successful it cannot be any other type of modulation... (in theory...) + clk = GetPskClock("", false, false); + if (clk>0) { + // allow undo + // save_restoreGB(1); + // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) + //CmdLtrim("160"); + if ( PSKDemod("0 0 6", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + if ( PSKDemod("0 1 6", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + // PSK2 - needs a call to psk1TOpsk2. + if ( PSKDemod("0 0 6", false)) { + psk1TOpsk2(DemodBuffer, DemodBufferLen); + if (preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + } // inverse waves does not affect PSK2 demod + //undo trim samples + //save_restoreGB(0); + // no other modulation clocks = 2 or 4 so quit searching + if (fc1 != 8) return false; + } + + // try ask clock detect. it could be another type even if successful. + clk = GetAskClock("", false, false); + if (clk>0) { + if ( ASKDemod_ext("0 0 1", false, false, 1, &st) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + st = true; + if ( ASKDemod_ext("0 1 1", false, false, 1, &st) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( ASKbiphaseDemod("0 0 0 2", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( ASKbiphaseDemod("0 0 1 2", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + } + + // try NRZ clock detect. it could be another type even if successful. + clk = GetNrzClock("", false, false); //has the most false positives :( + if (clk>0) { + if ( NRZrawDemod("0 0 1", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( NRZrawDemod("0 1 1", false) && + preambleSearchEx(DemodBuffer,preamble,sizeof(preamble),&DemodBufferLen,&startIdx,false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + } + return false; +} +// does this need to be a callable command? +int CmdT55xxDetectPage1(const char *Cmd){ + bool errors = false; + bool useGB = false; + bool usepwd = false; + uint32_t password = 0; + uint8_t cmdp = 0; + + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_t55xx_detectP1(); + case 'p': + case 'P': + password = param_get32ex(Cmd, cmdp+1, 0, 16); + usepwd = true; + cmdp += 2; + break; + case '1': + // use Graphbuffer data + useGB = true; + cmdp++; + break; + default: + PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + if (errors) return usage_t55xx_detectP1(); + + if ( !useGB ) { + if ( !AquireData(T55x7_PAGE1, 1, usepwd, password) ) + return false; + } + bool success = tryDetectP1(false); + if (success) PrintAndLog("T55xx chip found!"); + return success; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"bruteforce",CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, {"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."}, + {"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"}, {"read", CmdT55xxReadBlock, 0, "b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"}, {"resetread", CmdResetRead, 0, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"}, {"write", CmdT55xxWriteBlock,0, "b d p [password] [1] -- Write T55xx block data. Optional [p password], [page1]"}, diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 5c2ec79d..4f0fd21d 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -36,18 +36,18 @@ typedef struct { typedef struct { enum { - DEMOD_NRZ = 0x00, + DEMOD_NRZ = 0x00, DEMOD_PSK1 = 0x01, DEMOD_PSK2 = 0x02, DEMOD_PSK3 = 0x03, - DEMOD_FSK1 = 0x04, - DEMOD_FSK1a = 0x05, - DEMOD_FSK2 = 0x06, + DEMOD_FSK1 = 0x04, + DEMOD_FSK1a = 0x05, + DEMOD_FSK2 = 0x06, DEMOD_FSK2a = 0x07, DEMOD_FSK = 0xF0, //generic FSK (auto detect FCs) DEMOD_ASK = 0x08, DEMOD_BI = 0x10, - DEMOD_BIa = 0x18, + DEMOD_BIa = 0x18 } modulation; bool inverted; uint8_t offset; @@ -60,27 +60,27 @@ typedef struct { RF_50 = 0x04, RF_64 = 0x05, RF_100 = 0x06, - RF_128 = 0x07, + RF_128 = 0x07 } bitrate; bool Q5; bool ST; } t55xx_conf_block_t; -t55xx_conf_block_t Get_t55xx_Config(); -void Set_t55xx_Config(t55xx_conf_block_t conf); +t55xx_conf_block_t Get_t55xx_Config(void); +void Set_t55xx_Config(t55xx_conf_block_t conf); -int CmdLFT55XX(const char *Cmd); -int CmdT55xxBruteForce(const char *Cmd); -int CmdT55xxSetConfig(const char *Cmd); -int CmdT55xxReadBlock(const char *Cmd); -int CmdT55xxWriteBlock(const char *Cmd); -int CmdT55xxReadTrace(const char *Cmd); -int CmdT55xxInfo(const char *Cmd); -int CmdT55xxDetect(const char *Cmd); -int CmdResetRead(const char *Cmd); -int CmdT55xxWipe(const char *Cmd); +extern int CmdLFT55XX(const char *Cmd); +extern int CmdT55xxBruteForce(const char *Cmd); +extern int CmdT55xxSetConfig(const char *Cmd); +extern int CmdT55xxReadBlock(const char *Cmd); +extern int CmdT55xxWriteBlock(const char *Cmd); +extern int CmdT55xxReadTrace(const char *Cmd); +extern int CmdT55xxInfo(const char *Cmd); +extern int CmdT55xxDetect(const char *Cmd); +extern int CmdResetRead(const char *Cmd); +extern int CmdT55xxWipe(const char *Cmd); -char * GetBitRateStr(uint32_t id); +char * GetBitRateStr(uint32_t id, bool xmode); char * GetSaferStr(uint32_t id); char * GetModulationStr( uint32_t id); char * GetModelStrFromCID(uint32_t cid); @@ -90,8 +90,9 @@ void printT5xxHeader(uint8_t page); void printT55xxBlock(const char *demodStr); int printConfiguration( t55xx_conf_block_t b); -bool DecodeT55xxBlock(); -bool tryDetectModulation(); +bool DecodeT55xxBlock(void); +bool tryDetectModulation(void); +extern bool tryDetectP1(bool getData); bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5); int special(const char *Cmd); int AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ); diff --git a/client/graph.c b/client/graph.c index 995a32da..12f5ff71 100644 --- a/client/graph.c +++ b/client/graph.c @@ -150,7 +150,7 @@ int GetAskClock(const char str[], bool printAns, bool verbose) start = DetectASKClock(grph, size, &clock, 20); } // Only print this message if we're not looping something - if (printAns) { + if (printAns || g_debugMode) { PrintAndLog("Auto-detected clock rate: %d, Best Starting Position: %d", clock, start); } return clock; @@ -166,11 +166,12 @@ uint8_t GetPskCarrier(const char str[], bool printAns, bool verbose) PrintAndLog("Failed to copy from graphbuffer"); return 0; } - //uint8_t countPSK_FC(uint8_t *BitStream, size_t size) - - carrier = countFC(grph,size,0); + uint16_t fc = countFC(grph,size,0); + carrier = fc & 0xFF; + if (carrier != 2 && carrier != 4 && carrier != 8) return 0; + if ((fc>>8) == 10 && carrier == 8) return 0; // Only print this message if we're not looping something - if (printAns){ + if (printAns) { PrintAndLog("Auto-detected PSK carrier rate: %d", carrier); } return carrier; @@ -193,7 +194,9 @@ int GetPskClock(const char str[], bool printAns, bool verbose) PrintAndLog("Failed to copy from graphbuffer"); return -1; } - clock = DetectPSKClock(grph,size,0); + size_t firstPhaseShiftLoc = 0; + uint8_t curPhase = 0, fc = 0; + clock = DetectPSKClock(grph, size, 0, &firstPhaseShiftLoc, &curPhase, &fc); // Only print this message if we're not looping something if (printAns){ PrintAndLog("Auto-detected clock rate: %d", clock); diff --git a/client/util.c b/client/util.c index d4e59165..593eaa52 100644 --- a/client/util.c +++ b/client/util.c @@ -169,7 +169,7 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea size_t in_index = 0; // loop through the out_index to make sure we don't go too far - for (size_t out_index=0; out_index < max_len-1; out_index++) { + for (size_t out_index=0; out_index < max_len; out_index++) { // set character - (should be binary but verify it isn't more than 1 digit) if (data[in_index]<10) sprintf(tmp++, "%u", (unsigned int) data[in_index]); diff --git a/common/lfdemod.c b/common/lfdemod.c index c56301c0..6beef130 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -33,6 +33,7 @@ //----------------------------------------------------------------------------- #include // for memset, memcmp and size_t +#include "lfdemod.h" #include // for uint_32+ #include // for bool #include "parity.h" // for parity test @@ -277,6 +278,33 @@ bool loadWaveCounters(uint8_t samples[], size_t size, int lowToLowWaveLen[], int return true; } +size_t pskFindFirstPhaseShift(uint8_t samples[], size_t size, uint8_t *curPhase, size_t waveStart, uint16_t fc, uint16_t *fullWaveLen) { + uint16_t loopCnt = (size+3 < 4096) ? size : 4096; //don't need to loop through entire array... + + uint16_t avgWaveVal=0, lastAvgWaveVal=0; + size_t i = waveStart, waveEnd, waveLenCnt, firstFullWave; + for (; i= samples[i+2]){ + waveEnd = i+1; + if (g_debugMode == 2) prnt("DEBUG PSK: waveEnd: %u, waveStart: %u", waveEnd, waveStart); + waveLenCnt = waveEnd-waveStart; + if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+8)){ //not first peak and is a large wave but not out of whack + lastAvgWaveVal = avgWaveVal/(waveLenCnt); + firstFullWave = waveStart; + *fullWaveLen = waveLenCnt; + //if average wave value is > graph 0 then it is an up wave or a 1 (could cause inverting) + if (lastAvgWaveVal > FSK_PSK_THRESHOLD) *curPhase ^= 1; + return firstFullWave; + } + waveStart = i+1; + avgWaveVal = 0; + } + avgWaveVal += samples[i+2]; + } + return 0; +} + //by marshmellow //amplify based on ask edge detection - not accurate enough to use all the time void askAmp(uint8_t *BitStream, size_t size) { @@ -520,7 +548,7 @@ int DetectNRZClock(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx //get high and low peak int peak, low; - if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return 0; + if (getHiLo(dest, loopCnt, &peak, &low, 90, 90) < 1) return 0; int lowestTransition = DetectStrongNRZClk(dest, size-20, peak, low); size_t ii; @@ -529,26 +557,24 @@ int DetectNRZClock(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx uint16_t smplCnt = 0; int16_t peakcnt = 0; int16_t peaksdet[] = {0,0,0,0,0,0,0,0}; - uint16_t maxPeak = 255; - bool firstpeak = false; - //test for large clipped waves - for (i=0; i= peak || dest[i] <= low){ - if (!firstpeak) continue; + uint16_t minPeak = 255; + bool firstpeak = true; + //test for large clipped waves - ignore first peak + for (i=0; i= peak || dest[i] <= low) { + if (firstpeak) continue; smplCnt++; } else { - firstpeak=true; - if (smplCnt > 6 ){ - if (maxPeak > smplCnt){ - maxPeak = smplCnt; - //prnt("maxPk: %d",maxPeak); - } + firstpeak = false; + if (smplCnt > 0) { + if (minPeak > smplCnt && smplCnt > 7) minPeak = smplCnt; peakcnt++; - //prnt("maxPk: %d, smplCnt: %d, peakcnt: %d",maxPeak,smplCnt,peakcnt); - smplCnt=0; + if (g_debugMode == 2) prnt("DEBUG NRZ: minPeak: %d, smplCnt: %d, peakcnt: %d",minPeak,smplCnt,peakcnt); + smplCnt = 0; } } } + if (minPeak < 8) return 0; bool errBitHigh = 0; bool bitHigh = 0; uint8_t ignoreCnt = 0; @@ -558,12 +584,12 @@ int DetectNRZClock(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx size_t bestStart[]={0,0,0,0,0,0,0,0,0}; peakcnt=0; //test each valid clock from smallest to greatest to see which lines up - for(clkCnt=0; clkCnt < 8; ++clkCnt){ + for(clkCnt=0; clkCnt < 8; ++clkCnt) { //ignore clocks smaller than smallest peak - if (clk[clkCnt] < maxPeak - (clk[clkCnt]/4)) continue; + if (clk[clkCnt] < minPeak - (clk[clkCnt]/4)) continue; //try lining up the peaks by moving starting point (try first 256) - for (ii=20; ii < loopCnt; ++ii){ - if ((dest[ii] >= peak) || (dest[ii] <= low)){ + for (ii=20; ii < loopCnt; ++ii) { + if ((dest[ii] >= peak) || (dest[ii] <= low)) { peakcnt = 0; bitHigh = false; ignoreCnt = 0; @@ -587,8 +613,8 @@ int DetectNRZClock(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx lastBit += clk[clkCnt]; } //else if not a clock bit and no peaks - } else if (dest[i] < peak && dest[i] > low){ - if (ignoreCnt==0){ + } else if (dest[i] < peak && dest[i] > low) { + if (ignoreCnt==0) { bitHigh=false; if (errBitHigh==true) peakcnt--; errBitHigh=false; @@ -610,15 +636,15 @@ int DetectNRZClock(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx } int iii=7; uint8_t best=0; - for (iii=7; iii > 0; iii--){ + for (iii=7; iii > 0; iii--) { if ((peaksdet[iii] >= (peaksdet[best]-1)) && (peaksdet[iii] <= peaksdet[best]+1) && lowestTransition) { if (clk[iii] > (lowestTransition - (clk[iii]/8)) && clk[iii] < (lowestTransition + (clk[iii]/8))) { best = iii; } - } else if (peaksdet[iii] > peaksdet[best]){ + } else if (peaksdet[iii] > peaksdet[best]) { best = iii; } - if (g_debugMode==2) prnt("DEBUG NRZ: Clk: %d, peaks: %d, maxPeak: %d, bestClk: %d, lowestTrs: %d",clk[iii],peaksdet[iii],maxPeak, clk[best], lowestTransition); + if (g_debugMode==2) prnt("DEBUG NRZ: Clk: %d, peaks: %d, minPeak: %d, bestClk: %d, lowestTrs: %d",clk[iii],peaksdet[iii],minPeak, clk[best], lowestTransition); } *clockStartIdx = bestStart[best]; return clk[best]; @@ -691,6 +717,7 @@ uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj) { best3=i; } if (g_debugMode==2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u",fcLens[i],fcCnts[i],fcLens[best1],fcLens[best2]); + if (fcLens[i]==0) break; } if (fcLens[best1]==0) return 0; uint8_t fcH=0, fcL=0; @@ -708,18 +735,24 @@ uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj) { // TODO: take top 3 answers and compare to known Field clocks to get top 2 uint16_t fcs = (((uint16_t)fcH)<<8) | fcL; - if (fskAdj) return fcs; - return fcLens[best1]; + if (fskAdj) return fcs; + return (uint16_t)fcLens[best2] << 8 | fcLens[best1]; } //by marshmellow //detect psk clock by reading each phase shift // a phase shift is determined by measuring the sample length of each wave -int DetectPSKClock_ext(uint8_t dest[], size_t size, int clock, int *firstPhaseShift) { +int DetectPSKClock(uint8_t dest[], size_t size, int clock, size_t *firstPhaseShift, uint8_t *curPhase, uint8_t *fc) { uint8_t clk[]={255,16,32,40,50,64,100,128,255}; //255 is not a valid clock uint16_t loopCnt = 4096; //don't need to loop through entire array... if (size == 0) return 0; - if (size>8); + if ((fcs>>8) == 10 && *fc == 8) return -1; + if (*fc!=2 && *fc!=4 && *fc!=8) return -1; //if we already have a valid clock quit size_t i=1; @@ -727,37 +760,28 @@ int DetectPSKClock_ext(uint8_t dest[], size_t size, int clock, int *firstPhaseSh if (clk[i] == clock) return clock; size_t waveStart=0, waveEnd=0, firstFullWave=0, lastClkBit=0; - uint8_t clkCnt, fc=0, fullWaveLen=0, tol=1; - uint16_t peakcnt=0, errCnt=0, waveLenCnt=0; + + uint8_t clkCnt, tol=1; + uint16_t peakcnt=0, errCnt=0, waveLenCnt=0, fullWaveLen=0; uint16_t bestErr[]={1000,1000,1000,1000,1000,1000,1000,1000,1000}; uint16_t peaksdet[]={0,0,0,0,0,0,0,0,0}; - fc = countFC(dest, size, 0); - if (fc!=2 && fc!=4 && fc!=8) return -1; - if (g_debugMode==2) prnt("DEBUG PSK: FC: %d",fc); - //find first full wave - for (i=160; i= dest[i+2]){ - if (waveStart == 0) { - waveStart = i+1; - //prnt("DEBUG: waveStart: %d",waveStart); - } else { - waveEnd = i+1; - //prnt("DEBUG: waveEnd: %d",waveEnd); - waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > fc){ - firstFullWave = waveStart; - fullWaveLen=waveLenCnt; - break; - } - waveStart=0; - } - } + //find start of modulating data in trace + i = findModStart(dest, size, *fc); + + firstFullWave = pskFindFirstPhaseShift(dest, size, curPhase, i, *fc, &fullWaveLen); + if (firstFullWave == 0) { + // no phase shift detected - could be all 1's or 0's - doesn't matter where we start + // so skip a little to ensure we are past any Start Signal + firstFullWave = 160; + fullWaveLen = 0; } + *firstPhaseShift = firstFullWave; if (g_debugMode ==2) prnt("DEBUG PSK: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen); //test each valid clock from greatest to smallest to see which lines up - for(clkCnt=7; clkCnt >= 1 ; clkCnt--){ + for(clkCnt=7; clkCnt >= 1 ; clkCnt--) { + tol = *fc/2; lastClkBit = firstFullWave; //set end of wave as clock align waveStart = 0; errCnt=0; @@ -773,9 +797,9 @@ int DetectPSKClock_ext(uint8_t dest[], size_t size, int clock, int *firstPhaseSh } else { //waveEnd waveEnd = i+1; waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > fc){ + if (waveLenCnt > *fc){ //if this wave is a phase shift - if (g_debugMode == 2) prnt("DEBUG PSK: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+clk[clkCnt]-tol,i+1,fc); + if (g_debugMode == 2) prnt("DEBUG PSK: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+clk[clkCnt]-tol,i+1,*fc); if (i+1 >= lastClkBit + clk[clkCnt] - tol){ //should be a clock bit peakcnt++; lastClkBit+=clk[clkCnt]; @@ -784,7 +808,7 @@ int DetectPSKClock_ext(uint8_t dest[], size_t size, int clock, int *firstPhaseSh } else { //phase shift before supposed to based on clock errCnt++; } - } else if (i+1 > lastClkBit + clk[clkCnt] + tol + fc){ + } else if (i+1 > lastClkBit + clk[clkCnt] + tol + *fc){ lastClkBit+=clk[clkCnt]; //no phase shift but clock bit } waveStart=i+1; @@ -809,10 +833,11 @@ int DetectPSKClock_ext(uint8_t dest[], size_t size, int clock, int *firstPhaseSh return clk[best]; } -int DetectPSKClock(uint8_t dest[], size_t size, int clock) { - int firstPhaseShift = 0; - return DetectPSKClock_ext(dest, size, clock, &firstPhaseShift); -} +//int DetectPSKClock(uint8_t dest[], size_t size, int clock) { +// size_t firstPhaseShift = 0; +// uint8_t curPhase = 0; +// return DetectPSKClock_ext(dest, size, clock, &firstPhaseShift, &curPhase); +//} //by marshmellow //detects the bit clock for FSK given the high and low Field Clocks @@ -933,6 +958,8 @@ uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fc // look for Sequence Terminator - should be pulses of clk*(1 or 2), clk*2, clk*(1.5 or 2), by idx we mean graph position index... bool findST(int *stStopLoc, int *stStartIdx, int lowToLowWaveLen[], int highToLowWaveLen[], int clk, int tol, int buffSize, size_t *i) { + if (buffSize < *i+4) return false; + for (; *i < buffSize - 4; *i+=1) { *stStartIdx += lowToLowWaveLen[*i]; //caution part of this wave may be data and part may be ST.... to be accounted for in main function for now... if (lowToLowWaveLen[*i] >= clk*1-tol && lowToLowWaveLen[*i] <= (clk*2)+tol && highToLowWaveLen[*i] < clk+tol) { //1 to 2 clocks depending on 2 bits prior @@ -955,7 +982,7 @@ bool DetectST_ext(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststa //need to loop through all samples and identify our clock, look for the ST pattern int clk = 0; int tol = 0; - int j, high, low, skip, start, end, minClk=255; + int j=0, high, low, skip=0, start=0, end=0, minClk=255; size_t i = 0; //probably should malloc... || test if memory is available ... handle device side? memory danger!!! [marshmellow] int tmpbuff[bufsize / LOWEST_DEFAULT_CLOCK]; // low to low wave count //guess rf/32 clock, if click is smaller we will only have room for a fraction of the samples captured @@ -1023,9 +1050,9 @@ bool DetectST_ext(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststa return false; } size_t dataloc = start; - if (buffer[dataloc-(clk*4)-(clk/8)] <= low && buffer[dataloc] <= low && buffer[dataloc-(clk*4)] >= high) { + if (buffer[dataloc-(clk*4)-(clk/4)] <= low && buffer[dataloc] <= low && buffer[dataloc-(clk*4)] >= high) { //we have low drift (and a low just before the ST and a low just after the ST) - compensate by backing up the start - for ( i=0; i <= (clk/8); ++i ) { + for ( i=0; i <= (clk/4); ++i ) { if ( buffer[dataloc - (clk*4) - i] <= low ) { dataloc -= i; break; @@ -1040,14 +1067,15 @@ bool DetectST_ext(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststa // warning - overwriting buffer given with raw wave data with ST removed... while ( dataloc < bufsize-(clk/2) ) { //compensate for long high at end of ST not being high due to signal loss... (and we cut out the start of wave high part) - if (buffer[dataloc]low && buffer[dataloc+3]low) { + if (buffer[dataloc]low && buffer[dataloc+clk/4]low) { for(i=0; i < clk/2-tol; ++i) { buffer[dataloc+i] = high+5; } - } //test for single sample outlier (high between two lows) in the case of very strong waves - if (buffer[dataloc] >= high && buffer[dataloc+2] <= low) { - buffer[dataloc] = buffer[dataloc+2]; - buffer[dataloc+1] = buffer[dataloc+2]; + } //test for small spike outlier (high between two lows) in the case of very strong waves + if (buffer[dataloc] > low && buffer[dataloc+clk/4] <= low) { + for(i=0; i < clk/4; ++i) { + buffer[dataloc+i] = buffer[dataloc+clk/4]; + } } if (firstrun) { *stend = dataloc; @@ -1521,60 +1549,34 @@ void psk2TOpsk1(uint8_t *BitStream, size_t size) { return; } -size_t pskFindFirstPhaseShift(uint8_t samples[], size_t size, uint8_t *curPhase, size_t waveStart, uint16_t fc, uint16_t *fullWaveLen) { - uint16_t loopCnt = (size+3 < 4096) ? size : 4096; //don't need to loop through entire array... - - uint16_t avgWaveVal=0, lastAvgWaveVal=0; - size_t i = waveStart, waveEnd, waveLenCnt, firstFullWave; - for (; i= samples[i+2]){ - waveEnd = i+1; - if (g_debugMode == 2) prnt("DEBUG PSK: waveEnd: %u, waveStart: %u", waveEnd, waveStart); - waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+8)){ //not first peak and is a large wave but not out of whack - lastAvgWaveVal = avgWaveVal/(waveLenCnt); - firstFullWave = waveStart; - *fullWaveLen = waveLenCnt; - //if average wave value is > graph 0 then it is an up wave or a 1 (could cause inverting) - if (lastAvgWaveVal > FSK_PSK_THRESHOLD) *curPhase ^= 1; - return firstFullWave; - } - waveStart = i+1; - avgWaveVal = 0; - } - avgWaveVal += samples[i+2]; - } - return 0; -} - //by marshmellow - demodulate PSK1 wave //uses wave lengths (# Samples) int pskRawDemod_ext(uint8_t dest[], size_t *size, int *clock, int *invert, int *startIdx) { if (*size < 170) return -1; uint8_t curPhase = *invert; + uint8_t fc=0; size_t i=0, numBits=0, waveStart=1, waveEnd=0, firstFullWave=0, lastClkBit=0; - uint16_t fc=0, fullWaveLen=0, waveLenCnt=0, avgWaveVal, tol=1; + uint16_t fullWaveLen=0, waveLenCnt=0, avgWaveVal; uint16_t errCnt=0, errCnt2=0; - fc = countFC(dest, *size, 1); - if ((fc >> 8) == 10) return -1; //fsk found - quit - fc = fc & 0xFF; - if (fc!=2 && fc!=4 && fc!=8) return -1; - *clock = DetectPSKClock(dest, *size, *clock); + *clock = DetectPSKClock(dest, *size, *clock, &firstFullWave, &curPhase, &fc); if (*clock == 0) return -1; - - //find start of modulating data in trace - i = findModStart(dest, *size, fc); - - //find first phase shift - firstFullWave = pskFindFirstPhaseShift(dest, *size, &curPhase, i, fc, &fullWaveLen); + //if clock detect found firstfullwave... + uint16_t tol = fc/2; if (firstFullWave == 0) { - // no phase shift detected - could be all 1's or 0's - doesn't matter where we start - // so skip a little to ensure we are past any Start Signal - firstFullWave = 160; - memset(dest, curPhase, firstFullWave / *clock); + //find start of modulating data in trace + i = findModStart(dest, *size, fc); + //find first phase shift + firstFullWave = pskFindFirstPhaseShift(dest, *size, &curPhase, i, fc, &fullWaveLen); + if (firstFullWave == 0) { + // no phase shift detected - could be all 1's or 0's - doesn't matter where we start + // so skip a little to ensure we are past any Start Signal + firstFullWave = 160; + memset(dest, curPhase, firstFullWave / *clock); + } else { + memset(dest, curPhase^1, firstFullWave / *clock); + } } else { memset(dest, curPhase^1, firstFullWave / *clock); } @@ -1587,9 +1589,9 @@ int pskRawDemod_ext(uint8_t dest[], size_t *size, int *clock, int *invert, int * if (g_debugMode==2) prnt("DEBUG PSK: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit,(unsigned int) fc); waveStart = 0; dest[numBits++] = curPhase; //set first read bit - for (i = firstFullWave + fullWaveLen - 1; i < *size-3; i++){ + for (i = firstFullWave + fullWaveLen - 1; i < *size-3; i++) { //top edge of wave = start of new wave - if (dest[i]+fc < dest[i+1] && dest[i+1] >= dest[i+2]){ + if (dest[i]+fc < dest[i+1] && dest[i+1] >= dest[i+2]) { if (waveStart == 0) { waveStart = i+1; waveLenCnt = 0; @@ -1597,25 +1599,27 @@ int pskRawDemod_ext(uint8_t dest[], size_t *size, int *clock, int *invert, int * } else { //waveEnd waveEnd = i+1; waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > fc){ + if (waveLenCnt > fc) { //this wave is a phase shift //PrintAndLog("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+*clock-tol,i+1,fc); - if (i+1 >= lastClkBit + *clock - tol){ //should be a clock bit + if (i+1 >= lastClkBit + *clock - tol) { //should be a clock bit curPhase ^= 1; dest[numBits++] = curPhase; lastClkBit += *clock; - } else if (i < lastClkBit+10+fc){ + } else if (i < lastClkBit+10+fc) { //noise after a phase shift - ignore } else { //phase shift before supposed to based on clock errCnt++; dest[numBits++] = 7; } - } else if (i+1 > lastClkBit + *clock + tol + fc){ + } else if (i+1 > lastClkBit + *clock + tol + fc) { lastClkBit += *clock; //no phase shift but clock bit dest[numBits++] = curPhase; } else if (waveLenCnt < fc - 1) { //wave is smaller than field clock (shouldn't happen often) errCnt2++; if(errCnt2 > 101) return errCnt2; + avgWaveVal += dest[i+1]; + continue; } avgWaveVal = 0; waveStart = i+1; @@ -1800,7 +1804,7 @@ int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert) { } if (*size != 64 && *size != 224) return -2; if (*invert==1) - for (size_t i = startidx; i < *size; i++) + for (size_t i = startidx; i < *size + startidx; i++) bitStream[i] ^= 1; return (int) startidx; diff --git a/common/lfdemod.h b/common/lfdemod.h index a881fa18..697b78cb 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -30,8 +30,7 @@ extern uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, uint8_t high, ui extern uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow); extern uint8_t detectFSKClk_ext(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge); extern int DetectNRZClock(uint8_t dest[], size_t size, int clock, size_t *clockStartIdx); -extern int DetectPSKClock(uint8_t dest[], size_t size, int clock); -extern int DetectPSKClock_ext(uint8_t dest[], size_t size, int clock, int *firstPhaseShift); +extern int DetectPSKClock(uint8_t dest[], size_t size, int clock, size_t *firstPhaseShift, uint8_t *curPhase, uint8_t *fc); extern int DetectStrongAskClock(uint8_t dest[], size_t size, int high, int low, int *clock); extern bool DetectST(uint8_t buffer[], size_t *size, int *foundclock); extern bool DetectST_ext(uint8_t buffer[], size_t *size, int *foundclock, size_t *ststart, size_t *stend); @@ -42,7 +41,7 @@ extern uint32_t manchesterEncode2Bytes(uint16_t datain); extern int ManchesterEncode(uint8_t *BitStream, size_t size); extern int manrawdecode(uint8_t *BitStream, size_t *size, uint8_t invert, uint8_t *alignPos); extern int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx); -extern uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType); +extern bool parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType); extern uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx); extern bool preambleSearchEx(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone); extern int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert); diff --git a/common/protocols.h b/common/protocols.h index bb888d3d..31252ad3 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -238,6 +238,7 @@ void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t * #define T55x7_MODULATION_MANCHESTER 0x00008000 #define T55x7_MODULATION_BIPHASE 0x00010000 #define T55x7_MODULATION_DIPHASE 0x00018000 +#define T55x7_X_MODE 0x00020000 #define T55x7_BITRATE_RF_8 0 #define T55x7_BITRATE_RF_16 0x00040000 #define T55x7_BITRATE_RF_32 0x00080000