diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 0fc9dd63d..5aaa46bd8 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -770,13 +770,15 @@ static void PacketReceived(PacketCommandNG *packet) { case CMD_LF_MOD_THEN_ACQ_RAW_ADC: { struct p { uint32_t delay; - uint16_t ones; - uint16_t zeros; + uint16_t period_0; + uint16_t period_1; + uint8_t symbol_extra[LF_CMDREAD_MAX_EXTRA_SYMBOLS]; + uint16_t period_extra[LF_CMDREAD_MAX_EXTRA_SYMBOLS]; uint32_t samples : 31; bool verbose : 1; } PACKED; struct p *payload = (struct p *)packet->data.asBytes; - ModThenAcquireRawAdcSamples125k(payload->delay, payload->zeros, payload->ones, packet->data.asBytes + sizeof(struct p), payload->verbose, payload->samples); + ModThenAcquireRawAdcSamples125k(payload->delay, payload->period_0, payload->period_1, payload->symbol_extra, payload->period_extra, packet->data.asBytes + sizeof(struct p), payload->verbose, payload->samples); break; } case CMD_LF_SNIFF_RAW_ADC: { diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 8c4b1e454..324f8ae0e 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -383,13 +383,15 @@ void loadT55xxConfig(void) { * @param period_1 * @param command (in binary char array) */ -void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command, bool verbose, uint32_t samples) { +void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint16_t period_0, uint16_t period_1, uint8_t *symbol_extra, uint16_t *period_extra, uint8_t *command, bool verbose, uint32_t samples) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // use lf config settings sample_config *sc = getSamplingConfig(); + LFSetupFPGAForADC(sc->divisor, true); + // this causes the field to turn on for uncontrolled amount of time, so we'll turn it off // Make sure the tag is reset FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -402,15 +404,14 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint // clear read buffer BigBuf_Clear_keep_EM(); - LFSetupFPGAForADC(sc->divisor, true); - - // little more time for the tag to fully power up - WaitMS(20); - // if delay_off = 0 then just bitbang 1 = antenna on 0 = off for respective periods. bool bitbang = (delay_off == 0); // now modulate the reader field + + // Some tags need to be interrogated very soon after activation else they enter their emulation mode + // Therefore it's up to the caller to add an initial symbol of adequate duration, except for bitbang mode. if (bitbang) { + TurnReadLFOn(20000); // HACK it appears the loop and if statements take up about 7us so adjust waits accordingly... uint8_t hack_cnt = 7; if (period_0 < hack_cnt || period_1 < hack_cnt) { @@ -459,11 +460,19 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint } else { // old mode of cmd read using delay as off period while (*command != '\0' && *command != ' ') { LED_D_ON(); - if (*(command++) == '0') + if (*command == '0') { TurnReadLFOn(period_0); - else + } else if (*command == '1') { TurnReadLFOn(period_1); - + } else { + for (uint8_t i=0; i < LF_CMDREAD_MAX_EXTRA_SYMBOLS; i++) { + if (*command == symbol_extra[i]) { + TurnReadLFOn(period_extra[i]); + break; + } + } + } + command++; LED_D_OFF(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(delay_off); diff --git a/armsrc/lfops.h b/armsrc/lfops.h index 17c79ef61..0ac8066af 100644 --- a/armsrc/lfops.h +++ b/armsrc/lfops.h @@ -15,7 +15,7 @@ #include "pm3_cmd.h" // struct -void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command, bool verbose, uint32_t samples); +void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint16_t period_0, uint16_t period_1, uint8_t *symbol_extra, uint16_t *period_extra, uint8_t *command, bool verbose, uint32_t samples); void ReadTItag(void); void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc); diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index f7ffab795..98c794b69 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -56,29 +56,36 @@ #include "cmdlfmotorola.h" // for Motorola menu #include "cmdlfgallagher.h" // for GALLAGHER menu +#define LF_CMDREAD_MAX_EXTRA_SYMBOLS 4 static bool g_lf_threshold_set = false; static int CmdHelp(const char *Cmd); static int usage_lf_cmdread(void) { - PrintAndLogEx(NORMAL, "Usage: lf cmdread d z o c [q] [s #samples] [@]"); + PrintAndLogEx(NORMAL, "Usage: lf cmdread d z o [e ] c [q] [s #samples] [@]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " d delay OFF period, (0 for bitbang mode) (decimal)"); - PrintAndLogEx(NORMAL, " z ZERO time period (decimal)"); - PrintAndLogEx(NORMAL, " o ONE time period (decimal)"); - PrintAndLogEx(NORMAL, " c Command bytes (in ones and zeros)"); - PrintAndLogEx(NORMAL, " q silent (optional)"); - PrintAndLogEx(NORMAL, " s #samples number of samples to collect (optional)"); - PrintAndLogEx(NORMAL, " @ run continuously until a key is pressed (optional)"); + PrintAndLogEx(NORMAL, " d delay OFF period, (0 for bitbang mode)"); + PrintAndLogEx(NORMAL, " z ZERO time period"); + PrintAndLogEx(NORMAL, " o ONE time period"); + PrintAndLogEx(NORMAL, " e Extra symbol definition and duration (up to %i)", LF_CMDREAD_MAX_EXTRA_SYMBOLS); + PrintAndLogEx(NORMAL, " b B period"); + PrintAndLogEx(NORMAL, " c Command symbols (0/1/...)"); + PrintAndLogEx(NORMAL, " q silent (optional)"); + PrintAndLogEx(NORMAL, " s #samples number of samples to collect (optional)"); + PrintAndLogEx(NORMAL, " @ run continuously until a key is pressed (optional)"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " ************* " _YELLOW_("All periods in microseconds (us)")); + PrintAndLogEx(NORMAL, " ************* " _YELLOW_("All periods in decimal and in microseconds (μs)")); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, "- probing for HT2:"); - PrintAndLogEx(NORMAL, " lf cmdread d 50 z 116 o 166 c 011000"); - PrintAndLogEx(NORMAL, "- probing for HT2, oscilloscope style:"); + PrintAndLogEx(NORMAL, "- probing for Hitag 1/Hitag S:"); + PrintAndLogEx(NORMAL, " lf cmdread d 50 z 116 o 166 e W 3000 c W00110"); + PrintAndLogEx(NORMAL, "- probing for Hitag 2:"); + PrintAndLogEx(NORMAL, " lf cmdread d 50 z 116 o 166 e W 3000 c W11000"); + PrintAndLogEx(NORMAL, "- probing for Hitag 2, oscilloscope style:"); PrintAndLogEx(NORMAL, " data plot"); - PrintAndLogEx(NORMAL, " lf cmdread d 50 z 116 o 166 c 011000 q s 2000 @"); + PrintAndLogEx(NORMAL, " lf cmdread d 50 z 116 o 166 e W 3000 c W11000 q s 2000 @"); + PrintAndLogEx(NORMAL, "- probing for Hitag μ:"); + PrintAndLogEx(NORMAL, " lf cmdread d 48 z 112 o 176 e W 3000 e S 240 e E 336 c W0S00000010000E"); PrintAndLogEx(NORMAL, "Extras:"); PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")" to set parameters."); return PM3_SUCCESS; @@ -324,17 +331,20 @@ int CmdLFCommandRead(const char *Cmd) { uint32_t samples = 0; uint16_t datalen = 0; - const uint8_t payload_header_size = 12; + const uint8_t payload_header_size = 12 + (3 * LF_CMDREAD_MAX_EXTRA_SYMBOLS); struct p { uint32_t delay; - uint16_t ones; - uint16_t zeros; + uint16_t period_0; + uint16_t period_1; + uint8_t symbol_extra[LF_CMDREAD_MAX_EXTRA_SYMBOLS]; + uint16_t period_extra[LF_CMDREAD_MAX_EXTRA_SYMBOLS]; uint32_t samples : 31; bool verbose : 1; uint8_t data[PM3_CMD_DATA_SIZE - payload_header_size]; } PACKED payload; payload.samples = samples; payload.verbose = verbose; + uint8_t index_extra = 0; uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { @@ -350,13 +360,24 @@ int CmdLFCommandRead(const char *Cmd) { cmdp += 2; break; case 'z': // zero - payload.zeros = param_get32ex(Cmd, cmdp + 1, 0, 10) & 0xFFFF; + payload.period_0 = param_get32ex(Cmd, cmdp + 1, 0, 10) & 0xFFFF; cmdp += 2; break; case 'o': // ones - payload.ones = param_get32ex(Cmd, cmdp + 1, 0, 10) & 0xFFFF; + payload.period_1 = param_get32ex(Cmd, cmdp + 1, 0, 10) & 0xFFFF; cmdp += 2; break; + case 'e': // extra symbol definition + if (index_extra < LF_CMDREAD_MAX_EXTRA_SYMBOLS - 1) { + payload.symbol_extra[index_extra] = param_getchar(Cmd, cmdp + 1); + payload.period_extra[index_extra] = param_get32ex(Cmd, cmdp + 2, 0, 10) & 0xFFFF; + index_extra++; + cmdp += 3; + } else { + PrintAndLogEx(WARNING, "Too many extra symbols, please define up to %i symbols", LF_CMDREAD_MAX_EXTRA_SYMBOLS); + errors = true; + } + break; case 's': samples = param_get32ex(Cmd, cmdp + 1, 0, 10); payload.samples = samples; @@ -380,7 +401,7 @@ int CmdLFCommandRead(const char *Cmd) { // bitbang mode if (payload.delay == 0) { - if (payload.zeros < 7 || payload.ones < 7) { + if (payload.period_0 < 7 || payload.period_1 < 7) { PrintAndLogEx(WARNING, "warning periods cannot be less than 7us in bit bang mode"); return PM3_EINVARG; } diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 78fca9c62..6cacc5ef1 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -786,6 +786,7 @@ typedef struct { #define LF_DIVISOR_125 LF_FREQ2DIV(125) #define LF_DIVISOR_134 LF_FREQ2DIV(134.2) #define LF_DIV2FREQ(d) (12000.0/((d)+1)) +#define LF_CMDREAD_MAX_EXTRA_SYMBOLS 4 // Receiving from USART need more than 30ms as we used on USB // else we get errors about partial packet reception