X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/643fb10b2df5248f830f0a9e3d8ae43b24e1c2b2..b7eddc14db9262a51ad3100ade7386d03500ace8:/client/cmdlfem4x.c?ds=inline

diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c
index 47a5ac3e..eddeec56 100644
--- a/client/cmdlfem4x.c
+++ b/client/cmdlfem4x.c
@@ -20,6 +20,9 @@
 #include "cmdlf.h"
 #include "cmdlfem4x.h"
 #include "lfdemod.h"
+
+#define llx PRIx64
+
 char *global_em410xId;
 
 static int CmdHelp(const char *Cmd);
@@ -27,7 +30,7 @@ static int CmdHelp(const char *Cmd);
 int CmdEMdemodASK(const char *Cmd)
 {
 	char cmdp = param_getchar(Cmd, 0);
-	int findone = (cmdp == '1') ? 1 : 0;	
+	int findone = (cmdp == '1') ? 1 : 0;
 	UsbCommand c={CMD_EM410X_DEMOD};
 	c.arg[0]=findone;
 	SendCommand(&c);
@@ -47,7 +50,7 @@ int CmdEM410xRead(const char *Cmd)
 	uint32_t hi=0;
 	uint64_t lo=0;
 
-	if(!AskEm410xDemod("", &hi, &lo)) return 0;
+	if(!AskEm410xDemod("", &hi, &lo, false)) return 0;
 	PrintAndLog("EM410x pattern found: ");
 	printEM410x(hi, lo);
 	if (hi){
@@ -140,7 +143,6 @@ int CmdEM410xSim(const char *Cmd)
  *       rate gets lower, then grow the number of samples
  *  Changed by martin, 4000 x 4 = 16000, 
  *  see http://www.proxmark.org/forum/viewtopic.php?pid=7235#p7235
-
 */
 int CmdEM410xWatch(const char *Cmd)
 {
@@ -151,7 +153,7 @@ int CmdEM410xWatch(const char *Cmd)
 		}
 		
 		CmdLFRead("s");
-		getSamples("8192",true); //capture enough to get 2 full messages		
+		getSamples("8201",true); //capture enough to get 2 complete preambles (4096*2+9)	
 	} while (!CmdEM410xRead(""));
 
 	return 0;
@@ -238,7 +240,7 @@ bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t col
 {
 	if (rows*cols>size) return false;
 	uint8_t colP=0;
-	//assume last row is a parity row and do not test
+	//assume last col is a parity and do not test
 	for (uint8_t colNum = 0; colNum < cols-1; colNum++) {
 		for (uint8_t rowNum = 0; rowNum < rows; rowNum++) {
 			colP ^= BitStream[(rowNum*cols)+colNum];
@@ -271,7 +273,7 @@ uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool
 	code = code<<8 | bytebits_to_byte(BitStream+27,8);
 	if (verbose || g_debugMode){
 		for (uint8_t i = 0; i<5; i++){
-			if (i == 4) PrintAndLog("");
+			if (i == 4) PrintAndLog(""); //parity byte spacer
 			PrintAndLog("%d%d%d%d%d%d%d%d %d -> 0x%02x",
 			    BitStream[i*9],
 			    BitStream[i*9+1],
@@ -290,7 +292,6 @@ uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool
 		else
 			PrintAndLog("Parity Failed");
 	}
-	//PrintAndLog("Code: %08x",code);
 	return code;
 }
 /* Read the transmitted data of an EM4x50 tag
@@ -312,95 +313,106 @@ uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool
  * is stored in the blocks defined in the control word First and Last
  * Word Read values. UID is stored in block 32.
  */
+ //completed by Marshmellow
 int EM4x50Read(const char *Cmd, bool verbose)
 {
-	uint8_t fndClk[]={0,8,16,32,40,50,64};
+	uint8_t fndClk[] = {8,16,32,40,50,64,128};
 	int clk = 0; 
 	int invert = 0;
-	sscanf(Cmd, "%i %i", &clk, &invert);
 	int tol = 0;
 	int i, j, startblock, skip, block, start, end, low, high, minClk;
-	bool complete= false;
+	bool complete = false;
 	int tmpbuff[MAX_GRAPH_TRACE_LEN / 64];
-	save_restoreGB(1);
 	uint32_t Code[6];
 	char tmp[6];
-
 	char tmp2[20];
-	high= low= 0;
+	int phaseoff;
+	high = low = 0;
 	memset(tmpbuff, 0, MAX_GRAPH_TRACE_LEN / 64);
-		
+
+	// get user entry if any
+	sscanf(Cmd, "%i %i", &clk, &invert);
+	
+	// save GraphBuffer - to restore it later	
+	save_restoreGB(1);
+
 	// first get high and low values
-	for (i = 0; i < GraphTraceLen; i++)
-	{
+	for (i = 0; i < GraphTraceLen; i++) {
 		if (GraphBuffer[i] > high)
 			high = GraphBuffer[i];
 		else if (GraphBuffer[i] < low)
 			low = GraphBuffer[i];
 	}
 
-	// populate a buffer with pulse lengths
-	i= 0;
-	j= 0;
-	minClk= 255;
-	while (i < GraphTraceLen)
-	{
+	i = 0;
+	j = 0;
+	minClk = 255;
+	// get to first full low to prime loop and skip incomplete first pulse
+	while ((GraphBuffer[i] < high) && (i < GraphTraceLen))
+		++i;
+	while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
+		++i;
+	skip = i;
+
+	// populate tmpbuff buffer with pulse lengths
+	while (i < GraphTraceLen) {
 		// measure from low to low
-		while ((GraphBuffer[i] > low) && (i<GraphTraceLen))
+		while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
 			++i;
 		start= i;
-		while ((GraphBuffer[i] < high) && (i<GraphTraceLen))
+		while ((GraphBuffer[i] < high) && (i < GraphTraceLen))
 			++i;
-		while ((GraphBuffer[i] > low) && (i<GraphTraceLen))
+		while ((GraphBuffer[i] > low) && (i < GraphTraceLen))
 			++i;
 		if (j>=(MAX_GRAPH_TRACE_LEN/64)) {
 			break;
 		}
 		tmpbuff[j++]= i - start;
-		if (i-start < minClk) minClk = i-start;
+		if (i-start < minClk && i < GraphTraceLen) {
+			minClk = i - start;
+		}
 	}
 	// set clock
-	if (!clk){
+	if (!clk) {
 		for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) {
 			tol = fndClk[clkCnt]/8;
-			if (fndClk[clkCnt]-tol >= minClk) { 
+			if (minClk >= fndClk[clkCnt]-tol && minClk <= fndClk[clkCnt]+1) { 
 				clk=fndClk[clkCnt];
 				break;
 			}
 		}
+		if (!clk) return 0;
 	} else tol = clk/8;
 
 	// look for data start - should be 2 pairs of LW (pulses of clk*3,clk*2)
-	start= -1;
-	skip= 0;
-	for (i= 0; i < j - 4 ; ++i)
-	{
+	start = -1;
+	for (i= 0; i < j - 4 ; ++i) {
 		skip += tmpbuff[i];
-		if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol)
-			if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol)
-				if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol)
-					if (tmpbuff[i+3] >= clk-tol)
+		if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol)  //3 clocks
+			if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol)  //2 clocks
+				if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks
+					if (tmpbuff[i+3] >= clk-tol)  //1.5 to 2 clocks - depends on bit following
 					{
 						start= i + 4;
 						break;
 					}
 	}
-	startblock= i + 4;
+	startblock = i + 4;
 
 	// skip over the remainder of LW
-	skip += tmpbuff[i+1] + tmpbuff[i+2] + clk + clk/8;
-	
-	int phaseoff = tmpbuff[i+3]-clk;
-
+	skip += tmpbuff[i+1] + tmpbuff[i+2] + clk;
+	if (tmpbuff[i+3]>clk) 
+		phaseoff = tmpbuff[i+3]-clk;
+	else
+		phaseoff = 0;
 	// now do it again to find the end
 	end = skip;
-	for (i += 3; i < j - 4 ; ++i)
-	{
+	for (i += 3; i < j - 4 ; ++i) {
 		end += tmpbuff[i];
-		if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3 + tol)
-			if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2 + tol)
-				if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3 + tol)
-					if (tmpbuff[i+3] >= clk-tol)
+		if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol)  //3 clocks
+			if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol)  //2 clocks
+				if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks
+					if (tmpbuff[i+3] >= clk-tol)  //1.5 to 2 clocks - depends on bit following
 					{
 						complete= true;
 						break;
@@ -410,51 +422,46 @@ int EM4x50Read(const char *Cmd, bool verbose)
 	// report back
 	if (verbose || g_debugMode) {
 		if (start >= 0) {
-			PrintAndLog("\nNote: should print 45 bits then 0177 (end of block)");
-			PrintAndLog("      for each block");
-			PrintAndLog("      Also, sometimes the demod gets out of sync and ");
-			PrintAndLog("      inverts the output - when this happens the 0177");
-			PrintAndLog("      will be 3 extra 1's at the end");
-			PrintAndLog("        'data askedge' command may fix that");
+			PrintAndLog("\nNote: one block = 50 bits (32 data, 12 parity, 6 marker)");
 		}	else {
-			PrintAndLog("No data found!");
+			PrintAndLog("No data found!, clock tried:%d",clk);
 			PrintAndLog("Try again with more samples.");
+			PrintAndLog("  or after a 'data askedge' command to clean up the read");
 			return 0;
 		}
-		if (!complete)
-		{
-			PrintAndLog("*** Warning!");
-			PrintAndLog("Partial data - no end found!");
-			PrintAndLog("Try again with more samples.");
-		}
 	} else if (start < 0) return 0;
-	start=skip;
+	start = skip;
 	snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk*47);
 	// get rid of leading crap 
-	snprintf(tmp, sizeof(tmp),"%i",skip);
+	snprintf(tmp, sizeof(tmp), "%i", skip);
 	CmdLtrim(tmp);
 	bool pTest;
-	bool AllPTest=true;
+	bool AllPTest = true;
 	// now work through remaining buffer printing out data blocks
 	block = 0;
 	i = startblock;
-	while (block < 6)
-	{
+	while (block < 6) {
 		if (verbose || g_debugMode) PrintAndLog("\nBlock %i:", block);
 		skip = phaseoff;
 		
 		// look for LW before start of next block
-		for ( ; i < j - 4 ; ++i)
-		{
+		for ( ; i < j - 4 ; ++i) {
 			skip += tmpbuff[i];
 			if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol)
 				if (tmpbuff[i+1] >= clk-tol)
 					break;
 		}
+		if (i >= j-4) break; //next LW not found
 		skip += clk;
-		phaseoff = tmpbuff[i+1]-clk;
+		if (tmpbuff[i+1]>clk)
+			phaseoff = tmpbuff[i+1]-clk;
+		else
+			phaseoff = 0;
 		i += 2;
-		if (ASKmanDemod(tmp2, false, false)<1) return 0;
+		if (ASKDemod(tmp2, false, false, 1) < 1) {
+			save_restoreGB(0);
+			return 0;
+		}
 		//set DemodBufferLen to just one block
 		DemodBufferLen = skip/clk;
 		//test parities
@@ -462,26 +469,32 @@ int EM4x50Read(const char *Cmd, bool verbose)
 		pTest &= EM_EndParityTest(DemodBuffer,DemodBufferLen,5,9,0);
 		AllPTest &= pTest;
 		//get output
-		Code[block]=OutputEM4x50_Block(DemodBuffer,DemodBufferLen,verbose, pTest);
-		if (g_debugMode) PrintAndLog("\nskipping %d samples, bits:%d",start, skip/clk);
+		Code[block] = OutputEM4x50_Block(DemodBuffer,DemodBufferLen,verbose, pTest);
+		if (g_debugMode) PrintAndLog("\nskipping %d samples, bits:%d", skip, skip/clk);
 		//skip to start of next block
 		snprintf(tmp,sizeof(tmp),"%i",skip);
 		CmdLtrim(tmp);
 		block++;
-		if (i>=end) break; //in case chip doesn't output 6 blocks
+		if (i >= end) break; //in case chip doesn't output 6 blocks
 	}
 	//print full code:
 	if (verbose || g_debugMode || AllPTest){
-		PrintAndLog("Found data at sample: %i - using clock: %i",skip,clk);    
-		//PrintAndLog("\nSummary:");
-		end=block;
-		for (block=0; block<end; block++){
+		if (!complete) {
+			PrintAndLog("*** Warning!");
+			PrintAndLog("Partial data - no end found!");
+			PrintAndLog("Try again with more samples.");
+		}
+		PrintAndLog("Found data at sample: %i - using clock: %i", start, clk);    
+		end = block;
+		for (block=0; block < end; block++){
 			PrintAndLog("Block %d: %08x",block,Code[block]);
 		}
-		if (AllPTest)
+		if (AllPTest) {
 			PrintAndLog("Parities Passed");
-		else
+		} else {
 			PrintAndLog("Parities Failed");
+			PrintAndLog("Try cleaning the read samples with 'data askedge'");
+		}
 	}
 
 	//restore GraphBuffer
@@ -594,11 +607,11 @@ static command_t CommandTable[] =
 {
 	{"help", CmdHelp, 1, "This help"},
 	{"em410xdemod", CmdEMdemodASK, 0, "[findone] -- Extract ID from EM410x tag (option 0 for continuous loop, 1 for only 1 tag)"},  
-	{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag"},
+	{"em410xread", CmdEM410xRead, 1, "[clock rate] -- Extract ID from EM410x tag in GraphBuffer"},
 	{"em410xsim", CmdEM410xSim, 0, "<UID> -- Simulate EM410x tag"},
 	{"em410xwatch", CmdEM410xWatch, 0, "['h'] -- Watches for EM410x 125/134 kHz tags (option 'h' for 134)"},
 	{"em410xspoof", CmdEM410xWatchnSpoof, 0, "['h'] --- Watches for EM410x 125/134 kHz tags, and replays them. (option 'h' for 134)" },
-	{"em410xwrite", CmdEM410xWrite, 1, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
+	{"em410xwrite", CmdEM410xWrite, 0, "<UID> <'0' T5555> <'1' T55x7> [clock rate] -- Write EM410x UID to T5555(Q5) or T55x7 tag, optionally setting clock rate"},
 	{"em4x50read", CmdEM4x50Read, 1, "Extract data from EM4x50 tag"},
 	{"readword", CmdReadWord, 1, "<Word> -- Read EM4xxx word data"},
 	{"readwordPWD", CmdReadWordPWD, 1, "<Word> <Password> -- Read EM4xxx word data in password mode"},