X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/f513388ee056cfaa34799ed19e451383db1065c3..890738733a64445e6565516fe20c927884b712fd:/client/cmdlfem4x.c?ds=sidebyside

diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c
index 1dfab394..e84cccf9 100644
--- a/client/cmdlfem4x.c
+++ b/client/cmdlfem4x.c
@@ -22,6 +22,7 @@
 #include "cmdlf.h"
 #include "cmdmain.h"
 #include "lfdemod.h"
+#include "protocols.h"
 
 uint64_t g_em410xId=0;
 
@@ -145,17 +146,20 @@ void printEM410x(uint32_t hi, uint64_t id)
 int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo )
 {
 	size_t idx = 0;
-	size_t BitLen = DemodBufferLen;
-	uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
-	memcpy(BitStream, DemodBuffer, BitLen); 
-	if (Em410xDecode(BitStream, &BitLen, &idx, hi, lo)){
+	uint8_t BitStream[512]={0};
+	size_t BitLen = sizeof(BitStream);
+	if ( !getDemodBuf(BitStream, &BitLen) ) return 0;
+
+	if (Em410xDecode(BitStream, &BitLen, &idx, hi, lo)) {
 		//set GraphBuffer for clone or sim command
-		setDemodBuf(BitStream, BitLen, idx);
-		if (g_debugMode){
+		setDemodBuf(DemodBuffer, (BitLen==40) ? 64 : 128, idx+1);
+		setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx+1)*g_DemodClock));
+
+		if (g_debugMode) {
 			PrintAndLog("DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, BitLen);
 			printDemodBuff();
 		}
-		if (verbose){
+		if (verbose) {
 			PrintAndLog("EM410x pattern found: ");
 			printEM410x(*hi, *lo);
 			g_em410xId = *lo;
@@ -297,9 +301,7 @@ int CmdEM410xWatch(const char *Cmd)
 			printf("\naborted via keyboard!\n");
 			break;
 		}
-		
-		CmdLFRead("s");
-		getSamples("8201",true); 
+		lf_read(true, 8201);
 	} while (!CmdAskEM410xDemod(""));
 
 	return 0;
@@ -472,9 +474,6 @@ int EM4x50Read(const char *Cmd, bool verbose)
 	// 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++) {
 		if (GraphBuffer[i] > high)
@@ -571,6 +570,8 @@ int EM4x50Read(const char *Cmd, bool verbose)
 	} else if (start < 0) return 0;
 	start = skip;
 	snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk*47);
+	// save GraphBuffer - to restore it later	
+	save_restoreGB(GRAPH_SAVE);
 	// get rid of leading crap 
 	snprintf(tmp, sizeof(tmp), "%i", skip);
 	CmdLtrim(tmp);
@@ -598,7 +599,7 @@ int EM4x50Read(const char *Cmd, bool verbose)
 			phaseoff = 0;
 		i += 2;
 		if (ASKDemod(tmp2, false, false, 1) < 1) {
-			save_restoreGB(0);
+			save_restoreGB(GRAPH_RESTORE);
 			return 0;
 		}
 		//set DemodBufferLen to just one block
@@ -637,7 +638,7 @@ int EM4x50Read(const char *Cmd, bool verbose)
 	}
 
 	//restore GraphBuffer
-	save_restoreGB(0);
+	save_restoreGB(GRAPH_RESTORE);
 	return (int)AllPTest;
 }
 
@@ -703,6 +704,8 @@ bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) {
 		}
 
 		setDemodBuf(DemodBuffer, 32, 0);
+		//setClockGrid(0,0);
+
 		*word = bytebits_to_byteLSBF(DemodBuffer, 32);
 	}
 	return true;
