diff --git a/armsrc/appmain.c b/armsrc/appmain.c index fe8566363..87b17afd9 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1163,6 +1163,10 @@ static void PacketReceived(PacketCommandNG *packet) { em4x50_chk((uint8_t *)packet->data.asBytes); break; } + case CMD_LF_EM4X50_TEST: { + em4x50_test((em4x50_test_t *)packet->data.asBytes); + break; + } #endif #ifdef WITH_EM4x70 diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index 437afd956..a84a911c5 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -431,7 +431,6 @@ static int find_double_listen_window(bool bcommand) { // send RM for request mode em4x50_reader_send_bit(0); em4x50_reader_send_bit(0); - LED_B_OFF(); return PM3_SUCCESS; @@ -724,13 +723,27 @@ static bool em4x50_sim_send_word(uint32_t word) { static bool em4x50_sim_send_listen_window(void) { + bool cond = false; uint16_t check = 0; + uint32_t tval1[5 * EM4X50_T_TAG_FULL_PERIOD] = {0}; + uint32_t tval2[5 * EM4X50_T_TAG_FULL_PERIOD] = {0}; + + StartTicks(); for (int t = 0; t < 5 * EM4X50_T_TAG_FULL_PERIOD; t++) { + cond = ((t >= 3 * EM4X50_T_TAG_FULL_PERIOD) && (t < 4 * EM4X50_T_TAG_FULL_PERIOD)); + // wait until SSC_CLK goes HIGH + if (cond) { + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + while (AT91C_BASE_TC0->TC_CV > 0); + } + while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) { WDT_HIT(); + if (check == 1000) { if (BUTTON_PRESS()) return false; @@ -738,6 +751,8 @@ static bool em4x50_sim_send_listen_window(void) { } ++check; } + if (cond) + tval1[t] = GetTicks(); if (t >= 4 * EM4X50_T_TAG_FULL_PERIOD) SHORT_COIL(); @@ -753,6 +768,12 @@ static bool em4x50_sim_send_listen_window(void) { check = 0; // wait until SSC_CLK goes LOW + if (cond) { + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + while (AT91C_BASE_TC0->TC_CV > 0); + } + while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) { WDT_HIT(); if (check == 1000) { @@ -762,8 +783,16 @@ static bool em4x50_sim_send_listen_window(void) { } ++check; } + if (cond) + tval2[t] = GetTicks(); } + for (int t = 0; t < 5 * EM4X50_T_TAG_FULL_PERIOD; t++) { + //if (tval[t] > 4) + Dbprintf("%3i probably RM intialization found: delta = %i %i", t, tval1[t], tval2[t]); + } + Dbprintf(""); + return true; } @@ -1281,3 +1310,39 @@ void em4x50_sim(uint8_t *filename) { lf_finalize(); reply_ng(CMD_LF_EM4X50_SIM, status, NULL, 0); } + +void em4x50_test(em4x50_test_t *ett) { + + int status = PM3_EFAILED; + + em4x50_setup_read(); + + if (ett->field) { + LOW(GPIO_SSC_DOUT); + LED_A_ON(); + + if (DBGLEVEL >= DBG_DEBUG) + Dbprintf("switched field on"); + + status = 1; + } else { + HIGH(GPIO_SSC_DOUT); + LED_A_OFF(); + + if (DBGLEVEL >= DBG_DEBUG) + Dbprintf("switched field off"); + + status = 0; + } + + while (BUTTON_PRESS() == false) { + + if (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) { + Dbprintf("field on"); + } else if (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)){ + Dbprintf("field on"); + } + } + + reply_ng(CMD_LF_EM4X50_TEST, status, NULL, 0); +} diff --git a/armsrc/em4x50.h b/armsrc/em4x50.h index 9f9b38351..87451e198 100644 --- a/armsrc/em4x50.h +++ b/armsrc/em4x50.h @@ -22,5 +22,6 @@ void em4x50_login(uint32_t *password); void em4x50_sim(uint8_t *filename); void em4x50_reader(void); void em4x50_chk(uint8_t *filename); +void em4x50_test(em4x50_test_t *ett); #endif /* EM4X50_H */ diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 79b019a03..8182a822f 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -1158,6 +1158,43 @@ int CmdEM4x50Sim(const char *Cmd) { return resp.status; } +int CmdEM4x50Test(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "lf em 4x50 test", + "perform EM4x50 tests.", + "lf em 4x50 test --field 1 -> reader field on \n" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0("", "field", "field off/on"), + arg_param_end + }; + + CLIExecWithReturn(ctx, Cmd, argtable, true); + + em4x50_test_t ett; + ett.field = arg_get_lit(ctx, 1); + CLIParserFree(ctx); + + // start + clearCommandBuffer(); + PacketResponseNG resp; + SendCommandNG(CMD_LF_EM4X50_TEST, (uint8_t *)&ett, sizeof(ett)); + WaitForResponse(CMD_LF_EM4X50_TEST, &resp); + + // print response + if (resp.status == 1) { + PrintAndLogEx(SUCCESS, "Field switched " _GREEN_("on")); + } else if (resp.status == 0) { + PrintAndLogEx(SUCCESS, "Field switched " _GREEN_("off")); + } else { + PrintAndLogEx(FAILED, "Test call " _RED_("failed")); + } + + return resp.status; +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"brute", CmdEM4x50Brute, IfPm3EM4x50, "guess password of EM4x50"}, @@ -1175,6 +1212,7 @@ static command_t CommandTable[] = { {"eload", CmdEM4x50ELoad, IfPm3EM4x50, "upload dump of EM4x50 to emulator memory"}, {"esave", CmdEM4x50ESave, IfPm3EM4x50, "save emulator memory to file"}, {"eview", CmdEM4x50EView, IfPm3EM4x50, "view EM4x50 content in emulator memory"}, + {"test", CmdEM4x50Test, IfPm3EM4x50, "perform EM4x50 tests"}, {NULL, NULL, NULL, NULL} }; @@ -1188,3 +1226,4 @@ int CmdLFEM4X50(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } + diff --git a/client/src/cmdlfem4x50.h b/client/src/cmdlfem4x50.h index 0d5c04bc6..df9c587de 100644 --- a/client/src/cmdlfem4x50.h +++ b/client/src/cmdlfem4x50.h @@ -34,5 +34,6 @@ int CmdEM4x50ELoad(const char *Cmd); int CmdEM4x50ESave(const char *Cmd); int CmdEM4x50Chk(const char *Cmd); int CmdEM4x50EView(const char *Cmd); +int CmdEM4x50Test(const char *Cmd); #endif diff --git a/include/em4x50.h b/include/em4x50.h index 573c58375..27d71e661 100644 --- a/include/em4x50.h +++ b/include/em4x50.h @@ -46,6 +46,10 @@ typedef struct { uint32_t addresses; } PACKED em4x50_data_t; +typedef struct { + bool field; +} PACKED em4x50_test_t; + typedef struct { uint8_t byte[4]; } PACKED em4x50_word_t; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index e3dc29aee..022b602e3 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -516,6 +516,7 @@ typedef struct { #define CMD_LF_EM4X50_READER 0x0251 #define CMD_LF_EM4X50_ESET 0x0252 #define CMD_LF_EM4X50_CHK 0x0253 +#define CMD_LF_EM4X50_TEST 0x0254 #define CMD_LF_EM4X70_INFO 0x0260 #define CMD_LF_EM4X70_WRITE 0x0261 #define CMD_LF_EM4X70_UNLOCK 0x0262