+ setDemodBuf(DemodBuffer, 40, 0);
+ *word = bytebits_to_byteLSBF(DemodBuffer, 32);
+ }
+ 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;
+
+ // 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, ans: %d", ans);
+ } else {
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ }
+ }
+ }
+ // PSK clocks should be easy to detect ( but difficult to demod a non-repeating pattern... )
+ ans = GetPskClock("", FALSE, FALSE);
+ if (ans>0) {
+ //try psk1
+ ans = PSKDemod("0 0 6", FALSE);
+ if (!ans) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed, ans: %d", ans);
+ } else {
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ } else {
+ //try psk2
+ psk1TOpsk2(DemodBuffer, DemodBufferLen);
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ }
+ }
+ //try psk1 inverted
+ ans = PSKDemod("0 1 6", FALSE);
+ if (!ans) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: PSK1 Demod failed, ans: %d", ans);
+ } else {
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ } else {
+ //try psk2
+ psk1TOpsk2(DemodBuffer, DemodBufferLen);
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ }
+ }
+ }
+ }
+ }
+
+ // manchester is more common than biphase... try first
+ 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, ans: %d", ans);
+ } else {
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ }
+ }
+
+ //try biphase
+ ans = ASKbiphaseDemod("0 0 1", FALSE);
+ if (!ans) {
+ if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed, ans: %d", ans);
+ } else {
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ }
+ }
+
+ //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, ans: %d", ans);
+ } else {
+ if (EM4x05testDemodReadData(word, readCmd)) {
+ return 1;
+ }
+ }
+
+ return -1;
+}
+
+int EM4x05ReadWord(uint8_t addr, uint32_t pwd, bool usePwd) {
+ UsbCommand c = {CMD_EM4X_READ_WORD, {addr, pwd, usePwd}};
+ clearCommandBuffer();
+ SendCommand(&c);
+ UsbCommand resp;
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)){
+ PrintAndLog("Command timed out");
+ return -1;
+ }
+ if ( !downloadSamplesEM() ) {
+ return -1;
+ }
+ int testLen = (GraphTraceLen < 1000) ? GraphTraceLen : 1000;
+ if (graphJustNoise(GraphBuffer, testLen)) {
+ PrintAndLog("no tag not found");
+ return -1;
+ }
+ //attempt demod:
+ uint32_t wordData = 0;
+ int success = demodEM4x05resp(&wordData, true);
+ if (success == 1)
+ PrintAndLog(" Got Address %02d | %08X",addr,wordData);
+ else
+ PrintAndLog("RSead Address %02d | failed",addr);
+
+ return success;
+}
+
+int CmdEM4x05ReadWord(const char *Cmd) {
+ uint8_t addr;
+ uint32_t pwd;
+ bool usePwd = false;
+ uint8_t ctmp = param_getchar(Cmd, 0);
+ if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_read();
+
+ addr = param_get8ex(Cmd, 0, 50, 10);
+ // for now use default input of 1 as invalid (unlikely 1 will be a valid password...)
+ pwd = param_get32ex(Cmd, 1, 1, 16);
+
+ if ( (addr > 15) ) {
+ PrintAndLog("Address must be between 0 and 15");
+ return 1;
+ }
+ if ( pwd == 1 ) {
+ PrintAndLog("Reading address %02u", addr);
+ } else {
+ usePwd = true;
+ PrintAndLog("Reading address %02u | password %08X", addr, pwd);
+ }
+
+ return EM4x05ReadWord(addr, pwd, usePwd);
+}
+
+int usage_lf_em_dump(void) {
+ PrintAndLog("Dump EM4x05/EM4x69. Tag must be on antenna. ");
+ PrintAndLog("");
+ PrintAndLog("Usage: lf em 4x05dump [h] <pwd>");
+ PrintAndLog("Options:");
+ PrintAndLog(" h - this help");
+ PrintAndLog(" pwd - password (hex) (optional)");
+ PrintAndLog("samples:");
+ PrintAndLog(" lf em 4x05dump");
+ PrintAndLog(" lf em 4x05dump 11223344");
+ return 0;
+}
+
+int CmdEM4x05dump(const char *Cmd) {
+ uint8_t addr = 0;
+ uint32_t pwd;
+ bool usePwd = false;
+ uint8_t ctmp = param_getchar(Cmd, 0);
+ if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_dump();
+
+ // for now use default input of 1 as invalid (unlikely 1 will be a valid password...)
+ pwd = param_get32ex(Cmd, 0, 1, 16);
+
+ if ( pwd != 1 ) {
+ usePwd = true;
+ }
+ int success = 1;
+ for (; addr < 16; addr++) {
+ if (addr == 2) {
+ if (usePwd) {
+ PrintAndLog("PWD Address %02u | %08X",addr,pwd);
+ } else {
+ PrintAndLog("PWD Address 02 | cannot read");
+ }
+ } else {
+ success &= EM4x05ReadWord(addr, pwd, usePwd);
+ }
+ }
+
+ return success;
+}
+
+
+int usage_lf_em_write(void) {
+ PrintAndLog("Write EM4x05/EM4x69. Tag must be on antenna. ");
+ PrintAndLog("");
+ PrintAndLog("Usage: lf em 4x05writeword [h] <address> <data> <pwd>");
+ PrintAndLog("Options:");
+ PrintAndLog(" h - this help");
+ PrintAndLog(" address - memory address to write to. (0-15)");
+ PrintAndLog(" data - data to write (hex)");
+ PrintAndLog(" pwd - password (hex) (optional)");
+ PrintAndLog("samples:");
+ PrintAndLog(" lf em 4x05writeword 1");
+ PrintAndLog(" lf em 4x05writeword 1 deadc0de 11223344");
+ 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
+
+ addr = param_get8ex(Cmd, 0, 16, 10);
+ data = param_get32ex(Cmd, 1, 0, 16);
+ pwd = param_get32ex(Cmd, 2, 1, 16);
+
+
+ if ( (addr > 15) ) {
+ PrintAndLog("Address must be between 0 and 15");
+ return 1;
+ }
+ if ( pwd == 1 )
+ PrintAndLog("Writing address %d data %08X", addr, data);
+ else {
+ usePwd = true;
+ PrintAndLog("Writing address %d data %08X using password %08X", addr, data, pwd);
+ }
+
+ uint16_t flag = (addr << 8 ) | usePwd;
+
+ UsbCommand c = {CMD_EM4X_WRITE_WORD, {flag, data, pwd}};
+ clearCommandBuffer();
+ SendCommand(&c);
+ UsbCommand resp;
+ if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)){
+ PrintAndLog("Error occurred, device did not respond during write operation.");
+ return -1;
+ }
+ if ( !downloadSamplesEM() ) {
+ return -1;
+ }
+ //check response for 00001010 for write confirmation!
+ //attempt demod:
+ uint32_t dummy = 0;
+ int result = demodEM4x05resp(&dummy,false);
+ if (result == 1) {
+ PrintAndLog("Write Verified");
+ }
+ return result;
+}