+ return EM4x50Read(Cmd, true);
+}
+
+int usage_lf_em_read(void) {
+ PrintAndLog("Read EM4x05/EM4x69. Tag must be on antenna. ");
+ PrintAndLog("");
+ PrintAndLog("Usage: lf em 4x05readword [h] <address> <pwd>");
+ PrintAndLog("Options:");
+ PrintAndLog(" h - this help");
+ PrintAndLog(" address - memory address to read. (0-15)");
+ PrintAndLog(" pwd - password (hex) (optional)");
+ PrintAndLog("samples:");
+ PrintAndLog(" lf em 4x05readword 1");
+ PrintAndLog(" lf em 4x05readword 1 11223344");
+ return 0;
+}
+
+//search for given preamble in given BitStream and return success=1 or fail=0 and startIndex
+bool 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 false;
+ // em only sends preamble once, so look for it once in the first x bits
+ uint8_t foundCnt = 0;
+ for (size_t idx = 0; idx < size - pLen; idx++){
+ if (memcmp(BitStream+idx, preamble, pLen) == 0){
+ //first index found
+ foundCnt++;
+ if (foundCnt == 1) {
+ if (g_debugMode) PrintAndLog("DEBUG: preamble found at %u", idx);
+ *startIdx = idx;
+
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool EM4x05testDemodReadData(uint32_t *word, bool readCmd) {
+ // skip first two 0 bits as they might have been missed in the demod
+ uint8_t preamble[6] = {0,0,1,0,1,0};
+ size_t startIdx = 0;
+ // set size to 10 to only test first 4 positions for the preamble
+ size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10;
+ startIdx = 0;
+
+ //test preamble
+ bool errChk = EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx);
+ if ( !errChk ) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx);
+ return false;
+ }
+ if (readCmd) {
+ //test for even parity bits.
+ size = removeParity(DemodBuffer, startIdx + sizeof(preamble),9,0,44);
+ if (size == 0) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - Parity not detected");
+ return false;
+ }
+
+ //todo test last 8 bits for even parity || (xor)
+
+ setDemodBuf(DemodBuffer, 40, 0);
+
+ *word = bytebits_to_byteLSBF(DemodBuffer , 32);
+
+ uint8_t lo = (uint8_t) bytebits_to_byteLSBF(DemodBuffer , 8);
+ uint8_t lo2 = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 8, 8);
+ uint8_t hi = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 16, 8);
+ uint8_t hi2 = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 24, 8);
+ uint8_t cs = (uint8_t) bytebits_to_byteLSBF(DemodBuffer + 32, 8);
+ uint8_t cs2 = lo ^ lo2 ^ hi ^ hi2;
+ if (g_debugMode) PrintAndLog("EM4x05/4x69 : %08X CS: %02X %s",*word,cs, (cs2==cs) ? "Passed" : "Failed");
+
+ return (cs2==cs) ? true : false;
+ }
+ return true;
+}
+
+// FSK, PSK, ASK/MANCHESTER, ASK/BIPHASE, ASK/DIPHASE
+// should cover 90% of known used configs
+// the rest will need to be manually demoded for now...
+int demodEM4x05resp(uint32_t *word, bool readCmd) {
+ int ans = 0;
+ bool demodFound = false;
+ DemodBufferLen = 0x00;
+
+ // 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");
+ } else {
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ }
+ }
+ }
+ // PSK clocks should be easy to detect ( but difficult to demod a non-repeating pattern... )
+ if (!demodFound) {
+ ans = GetPskClock("", FALSE, FALSE);
+ if (ans>0) {
+ PrintAndLog("PSK response possibly found, run `data rawd p1` to attempt to demod");
+ }
+ }
+
+ // more common than biphase
+ if (!demodFound) {
+ DemodBufferLen = 0x00;
+ bool stcheck = false;
+ // try manchester - NOTE: ST only applies to T55x7 tags.
+ ans = ASKDemod_ext("0,0,1", false, false, 1, &stcheck);
+ if (!ans) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed");
+ } else {
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ }
+ }
+ }
+
+ 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");
+ } else {
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ }
+ }
+ }
+
+ if (!demodFound) {
+ DemodBufferLen = 0x00;
+ //try diphase (differential biphase or inverted)
+ ans = ASKbiphaseDemod("0 1 1", FALSE);
+ if (!ans) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed");
+ } else {
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ }
+ }
+ }
+
+ /*if (demodFound && bitsNeeded < DemodBufferLen) {
+ if (bitsNeeded > 0) {
+ setDemodBuf(DemodBuffer + startIdx + sizeof(preamble), bitsNeeded, 0);
+ CmdPrintDemodBuff("x");
+ }
+ return 1;
+ }*/
+ return -1;