Add option to define extra symbols for 'lf cmdread', required e.g. for Hitag Micro and for talking to HT2 in emulation mode

This commit is contained in:
Philippe Teuwen 2020-09-17 17:17:28 +02:00
parent 5a109122d3
commit 4ec7bca270
5 changed files with 65 additions and 32 deletions

View file

@ -770,13 +770,15 @@ static void PacketReceived(PacketCommandNG *packet) {
case CMD_LF_MOD_THEN_ACQ_RAW_ADC: { case CMD_LF_MOD_THEN_ACQ_RAW_ADC: {
struct p { struct p {
uint32_t delay; uint32_t delay;
uint16_t ones; uint16_t period_0;
uint16_t zeros; 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; uint32_t samples : 31;
bool verbose : 1; bool verbose : 1;
} PACKED; } PACKED;
struct p *payload = (struct p *)packet->data.asBytes; 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; break;
} }
case CMD_LF_SNIFF_RAW_ADC: { case CMD_LF_SNIFF_RAW_ADC: {

View file

@ -383,13 +383,15 @@ void loadT55xxConfig(void) {
* @param period_1 * @param period_1
* @param command (in binary char array) * @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); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// use lf config settings // use lf config settings
sample_config *sc = getSamplingConfig(); 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 // Make sure the tag is reset
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@ -402,15 +404,14 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint
// clear read buffer // clear read buffer
BigBuf_Clear_keep_EM(); 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. // if delay_off = 0 then just bitbang 1 = antenna on 0 = off for respective periods.
bool bitbang = (delay_off == 0); bool bitbang = (delay_off == 0);
// now modulate the reader field // 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) { if (bitbang) {
TurnReadLFOn(20000);
// HACK it appears the loop and if statements take up about 7us so adjust waits accordingly... // HACK it appears the loop and if statements take up about 7us so adjust waits accordingly...
uint8_t hack_cnt = 7; uint8_t hack_cnt = 7;
if (period_0 < hack_cnt || period_1 < hack_cnt) { 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 } else { // old mode of cmd read using delay as off period
while (*command != '\0' && *command != ' ') { while (*command != '\0' && *command != ' ') {
LED_D_ON(); LED_D_ON();
if (*(command++) == '0') if (*command == '0') {
TurnReadLFOn(period_0); TurnReadLFOn(period_0);
else } else if (*command == '1') {
TurnReadLFOn(period_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(); LED_D_OFF();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
WaitUS(delay_off); WaitUS(delay_off);

View file

@ -15,7 +15,7 @@
#include "pm3_cmd.h" // struct #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 ReadTItag(void);
void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc); void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);

View file

@ -56,29 +56,36 @@
#include "cmdlfmotorola.h" // for Motorola menu #include "cmdlfmotorola.h" // for Motorola menu
#include "cmdlfgallagher.h" // for GALLAGHER menu #include "cmdlfgallagher.h" // for GALLAGHER menu
#define LF_CMDREAD_MAX_EXTRA_SYMBOLS 4
static bool g_lf_threshold_set = false; static bool g_lf_threshold_set = false;
static int CmdHelp(const char *Cmd); static int CmdHelp(const char *Cmd);
static int usage_lf_cmdread(void) { static int usage_lf_cmdread(void) {
PrintAndLogEx(NORMAL, "Usage: lf cmdread d <delay period> z <zero period> o <one period> c <cmdbytes> [q] [s #samples] [@]"); PrintAndLogEx(NORMAL, "Usage: lf cmdread d <delay duration> z <zero duration> o <one duration> [e <symbol> <duration>] c <cmd symbols> [q] [s #samples] [@]");
PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " h This help");
PrintAndLogEx(NORMAL, " d <delay> delay OFF period, (0 for bitbang mode) (decimal)"); PrintAndLogEx(NORMAL, " d <duration> delay OFF period, (0 for bitbang mode)");
PrintAndLogEx(NORMAL, " z <zero> ZERO time period (decimal)"); PrintAndLogEx(NORMAL, " z <duration> ZERO time period");
PrintAndLogEx(NORMAL, " o <one> ONE time period (decimal)"); PrintAndLogEx(NORMAL, " o <duration> ONE time period");
PrintAndLogEx(NORMAL, " c <cmd> Command bytes (in ones and zeros)"); PrintAndLogEx(NORMAL, " e <symbol> <duration> Extra symbol definition and duration (up to %i)", LF_CMDREAD_MAX_EXTRA_SYMBOLS);
PrintAndLogEx(NORMAL, " q silent (optional)"); PrintAndLogEx(NORMAL, " b <duration> B period");
PrintAndLogEx(NORMAL, " s #samples number of samples to collect (optional)"); PrintAndLogEx(NORMAL, " c <cmd> Command symbols (0/1/...)");
PrintAndLogEx(NORMAL, " @ run continuously until a key is pressed (optional)"); 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, "");
PrintAndLogEx(NORMAL, " ************* " _YELLOW_("All periods in microseconds (us)")); PrintAndLogEx(NORMAL, " ************* " _YELLOW_("All periods in decimal and in microseconds (μs)"));
PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, "Examples:");
PrintAndLogEx(NORMAL, "- probing for HT2:"); PrintAndLogEx(NORMAL, "- probing for Hitag 1/Hitag S:");
PrintAndLogEx(NORMAL, " lf cmdread d 50 z 116 o 166 c 011000"); PrintAndLogEx(NORMAL, " lf cmdread d 50 z 116 o 166 e W 3000 c W00110");
PrintAndLogEx(NORMAL, "- probing for HT2, oscilloscope style:"); 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, " 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, "Extras:");
PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")" to set parameters."); PrintAndLogEx(NORMAL, " use " _YELLOW_("'lf config'")" to set parameters.");
return PM3_SUCCESS; return PM3_SUCCESS;
@ -324,17 +331,20 @@ int CmdLFCommandRead(const char *Cmd) {
uint32_t samples = 0; uint32_t samples = 0;
uint16_t datalen = 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 { struct p {
uint32_t delay; uint32_t delay;
uint16_t ones; uint16_t period_0;
uint16_t zeros; 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; uint32_t samples : 31;
bool verbose : 1; bool verbose : 1;
uint8_t data[PM3_CMD_DATA_SIZE - payload_header_size]; uint8_t data[PM3_CMD_DATA_SIZE - payload_header_size];
} PACKED payload; } PACKED payload;
payload.samples = samples; payload.samples = samples;
payload.verbose = verbose; payload.verbose = verbose;
uint8_t index_extra = 0;
uint8_t cmdp = 0; uint8_t cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
@ -350,13 +360,24 @@ int CmdLFCommandRead(const char *Cmd) {
cmdp += 2; cmdp += 2;
break; break;
case 'z': // zero 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; cmdp += 2;
break; break;
case 'o': // ones 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; cmdp += 2;
break; 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': case 's':
samples = param_get32ex(Cmd, cmdp + 1, 0, 10); samples = param_get32ex(Cmd, cmdp + 1, 0, 10);
payload.samples = samples; payload.samples = samples;
@ -380,7 +401,7 @@ int CmdLFCommandRead(const char *Cmd) {
// bitbang mode // bitbang mode
if (payload.delay == 0) { 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"); PrintAndLogEx(WARNING, "warning periods cannot be less than 7us in bit bang mode");
return PM3_EINVARG; return PM3_EINVARG;
} }

View file

@ -786,6 +786,7 @@ typedef struct {
#define LF_DIVISOR_125 LF_FREQ2DIV(125) #define LF_DIVISOR_125 LF_FREQ2DIV(125)
#define LF_DIVISOR_134 LF_FREQ2DIV(134.2) #define LF_DIVISOR_134 LF_FREQ2DIV(134.2)
#define LF_DIV2FREQ(d) (12000.0/((d)+1)) #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 // Receiving from USART need more than 30ms as we used on USB
// else we get errors about partial packet reception // else we get errors about partial packet reception