}
return code;
}
-/* Read the transmitted data of an EM4x50 tag
+/* Read the transmitted data of an EM4x50 tag from the graphbuffer
* Format:
*
* XXXXXXXX [row parity bit (even)] <- 8 bits plus parity
//completed by Marshmellow
int EM4x50Read(const char *Cmd, bool verbose)
{
- /*
- char buf[30] = {0x00};
- char *cmdStr = buf;
- int ans = 0;
- bool ST = config.ST;
- uint8_t bitRate[8] = {8,16,32,40,50,64,100,128};
- DemodBufferLen = 0x00;
- snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted );
- ans = ASKDemod_ext(cmdStr, FALSE, FALSE, 1, &ST);
- snprintf(cmdStr, sizeof(buf),"0 %d %d 1", bitRate[config.bitrate], config.inverted );
- ans = ASKbiphaseDemod(cmdStr, FALSE);
- */
-
+
uint8_t fndClk[] = {8,16,32,40,50,64,128};
int clk = 0;
int invert = 0;
}
int usage_lf_em_read(void) {
- PrintAndLog("Read EM4x50. Tag must be on antenna. ");
+ PrintAndLog("Read EM4x05/EM4x69. Tag must be on antenna. ");
PrintAndLog("");
PrintAndLog("Usage: lf em readword [h] <address> <pwd>");
PrintAndLog("Options:");
PrintAndLog(" lf em readword 1 11223344");
return 0;
}
+
+//search for given preamble in given BitStream and return success=1 or fail=0 and startIndex
+uint8_t EMpreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t size, size_t *startIdx)
+{
+ // Sanity check. If preamble length is bigger than bitstream length.
+ if ( size <= pLen ) return 0;
+ // em only sends preamble once, so look for it once in the first x bits
+ uint8_t foundCnt = 0;
+ for (int idx = 0; idx < size - pLen; idx++){
+ if (memcmp(BitStream+idx, preamble, pLen) == 0){
+ //first index found
+ foundCnt++;
+ if (foundCnt == 1) {
+ *startIdx = idx;
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+int demodEM4x05resp(uint8_t bitsNeeded) {
+ int ans = 0;
+ bool demodFound = false;
+ DemodBufferLen = 0x00;
+ // skip first two 0 bits as they might have been missed in the demod
+ uint8_t preamble[6] = {0,0,1,0,1,0};
+
+ // test for FSK wave (easiest to 99% ID)
+ if (GetFskClock("", FALSE, FALSE)) {
+ //valid fsk clocks found
+ ans = FSKrawDemod("0 0", false);
+ if (!ans) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: FSK Demod failed");
+ //return -1;
+ } else {
+ // set size to 10 to only test first 4 positions for the preamble
+ size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10;
+ size_t startIdx = 0;
+
+ if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size);
+
+ uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx);
+ if ( errChk == 0) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx);
+ //return -1;
+ } else {
+ //can't test size because the preamble doesn't repeat :(
+ //meaning chances of false positives are high.
+ demodFound = true;
+ }
+ }
+ }
+
+ ans = GetPskClock("", FALSE, FALSE);
+ if (ans>0) {
+ PrintAndLog("PSK response possibly found, run `data rawd p1` to attempt to demod");
+ }
+
+ if (!demodFound) {
+ DemodBufferLen = 0x00;
+ //try biphase
+ ans = ASKbiphaseDemod("0 0 1", FALSE);
+ if (!ans) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed");
+ //return -1;
+ } else {
+ // set size to 10 to only test first 4 positions for the preamble
+ size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10;
+ size_t startIdx = 0;
+
+ if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size);
+
+ uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx);
+ if ( errChk == 0) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx);
+ //return -1;
+ } else {
+ //can't test size because the preamble doesn't repeat :(
+ //meaning chances of false positives are high.
+ demodFound = true;
+ }
+ }
+ }
+
+ if (!demodFound) {
+ DemodBufferLen = 0x00;
+ // try manchester - NOTE: ST only applies to T55x7 tags.
+ ans = ASKDemod_ext("0,0,1", false, false, 1, false);
+ if (!ans) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed");
+ //return -1;
+ } else {
+ // set size to 10 to only test first 4 positions for the preamble
+ size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10;
+ size_t startIdx = 0;
+
+ if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size);
+
+ uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx);
+ if ( errChk == 0) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx);
+ //return -1;
+ } else {
+ //can't test size because the preamble doesn't repeat :(
+ //meaning chances of false positives are high.
+ demodFound = true;
+ }
+ }
+ }
+
+ if (demodFound && bitsNeeded < DemodBufferLen) {
+ setDemodBuf(DemodBuffer + ans + sizeof(preamble), bitsNeeded, 0);
+ CmdPrintDemodBuff("x");
+ return 1;
+ }
+ return -1;
+}
+
int CmdReadWord(const char *Cmd) {
int addr, pwd;
bool usePwd = false;
return -1;
}
- //uint8_t got[12288];
- uint8_t got[30000];
+ uint8_t got[6000];
GetFromBigBuf(got, sizeof(got), 0);
- if ( !WaitForResponseTimeout(CMD_ACK, NULL, 8000) ) {
+ if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) {
PrintAndLog("command execution time out");
- return 0;
+ return -1;
}
setGraphBuf(got, sizeof(got));
+ int testLen = (GraphTraceLen < 1000) ? GraphTraceLen : 1000;
+ if (graphJustNoise(GraphBuffer, testLen)) {
+ PrintAndLog("no tag not found");
+ return -1;
+ }
+
+ //need 32 bits for read word
+ demodEM4x05resp(32);
+
return 1;
}
int usage_lf_em_write(void) {
- PrintAndLog("Write EM4x50. Tag must be on antenna. ");
+ PrintAndLog("Write EM4x05/EM4x69. Tag must be on antenna. ");
PrintAndLog("");
PrintAndLog("Usage: lf em writeword [h] <address> <data> <pwd>");
PrintAndLog("Options:");
PrintAndLog("Error occurred, device did not respond during write operation.");
return -1;
}
+
+ //get response if there is one
+ uint8_t got[6000]; // 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples)
+ GetFromBigBuf(got, sizeof(got), 0);
+ if ( !WaitForResponseTimeout(CMD_ACK, NULL, 8000) ) {
+ PrintAndLog("command execution time out");
+ return -2;
+ }
+ setGraphBuf(got, sizeof(got));
+
+ int ans = 0;
+ //bool ST = true;
+ DemodBufferLen = 0x00;
+
+ //ans = ASKDemod_ext("0 0 1", FALSE, FALSE, 1, &ST);
+ ans = ASKbiphaseDemod("0 0 1", FALSE);
+ if (!ans) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed");
+ return -3;
+ }
+
+ //todo: check response for 00001010 then write data for write confirmation!
+ size_t startIdx = 0, size = DemodBufferLen;
+
+ uint8_t preamble[8] = {0,0,0,0,1,0,1,0};
+ if (!preambleSearch(DemodBuffer, preamble, sizeof(preamble), &size, &startIdx)){
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx);
+ return -4;
+ }
+ PrintAndLog("Write OK");
return 0;
}
{"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, 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, "Read EM4xxx data"},
- {"writeword", CmdWriteWord, 1, "Write EM4xxx data"},
+ {"em4x50read", CmdEM4x50Read, 1, "demod data from EM4x50 tag from the graphbuffer"},
+ {"readword", CmdReadWord, 1, "read EM4x05/4x69 data"},
+ {"writeword", CmdWriteWord, 1, "write EM405/4x69 data"},
{NULL, NULL, 0, NULL}
};