@@ -899,47 +902,35 @@ int CmdEM4x05dump(const char *Cmd) {
 int usage_lf_em_write(void) {
 	PrintAndLog("Write EM4x05/EM4x69.  Tag must be on antenna. ");
 	PrintAndLog("");
-	PrintAndLog("Usage:  lf em 4x05writeword [h] [s] <address> <data> <pwd>");
+	PrintAndLog("Usage:  lf em 4x05writeword [h] a <address> d <data> p <pwd> [s] [i]");
 	PrintAndLog("Options:");
-	PrintAndLog("       h         - this help");
-	PrintAndLog("       s         - swap data bit order before write");
-	PrintAndLog("       address   - memory address to write to. (0-15)");
-	PrintAndLog("       data      - data to write (hex)");	
-	PrintAndLog("       pwd       - password (hex) (optional)");
+	PrintAndLog("       h           - this help");
+	PrintAndLog("       a <address> - memory address to write to. (0-15)");
+	PrintAndLog("       d <data>    - data to write (hex)");	
+	PrintAndLog("       p <pwd>     - password (hex) (optional)");
+	PrintAndLog("       s           - swap the data bit order before write");
+	PrintAndLog("       i           - invert the data bits before write");
 	PrintAndLog("samples:");
-	PrintAndLog("      lf em 4x05writeword 1");
-	PrintAndLog("      lf em 4x05writeword 1 deadc0de 11223344");
+	PrintAndLog("      lf em 4x05writeword a 5 d 11223344");
+	PrintAndLog("      lf em 4x05writeword a 5 p deadc0de d 11223344 s i");
 	return 0;
 }
 
-int CmdEM4x05WriteWord(const char *Cmd) {
-	uint8_t ctmp = param_getchar(Cmd, 0);
-	if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_write();
-
-	bool usePwd = false;
-
-	uint8_t addr = 16; // default to invalid address
-	uint32_t data = 0xFFFFFFFF; // default to blank data
-	uint32_t pwd = 0xFFFFFFFF; // default to blank password
-	char swap = 0;
-
-	int p = 0;
-	swap = param_getchar(Cmd, 0);
-	if (swap == 's' || swap=='S') p++;
-	addr = param_get8ex(Cmd, p++, 16, 10);
-	data = param_get32ex(Cmd, p++, 0, 16);
-	pwd  = param_get32ex(Cmd, p++, 1, 16);
+// note: em4x05 doesn't have a way to invert data output so we must invert the data prior to writing
+//         it if invertion is needed. (example FSK2a vs FSK)
+//       also em4x05 requires swapping word data when compared to the data used for t55xx chips.
+int EM4x05WriteWord(uint8_t addr, uint32_t data, uint32_t pwd, bool usePwd, bool swap, bool invert) {
+	if (swap) data = SwapBits(data, 32);
 
-	if (swap == 's' || swap=='S') data = SwapBits(data, 32);
+	if (invert) data ^= 0xFFFFFFFF;
 
 	if ( (addr > 15) ) {
 		PrintAndLog("Address must be between 0 and 15");
-		return 1;
+		return -1;
 	}
-	if ( pwd == 1 )
-		PrintAndLog("Writing address %d data %08X", addr, data);	
-	else {
-		usePwd = true;
+	if ( !usePwd ) {
+		PrintAndLog("Writing address %d data %08X", addr, data);
+	} else {
 		PrintAndLog("Writing address %d data %08X using password %08X", addr, data, pwd);
 	}
 
@@ -968,8 +959,75 @@ int CmdEM4x05WriteWord(const char *Cmd) {
 	return result;
 }
 
+int CmdEM4x05WriteWord(const char *Cmd) {
+	bool errors = false;
+	bool usePwd = false;
+	uint32_t data = 0xFFFFFFFF;
+	uint32_t pwd = 0xFFFFFFFF;
+	bool swap = false;
+	bool invert = false;
+	uint8_t addr = 16; // default to invalid address
+	bool gotData = false;
+	char cmdp = 0;
+	while(param_getchar(Cmd, cmdp) != 0x00)
+	{
+		switch(param_getchar(Cmd, cmdp))
+		{
+		case 'h':
+		case 'H':
+			return usage_lf_em_write();
+		case 'a':
+		case 'A':
+			addr = param_get8ex(Cmd, cmdp+1, 16, 10);
+			cmdp += 2;
+			break;
+		case 'd':
+		case 'D':
+			data = param_get32ex(Cmd, cmdp+1, 0, 16);
+			gotData = true;
+			cmdp += 2;
+			break;
+		case 'i':
+		case 'I':
+			invert = true;
+			cmdp++;
+			break;
+		case 'p':
+		case 'P':
+			pwd = param_get32ex(Cmd, cmdp+1, 1, 16);
+			if (pwd == 1) {
+				PrintAndLog("invalid pwd");
+				errors = true;
+			}
+			usePwd = true;
+			cmdp += 2;
+			break;
+		case 's':
+		case 'S':
+			swap = true;
+			cmdp++;
+			break;
+		default:
+			PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+			errors = true;
+			break;
+		}
+		if(errors) break;
+	}
+	//Validations
+	if(errors) return usage_lf_em_write();
+
+	if ( strlen(Cmd) == 0 ) return usage_lf_em_write();
+
+	if (!gotData) {
+		PrintAndLog("You must enter the data you want to write");
+		return usage_lf_em_write();
+	}
+	return EM4x05WriteWord(addr, data, pwd, usePwd, swap, invert);
+}
+
 void printEM4x05config(uint32_t wordData) {
-	uint16_t datarate = (((wordData & 0x3F)+1)*2);
+	uint16_t datarate = EM4x05_GET_BITRATE(wordData);
 	uint8_t encoder = ((wordData >> 6) & 0xF);
 	char enc[14];
 	memset(enc,0,sizeof(enc));
@@ -980,8 +1038,8 @@ void printEM4x05config(uint32_t wordData) {
 	uint8_t delay = (wordData >> 12) & 0x3;
 	char cdelay[33];
 	memset(cdelay,0,sizeof(cdelay));
-	uint8_t LWR = (wordData >> 14) & 0xF; //last word read
-
+	uint8_t numblks = EM4x05_GET_NUM_BLOCKS(wordData);
+	uint8_t LWR = numblks+5-1; //last word read
 	switch (encoder) {
 		case 0: snprintf(enc,sizeof(enc),"NRZ"); break;
 		case 1: snprintf(enc,sizeof(enc),"Manchester"); break;
@@ -1009,21 +1067,29 @@ void printEM4x05config(uint32_t wordData) {
 		case 2: snprintf(cdelay, sizeof(cdelay),"BP/4 or 1/4th bit period delay"); break;
 		case 3: snprintf(cdelay, sizeof(cdelay),"no delay"); break;
 	}
+	uint8_t readLogin = (wordData & EM4x05_READ_LOGIN_REQ)>>18;
+	uint8_t readHKL = (wordData & EM4x05_READ_HK_LOGIN_REQ)>>19;
+	uint8_t writeLogin = (wordData & EM4x05_WRITE_LOGIN_REQ)>>20;
+	uint8_t writeHKL = (wordData & EM4x05_WRITE_HK_LOGIN_REQ)>>21;
+	uint8_t raw = (wordData & EM4x05_READ_AFTER_WRITE)>>22;
+	uint8_t disable = (wordData & EM4x05_DISABLE_ALLOWED)>>23;
+	uint8_t rtf = (wordData & EM4x05_READER_TALK_FIRST)>>24;
+	uint8_t pigeon = (wordData & (1<<26))>>26;
 	PrintAndLog("ConfigWord: %08X (Word 4)\n", wordData);
-	PrintAndLog("Config Breakdown:", wordData);
+	PrintAndLog("Config Breakdown:");
 	PrintAndLog(" Data Rate:  %02u | RF/%u", wordData & 0x3F, datarate);
 	PrintAndLog("   Encoder:   %u | %s", encoder, enc);
 	PrintAndLog("    PSK CF:   %u | %s", PSKcf, cf);
 	PrintAndLog("     Delay:   %u | %s", delay, cdelay);
-	PrintAndLog(" LastWordR:  %02u | Address of last word for default read", LWR);
-	PrintAndLog(" ReadLogin:   %u | Read Login is %s", (wordData & 0x40000)>>18, (wordData & 0x40000) ? "Required" : "Not Required");	
-	PrintAndLog("   ReadHKL:   %u | Read Housekeeping Words Login is %s", (wordData & 0x80000)>>19, (wordData & 0x80000) ? "Required" : "Not Required");	
-	PrintAndLog("WriteLogin:   %u | Write Login is %s", (wordData & 0x100000)>>20, (wordData & 0x100000) ? "Required" : "Not Required");	
-	PrintAndLog("  WriteHKL:   %u | Write Housekeeping Words Login is %s", (wordData & 0x200000)>>21, (wordData & 0x200000) ? "Required" : "Not Required");	
-	PrintAndLog("    R.A.W.:   %u | Read After Write is %s", (wordData & 0x400000)>>22, (wordData & 0x400000) ? "On" : "Off");
-	PrintAndLog("   Disable:   %u | Disable Command is %s", (wordData & 0x800000)>>23, (wordData & 0x800000) ? "Accepted" : "Not Accepted");
-	PrintAndLog("    R.T.F.:   %u | Reader Talk First is %s", (wordData & 0x1000000)>>24, (wordData & 0x1000000) ? "Enabled" : "Disabled");
-	PrintAndLog("    Pigeon:   %u | Pigeon Mode is %s\n", (wordData & 0x4000000)>>26, (wordData & 0x4000000) ? "Enabled" : "Disabled");
+	PrintAndLog(" LastWordR:  %02u | Address of last word for default read - meaning %u blocks are output", LWR, numblks);
+	PrintAndLog(" ReadLogin:   %u | Read Login is %s", readLogin, readLogin ? "Required" : "Not Required");	
+	PrintAndLog("   ReadHKL:   %u | Read Housekeeping Words Login is %s", readHKL, readHKL ? "Required" : "Not Required");	
+	PrintAndLog("WriteLogin:   %u | Write Login is %s", writeLogin, writeLogin ? "Required" : "Not Required");	
+	PrintAndLog("  WriteHKL:   %u | Write Housekeeping Words Login is %s", writeHKL, writeHKL ? "Required" : "Not Required");	
+	PrintAndLog("    R.A.W.:   %u | Read After Write is %s", raw, raw ? "On" : "Off");
+	PrintAndLog("   Disable:   %u | Disable Command is %s", disable, disable ? "Accepted" : "Not Accepted");
+	PrintAndLog("    R.T.F.:   %u | Reader Talk First is %s", rtf, rtf ? "Enabled" : "Disabled");
+	PrintAndLog("    Pigeon:   %u | Pigeon Mode is %s\n", pigeon, pigeon ? "Enabled" : "Disabled");
 }
 
 void printEM4x05info(uint8_t chipType, uint8_t cap, uint16_t custCode, uint32_t serial) {
@@ -1102,6 +1168,7 @@ int CmdEM4x05info(const char *Cmd) {
 	wordData = 0;
 	if ( EM4x05ReadWord_ext(4, pwd, usePwd, &wordData) != 1 ) {
 		//failed
+		PrintAndLog("Config block read failed - might be password protected.");
 		return 0;
 	}
 	printEM4x05config(wordData);