textual
[RRG-proxmark3.git] / client / src / cmdlf.c
blob25b304c9e27ac03e1e606d4cd725291c87f3a9d9
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
3 // Modified by
4 // Marshellow
5 // Iceman
6 // Doegox
7 //
8 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
9 // at your option, any later version. See the LICENSE.txt file for the text of
10 // the license.
11 //-----------------------------------------------------------------------------
12 // Low frequency commands
13 //-----------------------------------------------------------------------------
14 #include "cmdlf.h"
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <limits.h>
19 #include <ctype.h>
20 #include "cmdparser.h" // command_t
21 #include "comms.h"
22 #include "commonutil.h" // ARRAYLEN
23 #include "lfdemod.h" // device/client demods of LF signals
24 #include "ui.h" // for show graph controls
25 #include "proxgui.h"
26 #include "cliparser.h" // args parsing
27 #include "graph.h" // for graph data
28 #include "cmddata.h" // for `lf search`
29 #include "cmdlfawid.h" // for awid menu
30 #include "cmdlfem.h" // for em menu
31 #include "cmdlfem410x.h" // for em4x menu
32 #include "cmdlfem4x05.h" // for em4x05 / 4x69
33 #include "cmdlfem4x50.h" // for em4x50
34 #include "cmdlfem4x70.h" // for em4x70
35 #include "cmdlfhid.h" // for hid menu
36 #include "cmdlfhitag.h" // for hitag menu
37 #include "cmdlfidteck.h" // for idteck menu
38 #include "cmdlfio.h" // for ioprox menu
39 #include "cmdlfcotag.h" // for COTAG meny
40 #include "cmdlfdestron.h" // for FDX-A FECAVA Destron menu
41 #include "cmdlffdxb.h" // for FDX-B menu
42 #include "cmdlfgallagher.h" // for GALLAGHER menu
43 #include "cmdlfguard.h" // for gproxii menu
44 #include "cmdlfindala.h" // for indala menu
45 #include "cmdlfjablotron.h" // for JABLOTRON menu
46 #include "cmdlfkeri.h" // for keri menu
47 #include "cmdlfmotorola.h" // for Motorola menu
48 #include "cmdlfnedap.h" // for NEDAP menu
49 #include "cmdlfnexwatch.h" // for nexwatch menu
50 #include "cmdlfnoralsy.h" // for NORALSY meny
51 #include "cmdlfpac.h" // for pac menu
52 #include "cmdlfparadox.h" // for paradox menu
53 #include "cmdlfpcf7931.h" // for pcf7931 menu
54 #include "cmdlfpresco.h" // for presco menu
55 #include "cmdlfpyramid.h" // for pyramid menu
56 #include "cmdlfsecurakey.h" // for securakey menu
57 #include "cmdlft55xx.h" // for t55xx menu
58 #include "cmdlfti.h" // for ti menu
59 #include "cmdlfviking.h" // for viking menu
60 #include "cmdlfvisa2000.h" // for VISA2000 menu
61 #include "pm3_cmd.h" // for LF_CMDREAD_MAX_EXTRA_SYMBOLS
63 static bool g_lf_threshold_set = false;
65 static int CmdHelp(const char *Cmd);
67 // Informative user function.
68 // loop and wait for either keyboard press or pm3 button to exit
69 // if key event, send break loop cmd to Pm3
70 int lfsim_wait_check(uint32_t cmd) {
71 PrintAndLogEx(NORMAL, "");
72 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " or pm3-button to abort simulation");
74 for (;;) {
75 if (kbd_enter_pressed()) {
76 SendCommandNG(CMD_BREAK_LOOP, NULL, 0);
77 PrintAndLogEx(DEBUG, "User aborted");
78 break;
81 PacketResponseNG resp;
82 if (WaitForResponseTimeout(cmd, &resp, 1000)) {
83 if (resp.status == PM3_EOPABORTED) {
84 PrintAndLogEx(DEBUG, "Button pressed, user aborted");
85 break;
89 PrintAndLogEx(INFO, "Done");
90 return PM3_SUCCESS;
93 static int CmdLFTune(const char *Cmd) {
95 CLIParserContext *ctx;
96 CLIParserInit(&ctx, "lf tune",
97 "Continuously measure LF antenna tuning.\n"
98 "Press button or <Enter> to interrupt.",
99 "lf tune\n"
100 "lf tune --mix"
103 char q_str[60];
104 snprintf(q_str, sizeof(q_str), "Frequency divisor. %d -> 134 kHz, %d -> 125 kHz", LF_DIVISOR_134, LF_DIVISOR_125);
105 void *argtable[] = {
106 arg_param_begin,
107 arg_u64_0("n", "iter", "<dec>", "number of iterations (default: 0=infinite)"),
108 arg_u64_0("q", "divisor", "<dec>", q_str),
109 arg_dbl0("f", "freq", "<float>", "Frequency in kHz"),
110 arg_lit0(NULL, "bar", "bar style"),
111 arg_lit0(NULL, "mix", "mixed style"),
112 arg_lit0(NULL, "value", "values style"),
113 arg_param_end
115 CLIExecWithReturn(ctx, Cmd, argtable, true);
116 uint32_t iter = arg_get_u32_def(ctx, 1, 0);
117 uint8_t divisor = arg_get_u32_def(ctx, 2, LF_DIVISOR_125);
118 double freq = arg_get_dbl_def(ctx, 3, 125);
120 bool is_bar = arg_get_lit(ctx, 4);
121 bool is_mix = arg_get_lit(ctx, 5);
122 bool is_value = arg_get_lit(ctx, 6);
123 CLIParserFree(ctx);
125 if (divisor < 19) {
126 PrintAndLogEx(ERR, "divisor must be between 19 and 255");
127 return PM3_EINVARG;
130 if ((freq < 47) || (freq > 600)) {
131 PrintAndLogEx(ERR, "freq must be between 47 and 600");
132 return PM3_EINVARG;
134 divisor = LF_FREQ2DIV(freq);
136 if ((is_bar + is_mix + is_value) > 1) {
137 PrintAndLogEx(ERR, "Select only one output style");
138 return PM3_EINVARG;
141 barMode_t style = session.bar_mode;
142 if (is_bar)
143 style = STYLE_BAR;
144 if (is_mix)
145 style = STYLE_MIXED;
146 if (is_value)
147 style = STYLE_VALUE;
149 PrintAndLogEx(INFO, "Measuring LF antenna at " _YELLOW_("%.2f") " kHz, click " _GREEN_("pm3 button") " or press " _GREEN_("Enter") " to exit", LF_DIV2FREQ(divisor));
151 uint8_t params[] = {1, 0};
152 params[1] = divisor;
153 PacketResponseNG resp;
154 clearCommandBuffer();
156 SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_LF, params, sizeof(params));
157 if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_LF, &resp, 1000)) {
158 PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark LF initialization, aborting");
159 return PM3_ETIMEOUT;
162 params[0] = 2;
164 // #define MAX_ADC_LF_VOLTAGE 140800
165 uint32_t max = 71000;
166 bool first = true;
168 print_progress(0, max, style);
170 // loop forever (till button pressed) if iter = 0 (default)
171 for (uint8_t i = 0; iter == 0 || i < iter; i++) {
172 if (kbd_enter_pressed()) {
173 break;
176 SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_LF, params, sizeof(params));
177 if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_LF, &resp, 1000)) {
178 PrintAndLogEx(NORMAL, "");
179 PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark LF measure, aborting");
180 break;
183 if ((resp.status == PM3_EOPABORTED) || (resp.length != sizeof(uint32_t))) {
184 PrintAndLogEx(NORMAL, "");
185 break;
188 uint32_t volt = resp.data.asDwords[0];
189 if (first) {
190 max = (volt * 1.03);
191 first = false;
193 if (volt > max) {
194 max = (volt * 1.03);
196 print_progress(volt, max, style);
199 params[0] = 3;
200 SendCommandNG(CMD_MEASURE_ANTENNA_TUNING_LF, params, sizeof(params));
201 if (!WaitForResponseTimeout(CMD_MEASURE_ANTENNA_TUNING_LF, &resp, 1000)) {
202 PrintAndLogEx(WARNING, "Timeout while waiting for Proxmark LF shutdown, aborting");
203 return PM3_ETIMEOUT;
205 PrintAndLogEx(NORMAL, "\x1b%c[2K\r", 30);
206 PrintAndLogEx(INFO, "Done.");
207 return PM3_SUCCESS;
210 /* send a LF command before reading */
211 int CmdLFCommandRead(const char *Cmd) {
212 CLIParserContext *ctx;
213 CLIParserInit(&ctx, "lf cmdread",
214 "Modulate LF reader field to send command before read. All periods in microseconds.\n"
215 " - use " _YELLOW_("`lf config`") _CYAN_(" to set parameters"),
216 "lf cmdread -d 50 -z 116 -o 166 -e W3000 -c W00110 --> probing for Hitag 1/S\n"
217 "lf cmdread -d 50 -z 116 -o 166 -e W3000 -c W11000 --> probing for Hitag 2\n"
218 "lf cmdread -d 50 -z 116 -o 166 -e W3000 -c W11000 -q -s 2000 -@ --> probing for Hitag 2, oscilloscope style\n"
219 "lf cmdread -d 48 -z 112 -o 176 -e W3000 -e S240 -e E336 -c W0S00000010000E --> probing for Hitag (us)\n"
222 char div_str[70] = {0};
223 sprintf(div_str, "Extra symbol definition and duration (up to %i)", LF_CMDREAD_MAX_EXTRA_SYMBOLS);
225 void *argtable[] = {
226 arg_param_begin,
227 arg_u64_0("d", "duration", "<us>", "delay OFF period, (0 for bitbang mode)"),
228 arg_str0("c", "cmd", "<0|1|...>", "command symbols"),
229 arg_strx0("e", "extra", "<us>", div_str),
230 arg_u64_0("o", "one", "<us>", "ONE time period"),
231 arg_u64_0("z", "zero", "<us>", "ZERO time period"),
232 arg_u64_0("s", "samples", "<dec>", "number of samples to collect"),
233 arg_lit0("v", "verbose", "verbose output"),
234 arg_lit0("@", NULL, "continuous mode"),
235 arg_param_end
237 CLIExecWithReturn(ctx, Cmd, argtable, false);
238 uint32_t delay = arg_get_u32_def(ctx, 1, 0);
240 int cmd_len = 128;
241 char cmd[128] = {0};
242 CLIGetStrWithReturn(ctx, 2, (uint8_t *)cmd, &cmd_len);
244 int extra_arg_len = 250;
245 char extra_arg[250] = {0};
246 CLIGetStrWithReturn(ctx, 3, (uint8_t *)extra_arg, &extra_arg_len);
248 uint16_t period_1 = arg_get_u32_def(ctx, 4, 0);
249 uint16_t period_0 = arg_get_u32_def(ctx, 5, 0);
250 uint32_t samples = arg_get_u32_def(ctx, 6, 0);
251 bool verbose = arg_get_lit(ctx, 7);
252 bool cm = arg_get_lit(ctx, 8);
253 CLIParserFree(ctx);
255 if (session.pm3_present == false)
256 return PM3_ENOTTY;
258 #define PAYLOAD_HEADER_SIZE (12 + (3 * LF_CMDREAD_MAX_EXTRA_SYMBOLS))
259 struct p {
260 uint32_t delay;
261 uint16_t period_0;
262 uint16_t period_1;
263 uint8_t symbol_extra[LF_CMDREAD_MAX_EXTRA_SYMBOLS];
264 uint16_t period_extra[LF_CMDREAD_MAX_EXTRA_SYMBOLS];
265 uint32_t samples : 31;
266 bool verbose : 1;
267 uint8_t data[PM3_CMD_DATA_SIZE - PAYLOAD_HEADER_SIZE];
268 } PACKED payload;
269 payload.delay = delay;
270 payload.period_1 = period_1;
271 payload.period_0 = period_0;
272 payload.samples = samples;
273 payload.verbose = verbose;
274 memcpy(payload.data, cmd, cmd_len);
276 // extra symbol definition
277 uint8_t index_extra = 0;
278 int i = 0;
279 for (; i < extra_arg_len;) {
281 if (index_extra < LF_CMDREAD_MAX_EXTRA_SYMBOLS - 1) {
282 payload.symbol_extra[index_extra] = extra_arg[i];
283 int tmp = atoi(extra_arg + (i + 1));
284 payload.period_extra[index_extra] = tmp;
285 index_extra++;
286 i++;
287 while (extra_arg[i] >= 0x30 && extra_arg[i] <= 0x39)
288 i++;
290 } else {
291 PrintAndLogEx(WARNING, "Too many extra symbols, please define up to %i symbols", LF_CMDREAD_MAX_EXTRA_SYMBOLS);
295 // bitbang mode
296 if (payload.delay == 0) {
297 if (payload.period_0 < 7 || payload.period_1 < 7) {
298 PrintAndLogEx(WARNING, "periods cannot be less than 7us in bit bang mode");
299 return PM3_EINVARG;
303 PrintAndLogEx(DEBUG, "Cmd read - settings");
304 PrintAndLogEx(DEBUG, "-------------------");
305 PrintAndLogEx(DEBUG, "delay: %u , zero %u , one %u , samples %u", payload.delay, payload.period_0, payload.period_1, payload.samples);
306 PrintAndLogEx(DEBUG, "Extra symbols");
307 PrintAndLogEx(DEBUG, "-------------");
308 for (i = 0; i < LF_CMDREAD_MAX_EXTRA_SYMBOLS; i++) {
309 if (payload.symbol_extra[i] == 0x00)
310 continue;
312 PrintAndLogEx(DEBUG, " %c - %u", payload.symbol_extra[i], payload.period_extra[i]);
314 PrintAndLogEx(DEBUG, "data: %s", payload.data);
316 if (cm) {
317 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
320 if (verbose) {
321 PrintAndLogEx(SUCCESS, "Sending command...");
324 int ret = PM3_SUCCESS;
325 do {
326 clearCommandBuffer();
327 SendCommandNG(CMD_LF_MOD_THEN_ACQ_RAW_ADC, (uint8_t *)&payload, PAYLOAD_HEADER_SIZE + cmd_len);
329 PacketResponseNG resp;
331 i = 10;
332 // 20sec wait loop
333 while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) {
334 if (verbose) {
335 PrintAndLogEx(NORMAL, "." NOLF);
337 i--;
339 if (verbose) {
340 PrintAndLogEx(NORMAL, "");
342 if (resp.status != PM3_SUCCESS) {
343 PrintAndLogEx(WARNING, "command failed.");
344 return PM3_ESOFT;
347 if (i) {
348 if (verbose) {
349 PrintAndLogEx(SUCCESS, "downloading response signal data");
351 getSamples(samples, false);
352 ret = PM3_SUCCESS;
353 } else {
354 PrintAndLogEx(WARNING, "timeout while waiting for reply.");
355 return PM3_ETIMEOUT;
358 } while (cm && kbd_enter_pressed() == false);
359 return ret;
362 int CmdFlexdemod(const char *Cmd) {
363 (void)Cmd; // Cmd is not used so far
365 #ifndef LONG_WAIT
366 #define LONG_WAIT 100
367 #endif
368 int i, j, start, bit, sum;
370 int data[GraphTraceLen];
371 memcpy(data, GraphBuffer, GraphTraceLen);
373 size_t size = GraphTraceLen;
375 for (i = 0; i < GraphTraceLen; ++i)
376 data[i] = (data[i] < 0) ? -1 : 1;
378 for (start = 0; start < size - LONG_WAIT; start++) {
379 int first = data[start];
380 for (i = start; i < start + LONG_WAIT; i++) {
381 if (data[i] != first) {
382 break;
385 if (i == (start + LONG_WAIT))
386 break;
389 if (start == size - LONG_WAIT) {
390 PrintAndLogEx(WARNING, "nothing to wait for");
391 return PM3_ENODATA;
394 data[start] = 4;
395 data[start + 1] = 0;
397 uint8_t bits[64] = {0x00};
399 i = start;
400 for (bit = 0; bit < 64; bit++) {
401 sum = 0;
402 for (j = 0; j < 16; j++) {
403 sum += data[i++];
405 bits[bit] = (sum > 0) ? 1 : 0;
406 PrintAndLogEx(NORMAL, "bit %d sum %d", bit, sum);
409 for (bit = 0; bit < 64; bit++) {
410 sum = 0;
411 for (j = 0; j < 16; j++)
412 sum += data[i++];
414 if (sum > 0 && bits[bit] != 1) PrintAndLogEx(WARNING, "oops1 at %d", bit);
416 if (sum < 0 && bits[bit] != 0) PrintAndLogEx(WARNING, "oops2 at %d", bit);
420 // iceman, use demod buffer? blue line?
421 // HACK writing back to graphbuffer.
422 GraphTraceLen = 32 * 64;
423 i = 0;
424 for (bit = 0; bit < 64; bit++) {
426 int phase = (bits[bit] == 0) ? 0 : 1;
428 for (j = 0; j < 32; j++) {
429 GraphBuffer[i++] = phase;
430 phase = !phase;
433 RepaintGraphWindow();
434 return PM3_SUCCESS;
437 int lf_getconfig(sample_config *config) {
438 if (!session.pm3_present) return PM3_ENOTTY;
440 if (config == NULL)
441 return PM3_EINVARG;
443 clearCommandBuffer();
445 SendCommandNG(CMD_LF_SAMPLING_GET_CONFIG, NULL, 0);
446 PacketResponseNG resp;
447 if (!WaitForResponseTimeout(CMD_LF_SAMPLING_GET_CONFIG, &resp, 2000)) {
448 PrintAndLogEx(WARNING, "command execution time out");
449 return PM3_ETIMEOUT;
451 memcpy(config, resp.data.asBytes, sizeof(sample_config));
452 return PM3_SUCCESS;
455 int lf_config(sample_config *config) {
456 if (!session.pm3_present) return PM3_ENOTTY;
458 clearCommandBuffer();
459 if (config != NULL)
460 SendCommandNG(CMD_LF_SAMPLING_SET_CONFIG, (uint8_t *)config, sizeof(sample_config));
461 else
462 SendCommandNG(CMD_LF_SAMPLING_PRINT_CONFIG, NULL, 0);
464 return PM3_SUCCESS;
467 int CmdLFConfig(const char *Cmd) {
468 CLIParserContext *ctx;
469 CLIParserInit(&ctx, "lf config",
470 "Get/Set config for LF sampling, bit/sample, decimation, frequency\n"
471 "These changes are temporary, will be reset after a power cycle.\n\n"
472 " - use " _YELLOW_("`lf read`") _CYAN_(" performs a read (active field)\n")
473 _CYAN_(" - use ") _YELLOW_("`lf sniff`") _CYAN_(" performs a sniff (no active field)"),
474 "lf config --> shows current config\n"
475 "lf config -b 8 --125 --> samples at 125 kHz, 8 bps\n"
476 "lf config -b 4 --134 --dec 3 --> samples at 134 kHz, averages three samples into one, stored with a resolution of 4 bits per sample\n"
477 "lf config --trig 20 -s 10000 --> trigger sampling when above 20, skip 10 000 first samples after triggered\n"
480 char div_str[70] = {0};
481 sprintf(div_str, "Manually set freq divisor. %d -> 134 kHz, %d -> 125 kHz", LF_DIVISOR_134, LF_DIVISOR_125);
483 void *argtable[] = {
484 arg_param_begin,
485 arg_lit0(NULL, "125", "125 kHz frequency"),
486 arg_lit0(NULL, "134", "134 kHz frequency"),
487 arg_int0("a", "avg", "<0|1>", "averaging - if set, will average the stored sample value when decimating (default 1)"),
488 arg_int0("b", "bps", "<1-8>", "sets resolution of bits per sample (default 8)"),
489 arg_int0(NULL, "dec", "<1-8>", "sets decimation. A value of N saves only 1 in N samples (default 1)"),
490 arg_int0(NULL, "divisor", "<19-255>", div_str),
491 arg_int0("f", "freq", "<47-600>", "manually set frequency in kHz"),
492 arg_lit0("r", "reset", "reset values to defaults"),
493 arg_int0("s", "skip", "<dec>", "sets a number of samples to skip before capture (default 0)"),
494 arg_int0("t", "trig", "<0-128>", "sets trigger threshold. 0 means no threshold"),
495 arg_param_end
497 CLIExecWithReturn(ctx, Cmd, argtable, true);
498 bool use_125 = arg_get_lit(ctx, 1);
499 bool use_134 = arg_get_lit(ctx, 2);
500 int8_t avg = arg_get_int_def(ctx, 3, 0);
501 int8_t bps = arg_get_int_def(ctx, 4, -1);
502 int8_t dec = arg_get_int_def(ctx, 5, -1);
503 int16_t divisor = arg_get_int_def(ctx, 6, -1);
504 int16_t freq = arg_get_int_def(ctx, 7, -1);
505 bool reset = arg_get_lit(ctx, 8);
506 int32_t skip = arg_get_int_def(ctx, 9, -1);
507 int16_t trigg = arg_get_int_def(ctx, 10, -1);
508 CLIParserFree(ctx);
510 if (session.pm3_present == false)
511 return PM3_ENOTTY;
513 // if called with no params, just print the device config
514 if (strlen(Cmd) == 0) {
515 return lf_config(NULL);
518 if (use_125 + use_134 > 1) {
519 PrintAndLogEx(ERR, "use only one of 125 or 134 params");
520 return PM3_EINVARG;
523 sample_config config = {
524 .decimation = -1,
525 .bits_per_sample = -1,
526 .averaging = -1,
527 .divisor = -1,
528 .trigger_threshold = -1,
529 .samples_to_skip = -1,
530 .verbose = true
533 if (reset) {
534 config.decimation = 1;
535 config.bits_per_sample = 8;
536 config.averaging = 1,
537 config.divisor = LF_DIVISOR_125;
538 config.samples_to_skip = 0;
539 config.trigger_threshold = 0;
540 g_lf_threshold_set = false;
543 if (use_125)
544 config.divisor = LF_DIVISOR_125;
546 if (use_134)
547 config.divisor = LF_DIVISOR_134;
549 config.averaging = (avg == 1);
551 if (bps > -1) {
552 // bps is limited to 8
553 config.bits_per_sample = (bps & 0x0F);
554 if (config.bits_per_sample > 8)
555 config.bits_per_sample = 8;
558 if (dec > -1) {
559 // decimation is limited to 8
560 config.decimation = (dec & 0x0F);
561 if (config.decimation > 8)
562 config.decimation = 8;
565 if (divisor > -1) {
566 config.divisor = divisor;
567 if (config.divisor < 19) {
568 PrintAndLogEx(ERR, "divisor must be between 19 and 255");
569 return PM3_EINVARG;
573 if (freq > -1) {
574 config.divisor = LF_FREQ2DIV(freq);
575 if (config.divisor < 19) {
576 PrintAndLogEx(ERR, "freq must be between 47 and 600");
577 return PM3_EINVARG;
581 if (trigg > -1) {
582 config.trigger_threshold = trigg;
583 g_lf_threshold_set = (config.trigger_threshold > 0);
586 config.samples_to_skip = skip;
587 return lf_config(&config);
590 int lf_read(bool verbose, uint32_t samples) {
591 if (!session.pm3_present) return PM3_ENOTTY;
593 struct p {
594 uint32_t samples : 31;
595 bool verbose : 1;
596 } PACKED;
598 struct p payload;
599 payload.verbose = verbose;
600 payload.samples = samples;
602 clearCommandBuffer();
603 SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
604 PacketResponseNG resp;
605 if (g_lf_threshold_set) {
606 WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp);
607 } else {
608 if (!WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500)) {
609 PrintAndLogEx(WARNING, "(lf_read) command execution time out");
610 return PM3_ETIMEOUT;
614 // response is number of bits read
615 uint32_t size = (resp.data.asDwords[0] / 8);
616 getSamples(size, verbose);
617 return PM3_SUCCESS;
620 int CmdLFRead(const char *Cmd) {
621 CLIParserContext *ctx;
622 CLIParserInit(&ctx, "lf read",
623 "Sniff low frequency signal.\n"
624 " - use " _YELLOW_("`lf config`") _CYAN_(" to set parameters.\n")
625 _CYAN_(" - use ") _YELLOW_("`data plot`") _CYAN_(" to look at it"),
626 "lf read -v -s 12000 --> collect 12000 samples\n"
627 "lf read -s 3000 -@ --> oscilloscope style \n"
630 void *argtable[] = {
631 arg_param_begin,
632 arg_u64_0("s", "samples", "<dec>", "number of samples to collect"),
633 arg_lit0("v", "verbose", "verbose output"),
634 arg_lit0("@", NULL, "continuous reading mode"),
635 arg_param_end
637 CLIExecWithReturn(ctx, Cmd, argtable, true);
638 uint32_t samples = arg_get_u32_def(ctx, 1, 0);
639 bool verbose = arg_get_lit(ctx, 2);
640 bool cm = arg_get_lit(ctx, 3);
641 CLIParserFree(ctx);
643 if (session.pm3_present == false)
644 return PM3_ENOTTY;
646 if (cm) {
647 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
649 int ret = PM3_SUCCESS;
650 do {
651 ret = lf_read(verbose, samples);
652 } while (cm && kbd_enter_pressed() == false);
653 return ret;
656 int lf_sniff(bool verbose, uint32_t samples) {
657 if (!session.pm3_present) return PM3_ENOTTY;
659 struct p {
660 uint32_t samples : 31;
661 bool verbose : 1;
662 } PACKED;
664 struct p payload;
665 payload.verbose = verbose;
666 payload.samples = samples;
668 clearCommandBuffer();
669 SendCommandNG(CMD_LF_SNIFF_RAW_ADC, (uint8_t *)&payload, sizeof(payload));
670 PacketResponseNG resp;
671 if (g_lf_threshold_set) {
672 WaitForResponse(CMD_LF_SNIFF_RAW_ADC, &resp);
673 } else {
674 if (!WaitForResponseTimeout(CMD_LF_SNIFF_RAW_ADC, &resp, 2500)) {
675 PrintAndLogEx(WARNING, "(lf_read) command execution time out");
676 return PM3_ETIMEOUT;
680 // response is number of bits read
681 uint32_t size = (resp.data.asDwords[0] / 8);
682 getSamples(size, verbose);
683 return PM3_SUCCESS;
686 int CmdLFSniff(const char *Cmd) {
687 CLIParserContext *ctx;
688 CLIParserInit(&ctx, "lf sniff",
689 "Sniff low frequency signal. You need to configure the LF part on the Proxmark3 device manually.\n"
690 "Usually a trigger and skip samples is a good thing to set before doing a low frequency sniff.\n"
691 "\n"
692 " - use " _YELLOW_("`lf config`") _CYAN_(" to set parameters.\n")
693 _CYAN_(" - use ") _YELLOW_("`data plot`") _CYAN_(" to look at sniff signal.\n")
694 _CYAN_(" - use ") _YELLOW_("`lf search -1`") _CYAN_(" to see if signal can be automatic decoded\n"),
695 "lf sniff -v\n"
696 "lf sniff -s 3000 -@ --> oscilloscope style \n"
699 void *argtable[] = {
700 arg_param_begin,
701 arg_u64_0("s", "samples", "<dec>", "number of samples to collect"),
702 arg_lit0("v", "verbose", "verbose output"),
703 arg_lit0("@", NULL, "continuous sniffing mode"),
704 arg_param_end
706 CLIExecWithReturn(ctx, Cmd, argtable, true);
707 uint32_t samples = arg_get_u32_def(ctx, 1, 0);
708 bool verbose = arg_get_lit(ctx, 2);
709 bool cm = arg_get_lit(ctx, 3);
710 CLIParserFree(ctx);
712 if (session.pm3_present == false)
713 return PM3_ENOTTY;
715 if (cm) {
716 PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
718 int ret = PM3_SUCCESS;
719 do {
720 ret = lf_sniff(verbose, samples);
721 } while (cm && !kbd_enter_pressed());
722 return ret;
725 static void lf_chk_bitstream(void) {
726 // convert to bitstream if necessary
727 for (int i = 0; i < (int)(GraphTraceLen / 2); i++) {
728 if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0) {
729 CmdGetBitStream("");
730 PrintAndLogEx(INFO, "converted Graphbuffer to bitstream values (0|1)");
731 break;
736 // Uploads GraphBuffer to device, in order to be used for LF SIM.
737 int lfsim_upload_gb(void) {
738 PrintAndLogEx(DEBUG, "DEBUG: Uploading %zu bytes", GraphTraceLen);
740 struct pupload {
741 uint8_t flag;
742 uint16_t offset;
743 uint8_t data[PM3_CMD_DATA_SIZE - 3];
744 } PACKED payload_up;
746 // flag =
747 // b0 0
748 // 1 clear bigbuff
749 payload_up.flag = 0x1;
751 // fast push mode
752 conn.block_after_ACK = true;
754 PacketResponseNG resp;
756 //can send only 512 bits at a time (1 byte sent per bit...)
757 PrintAndLogEx(INFO, "." NOLF);
758 for (uint16_t i = 0; i < GraphTraceLen; i += PM3_CMD_DATA_SIZE - 3) {
760 size_t len = MIN((GraphTraceLen - i), PM3_CMD_DATA_SIZE - 3);
761 clearCommandBuffer();
762 payload_up.offset = i;
764 for (uint16_t j = 0; j < len; j++)
765 payload_up.data[j] = GraphBuffer[i + j];
767 SendCommandNG(CMD_LF_UPLOAD_SIM_SAMPLES, (uint8_t *)&payload_up, sizeof(struct pupload));
768 WaitForResponse(CMD_LF_UPLOAD_SIM_SAMPLES, &resp);
769 if (resp.status != PM3_SUCCESS) {
770 PrintAndLogEx(INFO, "Bigbuf is full");
771 break;
773 PrintAndLogEx(NORMAL, "." NOLF);
774 fflush(stdout);
775 payload_up.flag = 0;
777 PrintAndLogEx(NORMAL, "");
779 // Disable fast mode before last command
780 conn.block_after_ACK = false;
781 return PM3_SUCCESS;
784 //Attempt to simulate any wave in buffer (one bit per output sample)
785 // converts GraphBuffer to bitstream (based on zero crossings) if needed.
786 int CmdLFSim(const char *Cmd) {
787 CLIParserContext *ctx;
788 CLIParserInit(&ctx, "lf sim",
789 "Simulate low frequency tag from graphbuffer\n"
790 "Use " _YELLOW_("`lf config`") _CYAN_(" to set parameters"),
791 "lf sim\n"
792 "lf sim --gap 240 --> start simulating with 240ms gap"
795 void *argtable[] = {
796 arg_param_begin,
797 arg_u64_0("g", "gap", "<ms>", "start gap in microseconds"),
798 arg_param_end
800 CLIExecWithReturn(ctx, Cmd, argtable, true);
801 uint16_t gap = arg_get_u32_def(ctx, 1, 0);
802 CLIParserFree(ctx);
804 if (session.pm3_present == false) {
805 PrintAndLogEx(DEBUG, "DEBUG: no proxmark present");
806 return PM3_ENOTTY;
809 // sanity check
810 if (GraphTraceLen < 20) {
811 PrintAndLogEx(ERR, "No data in Graphbuffer");
812 return PM3_ENODATA;
815 // convert to bitstream if necessary
816 lf_chk_bitstream();
818 lfsim_upload_gb();
820 struct p {
821 uint16_t len;
822 uint16_t gap;
823 } PACKED payload;
824 payload.len = GraphTraceLen;
825 payload.gap = gap;
827 clearCommandBuffer();
828 SendCommandNG(CMD_LF_SIMULATE, (uint8_t *)&payload, sizeof(payload));
829 return lfsim_wait_check(CMD_LF_SIMULATE);
832 // sim fsk data given clock, fcHigh, fcLow, invert
833 // - allow pull data from DemodBuffer
834 int CmdLFfskSim(const char *Cmd) {
835 CLIParserContext *ctx;
836 CLIParserInit(&ctx, "lf simfsk",
837 "Simulate FSK tag from demodbuffer or input. There are about four FSK modulations to know of.\n"
838 "FSK1 - where fc/8 = high and fc/5 = low\n"
839 "FSK1a - is inverted FSK1, ie: fc/5 = high and fc/8 = low\n"
840 "FSK2 - where fc/10 = high and fc/8 = low\n"
841 "FSK2a - is inverted FSK2, ie: fc/10 = high and fc/8 = low\n\n"
842 "NOTE: if you set one clock manually set them all manually",
843 "lf simfsk -c 40 --high 8 --low 5 -d 010203 --> FSK1 rf/40 data 010203\n"
844 "lf simfsk -c 40 --high 5 --low 8 -d 010203 --> FSK1a rf/40 data 010203\n"
845 "lf simfsk -c 64 --high 10 --low 8 -d 010203 --> FSK2 rf/64 data 010203\n"
846 "lf simfsk -c 64 --high 8 --low 10 -d 010203 --> FSK2a rf/64 data 010203\n\n"
847 "lf simfsk -c 50 --high 10 --low 8 -d 1D5559555569A9A555A59569 --> simulate HID Prox tag manually\n"
848 "lf simfsk -c 50 --high 10 --low 8 --stt -d 011DB2487E8D811111111111 --> simulate AWID tag manually"
851 void *argtable[] = {
852 arg_param_begin,
853 arg_u64_0("c", "clk", "<dec>", "manually set clock - can autodetect if using DemodBuffer (default 64)"),
854 arg_u64_0(NULL, "low", "<dec>", "manually set larger Field Clock"),
855 arg_u64_0(NULL, "high", "<dec>", "manually set smaller Field Clock"),
856 arg_lit0(NULL, "stt", "TBD! - STT to enable a gap between playback repetitions (default: no gap)"),
857 arg_str0("d", "data", "<hex>", "data to sim - omit to use DemodBuffer"),
858 arg_lit0("v", "verbose", "verbose output"),
859 arg_param_end
861 CLIExecWithReturn(ctx, Cmd, argtable, true);
862 uint8_t clk = arg_get_u32_def(ctx, 1, 0);
863 uint8_t fclow = arg_get_u32_def(ctx, 2, 0);
864 uint8_t fchigh = arg_get_u32_def(ctx, 3, 0);
865 bool separator = arg_get_lit(ctx, 4);
867 int raw_len = 64;
868 char raw[64] = {0};
869 CLIGetStrWithReturn(ctx, 5, (uint8_t *)raw, &raw_len);
870 bool verbose = arg_get_lit(ctx, 6);
871 CLIParserFree(ctx);
873 // No args
874 if (raw_len == 0 && DemodBufferLen == 0) {
875 PrintAndLogEx(ERR, "No user supplied data nor inside Demodbuffer");
876 return PM3_EINVARG;
879 if (verbose && separator) {
880 PrintAndLogEx(INFO, "STT gap isn't implemented yet. Skipping...");
881 separator = 0;
884 uint8_t bs[256] = {0x00};
885 int bs_len = hextobinarray((char *)bs, raw);
886 if (bs_len == 0) {
887 // Using data from DemodBuffer
888 // might be able to autodetect FC and clock from Graphbuffer if using demod buffer
889 // will need clock, fchigh, fclow and bitstream
890 PrintAndLogEx(INFO, "No user supplied data, using Demodbuffer...");
892 if (clk == 0 || fchigh == 0 || fclow == 0) {
893 int firstClockEdge = 0;
894 bool res = fskClocks(&fchigh, &fclow, &clk, &firstClockEdge);
895 if (res == false) {
896 clk = 0;
897 fchigh = 0;
898 fclow = 0;
901 PrintAndLogEx(DEBUG, "Detected rf/%u, High fc/%u, Low fc/%u, n %zu ", clk, fchigh, fclow, DemodBufferLen);
903 } else {
904 setDemodBuff(bs, bs_len, 0);
907 //default if not found
908 if (clk == 0) {
909 clk = 50;
910 PrintAndLogEx(DEBUG, "Autodetection of clock failed, falling back to rf/%u", clk);
913 if (fchigh == 0) {
914 fchigh = 10;
915 PrintAndLogEx(DEBUG, "Autodetection of larger clock failed, falling back to fc/%u", fchigh);
918 if (fclow == 0) {
919 fclow = 8;
920 PrintAndLogEx(DEBUG, "Autodetection of smaller clock failed, falling back to fc/%u", fclow);
923 size_t size = DemodBufferLen;
924 if (size > (PM3_CMD_DATA_SIZE - sizeof(lf_fsksim_t))) {
925 PrintAndLogEx(WARNING, "DemodBuffer too long for current implementation - length: %zu - max: %zu", size, PM3_CMD_DATA_SIZE - sizeof(lf_fsksim_t));
926 PrintAndLogEx(INFO, "Continuing with trimmed down data");
927 size = PM3_CMD_DATA_SIZE - sizeof(lf_fsksim_t);
930 lf_fsksim_t *payload = calloc(1, sizeof(lf_fsksim_t) + size);
931 payload->fchigh = fchigh;
932 payload->fclow = fclow;
933 payload->separator = separator;
934 payload->clock = clk;
935 memcpy(payload->data, DemodBuffer, size);
937 clearCommandBuffer();
938 SendCommandNG(CMD_LF_FSK_SIMULATE, (uint8_t *)payload, sizeof(lf_fsksim_t) + size);
939 free(payload);
940 setClockGrid(clk, 0);
942 return lfsim_wait_check(CMD_LF_FSK_SIMULATE);
945 // sim ask data given clock, invert, manchester or raw, separator
946 // - allow pull data from DemodBuffer
947 int CmdLFaskSim(const char *Cmd) {
948 CLIParserContext *ctx;
949 CLIParserInit(&ctx, "lf simask",
950 "Simulate ASK tag from demodbuffer or input",
951 "lf simask --clk 32 --am -d 0102030405 --> simulate ASK/MAN rf/32\n"
952 "lf simask --clk 32 --bi -d 0102030405 --> simulate ASK/BIPHASE rf/32\n\n"
953 "lf simask --clk 64 --am -d ffbd8001686f1924 --> simulate a EM410x tag\n"
954 "lf simask --clk 64 --am --stt -d 5649533200003F340000001B --> simulate a VISA2K tag"
957 void *argtable[] = {
958 arg_param_begin,
959 arg_lit0("i", "inv", "invert data"),
960 arg_u64_0("c", "clk", "<dec>", "manually set clock - can autodetect if using DemodBuffer (default 64)"),
961 arg_lit0(NULL, "bi", "ask/biphase encoding"),
962 arg_lit0(NULL, "am", "ask/manchester encoding (default)"),
963 arg_lit0(NULL, "ar", "ask/raw encoding"),
964 arg_lit0(NULL, "stt", "add t55xx Sequence Terminator gap - default: no gaps (only manchester)"),
965 arg_str0("d", "data", "<hex>", "data to sim - omit to use DemodBuffer"),
966 arg_lit0("v", "verbose", "verbose output"),
967 arg_param_end
969 CLIExecWithReturn(ctx, Cmd, argtable, true);
970 bool invert = arg_get_lit(ctx, 1);
971 uint8_t clk = arg_get_u32_def(ctx, 2, 0);
972 bool use_bi = arg_get_lit(ctx, 3);
973 bool use_am = arg_get_lit(ctx, 4);
974 bool use_ar = arg_get_lit(ctx, 5);
975 bool separator = arg_get_lit(ctx, 6);
977 int raw_len = 64;
978 char raw[64] = {0};
979 CLIGetStrWithReturn(ctx, 7, (uint8_t *)raw, &raw_len);
980 bool verbose = arg_get_lit(ctx, 8);
981 CLIParserFree(ctx);
983 if ((use_bi + use_am + use_ar) > 1) {
984 PrintAndLogEx(ERR, "only one encoding can be set");
985 return PM3_EINVARG;
988 uint8_t encoding = 1;
989 if (use_bi)
990 encoding = 2;
991 else if (use_ar)
992 encoding = 0;
994 // No args
995 if (raw_len == 0 && DemodBufferLen == 0) {
996 PrintAndLogEx(ERR, "No user supplied data nor any inside Demodbuffer");
997 return PM3_EINVARG;
1000 uint8_t bs[256] = {0x00};
1001 int bs_len = hextobinarray((char *)bs, raw);
1002 if (bs_len == 0) {
1003 // Using data from DemodBuffer
1004 // might be able to autodetect FC and clock from Graphbuffer if using demod buffer
1005 // will need carrier, clock, and bitstream
1006 PrintAndLogEx(INFO, "No user supplied data, using Demodbuffer...");
1008 if (clk == 0) {
1009 int res = GetAskClock("0", verbose);
1010 if (res < 1) {
1011 clk = 64;
1012 } else {
1013 clk = (uint8_t)res;
1017 PrintAndLogEx(DEBUG, "Detected rf/%u, n %zu ", clk, DemodBufferLen);
1019 } else {
1020 setDemodBuff(bs, bs_len, 0);
1024 if (clk == 0) {
1025 clk = 32;
1026 PrintAndLogEx(DEBUG, "Autodetection of clock failed, falling back to rf/%u", clk);
1029 if (encoding == 0) {
1030 clk /= 2; // askraw needs to double the clock speed
1031 PrintAndLogEx(DEBUG, "ASK/RAW needs half rf. Using rf/%u", clk);
1034 size_t size = DemodBufferLen;
1035 if (size > (PM3_CMD_DATA_SIZE - sizeof(lf_asksim_t))) {
1036 PrintAndLogEx(WARNING, "DemodBuffer too long for current implementation - length: %zu - max: %zu", size, PM3_CMD_DATA_SIZE - sizeof(lf_asksim_t));
1037 PrintAndLogEx(INFO, "Continuing with trimmed down data");
1038 size = PM3_CMD_DATA_SIZE - sizeof(lf_asksim_t);
1041 lf_asksim_t *payload = calloc(1, sizeof(lf_asksim_t) + size);
1042 payload->encoding = encoding;
1043 payload->invert = invert;
1044 payload->separator = separator;
1045 payload->clock = clk;
1046 memcpy(payload->data, DemodBuffer, size);
1048 clearCommandBuffer();
1049 SendCommandNG(CMD_LF_ASK_SIMULATE, (uint8_t *)payload, sizeof(lf_asksim_t) + size);
1050 free(payload);
1051 setClockGrid(clk, 0);
1053 return lfsim_wait_check(CMD_LF_ASK_SIMULATE);
1056 // sim psk data given carrier, clock, invert
1057 // - allow pull data from DemodBuffer or parameters
1058 int CmdLFpskSim(const char *Cmd) {
1060 CLIParserContext *ctx;
1061 CLIParserInit(&ctx, "lf simpsk",
1062 "Simulate PSK tag from demodbuffer or input",
1063 "lf simpsk -1 --clk 40 --fc 4 -d 01020304 --> simulate PSK1 rf/40 psksub fc/4, data 01020304\n\n"
1064 "lf simpsk -1 --clk 32 --fc 2 -d a0000000bd989a11 --> simulate a indala tag manually"
1067 void *argtable[] = {
1068 arg_param_begin,
1069 arg_lit0("1", "psk1", "set PSK1 (default)"),
1070 arg_lit0("2", "psk2", "set PSK2"),
1071 arg_lit0("3", "psk3", "set PSK3"),
1072 arg_lit0("i", "inv", "invert data"),
1073 arg_u64_0("c", "clk", "<dec>", "manually set clock - can autodetect if using DemodBuffer (default 32)"),
1074 arg_u64_0(NULL, "fc", "<dec>", "2|4|8 are valid carriers (default 2)"),
1075 arg_str0("d", "data", "<hex>", "data to sim - omit to use DemodBuffer"),
1076 arg_lit0("v", "verbose", "verbose output"),
1077 arg_param_end
1079 CLIExecWithReturn(ctx, Cmd, argtable, true);
1080 bool use_psk1 = arg_get_lit(ctx, 1);
1081 bool use_psk2 = arg_get_lit(ctx, 2);
1082 bool use_psk3 = arg_get_lit(ctx, 3);
1083 bool invert = arg_get_lit(ctx, 4);
1084 uint8_t clk = arg_get_u32_def(ctx, 5, 0);
1085 uint8_t carrier = arg_get_u32_def(ctx, 6, 2);
1086 int raw_len = 64;
1087 char raw[64] = {0};
1088 CLIGetStrWithReturn(ctx, 7, (uint8_t *)raw, &raw_len);
1089 bool verbose = arg_get_lit(ctx, 8);
1090 CLIParserFree(ctx);
1092 if ((use_psk1 + use_psk2 + use_psk3) > 1) {
1093 PrintAndLogEx(ERR, "only one PSK mode can be set");
1094 return PM3_EINVARG;
1097 if (carrier != 2 && carrier != 4 && carrier != 8) {
1098 PrintAndLogEx(ERR, "Wrong carrier given, expected <2|4|8>");
1099 return PM3_EINVARG;
1102 uint8_t psk_type = 1;
1103 if (use_psk2)
1104 psk_type = 2;
1105 if (use_psk3)
1106 psk_type = 3;
1108 // No args
1109 if (raw_len == 0 && DemodBufferLen == 0) {
1110 PrintAndLogEx(ERR, "No user supplied data nor any inside Demodbuffer");
1111 return PM3_EINVARG;
1114 uint8_t bs[256] = {0x00};
1115 int bs_len = hextobinarray((char *)bs, raw);
1117 if (bs_len == 0) {
1118 // Using data from DemodBuffer
1119 // might be able to autodetect FC and clock from Graphbuffer if using demod buffer
1120 // will need carrier, clock, and bitstream
1121 PrintAndLogEx(INFO, "No user supplied data, using Demodbuffer...");
1123 int res;
1124 if (clk == 0) {
1125 res = GetPskClock("", verbose);
1126 if (res < 1) {
1127 clk = 32;
1128 } else {
1129 clk = (uint8_t)res;
1133 if (carrier == 0) {
1134 res = GetPskCarrier(verbose);
1135 if (res < 1) {
1136 carrier = 2;
1137 } else {
1138 carrier = (uint8_t)res;
1142 PrintAndLogEx(DEBUG, "Detected rf/%u, fc/%u, n %zu ", clk, carrier, DemodBufferLen);
1144 } else {
1145 setDemodBuff(bs, bs_len, 0);
1148 if (clk == 0) {
1149 clk = 32;
1150 PrintAndLogEx(DEBUG, "Autodetection of clock failed, falling back to rf/%u", clk);
1153 if (psk_type == 2) {
1154 //need to convert psk2 to psk1 data before sim
1155 psk2TOpsk1(DemodBuffer, DemodBufferLen);
1156 } else if (psk_type == 3) {
1157 PrintAndLogEx(INFO, "PSK3 not yet available. Falling back to PSK1");
1160 size_t size = DemodBufferLen;
1161 if (size > (PM3_CMD_DATA_SIZE - sizeof(lf_psksim_t))) {
1162 PrintAndLogEx(WARNING, "DemodBuffer too long for current implementation - length: %zu - max: %zu", size, PM3_CMD_DATA_SIZE - sizeof(lf_psksim_t));
1163 PrintAndLogEx(INFO, "Continuing with trimmed down data");
1164 size = PM3_CMD_DATA_SIZE - sizeof(lf_psksim_t);
1167 lf_psksim_t *payload = calloc(1, sizeof(lf_psksim_t) + size);
1168 payload->carrier = carrier;
1169 payload->invert = invert;
1170 payload->clock = clk;
1171 memcpy(payload->data, DemodBuffer, size);
1172 clearCommandBuffer();
1173 SendCommandNG(CMD_LF_PSK_SIMULATE, (uint8_t *)payload, sizeof(lf_psksim_t) + size);
1174 free(payload);
1175 setClockGrid(clk, 0);
1177 return lfsim_wait_check(CMD_LF_PSK_SIMULATE);
1180 int CmdLFSimBidir(const char *Cmd) {
1182 CLIParserContext *ctx;
1183 CLIParserInit(&ctx, "lf simbidir",
1184 "Simulate LF tag with bidirectional data transmission between reader and tag",
1185 "lf simbidir"
1188 void *argtable[] = {
1189 arg_param_begin,
1190 arg_param_end
1192 CLIExecWithReturn(ctx, Cmd, argtable, true);
1193 CLIParserFree(ctx);
1195 // Set ADC to twice the carrier for a slight supersampling
1196 // HACK: not implemented in ARMSRC.
1197 PrintAndLogEx(INFO, "Not implemented yet.");
1198 // SendCommandMIX(CMD_LF_SIMULATE_BIDIR, 47, 384, 0, NULL, 0);
1199 return PM3_SUCCESS;
1202 // ICEMAN, Verichip is Animal tag. Tested against correct reader
1205 int CmdVchDemod(const char *Cmd) {
1207 if (GraphTraceLen < 4096) {
1208 PrintAndLogEx(DEBUG, "debug; VchDemod - too few samples");
1209 return PM3_EINVARG;
1212 // Is this the entire sync pattern, or does this also include some
1213 // data bits that happen to be the same everywhere? That would be
1214 // lovely to know.
1215 static const int SyncPattern[] = {
1216 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1217 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1218 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1219 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1220 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1221 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1222 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1223 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1224 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1225 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1228 // iceman, using correlate as preamble detect seems way better than our current memcompare
1230 // So first, we correlate for the sync pattern, and mark that.
1231 int bestCorrel = 0, bestPos = 0;
1232 int i, j, sum = 0;
1234 // It does us no good to find the sync pattern, with fewer than 2048 samples after it.
1236 for (i = 0; i < (GraphTraceLen - 2048); i++) {
1237 for (j = 0; j < ARRAYLEN(SyncPattern); j++) {
1238 sum += GraphBuffer[i + j] * SyncPattern[j];
1240 if (sum > bestCorrel) {
1241 bestCorrel = sum;
1242 bestPos = i;
1245 PrintAndLogEx(NORMAL, "best sync at %d [metric %d]", bestPos, bestCorrel);
1247 char bits[257];
1248 bits[256] = '\0';
1250 int worst = INT_MAX, worstPos = 0;
1252 for (i = 0; i < 2048; i += 8) {
1253 sum = 0;
1254 for (j = 0; j < 8; j++)
1255 sum += GraphBuffer[bestPos + i + j];
1257 if (sum < 0)
1258 bits[i / 8] = '.';
1259 else
1260 bits[i / 8] = '1';
1262 if (abs(sum) < worst) {
1263 worst = abs(sum);
1264 worstPos = i;
1267 PrintAndLogEx(NORMAL, "bits:");
1268 PrintAndLogEx(NORMAL, "%s", bits);
1269 PrintAndLogEx(NORMAL, "worst metric: %d at pos %d", worst, worstPos);
1271 // clone
1272 if (strcmp(Cmd, "clone") == 0) {
1273 GraphTraceLen = 0;
1274 char *s;
1275 for (s = bits; *s; s++) {
1276 for (j = 0; j < 16; j++) {
1277 GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0;
1280 RepaintGraphWindow();
1282 return PM3_SUCCESS;
1286 static bool CheckChipType(bool getDeviceData) {
1288 bool retval = false;
1290 if (!getDeviceData) return retval;
1292 save_restoreGB(GRAPH_SAVE);
1293 save_restoreDB(GRAPH_SAVE);
1295 //check for em4x05/em4x69 chips first
1296 uint32_t word = 0;
1297 if (em4x05_isblock0(&word)) {
1298 PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("EM4x05 / EM4x69"));
1299 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x05`") " commands");
1300 retval = true;
1301 goto out;
1304 //check for t55xx chip...
1305 if (tryDetectP1(true)) {
1306 PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("T55xx"));
1307 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf t55xx`") " commands");
1308 retval = true;
1309 goto out;
1312 // check for em4x50 chips
1313 if (detect_4x50_block()) {
1314 PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("EM4x50"));
1315 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x50`") " commands");
1316 retval = true;
1317 goto out;
1320 // check for em4x70 chips
1321 if (detect_4x70_block()) {
1322 PrintAndLogEx(SUCCESS, "Chipset detection: " _GREEN_("EM4x70"));
1323 PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf em 4x70`") " commands");
1324 retval = true;
1325 goto out;
1328 PrintAndLogEx(INFO, "Couldn't identify a chipset");
1329 out:
1330 save_restoreGB(GRAPH_RESTORE);
1331 save_restoreDB(GRAPH_RESTORE);
1332 return retval;
1335 int CmdLFfind(const char *Cmd) {
1337 CLIParserContext *ctx;
1338 CLIParserInit(&ctx, "lf search",
1339 "Read and search for valid known tag. For offline mode, you can `data load` first then search.",
1340 "lf search -> try reading data from tag & search for known tag\n"
1341 "lf search -1 -> use data from GraphBuffer & search for known tag\n"
1342 "lf search -u -> try reading data from tag & search for known and unknown tag\n"
1343 "lf search -1u -> use data from GraphBuffer & search for known and unknown tag\n"
1346 void *argtable[] = {
1347 arg_param_begin,
1348 arg_lit0("1", NULL, "Use data from Graphbuffer to search"),
1349 arg_lit0("c", NULL, "Continue searching even after a first hit"),
1350 arg_lit0("u", NULL, "Search for unknown tags. If not set, reads only known tags"),
1351 arg_param_end
1353 CLIExecWithReturn(ctx, Cmd, argtable, true);
1354 bool use_gb = arg_get_lit(ctx, 1);
1355 bool search_cont = arg_get_lit(ctx, 2);
1356 bool search_unk = arg_get_lit(ctx, 3);
1357 CLIParserFree(ctx);
1358 int found = 0;
1359 bool is_online = (session.pm3_present && (use_gb == false));
1360 if (is_online)
1361 lf_read(false, 30000);
1363 size_t min_length = 2000;
1364 if (GraphTraceLen < min_length) {
1365 PrintAndLogEx(FAILED, "Data in Graphbuffer was too small.");
1366 return PM3_ESOFT;
1369 if (search_cont) {
1370 PrintAndLogEx(INFO, "Continuous search enabled");
1373 PrintAndLogEx(NORMAL, "");
1374 PrintAndLogEx(INFO, "NOTE: some demods output possible binary");
1375 PrintAndLogEx(INFO, "if it finds something that looks like a tag");
1376 PrintAndLogEx(INFO, "False Positives " _YELLOW_("ARE") " possible");
1377 PrintAndLogEx(INFO, "");
1378 PrintAndLogEx(INFO, "Checking for known tags...");
1379 PrintAndLogEx(INFO, "");
1381 // only run these tests if device is online
1382 if (is_online) {
1384 if (IfPm3Hitag()) {
1385 if (readHitagUid()) {
1386 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") " found!");
1387 if (search_cont) {
1388 found++;
1389 } else {
1390 return PM3_SUCCESS;
1395 if (IfPm3EM4x50()) {
1396 if (read_em4x50_uid() == PM3_SUCCESS) {
1397 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM4x50 ID") " found!");
1398 if (search_cont) {
1399 found++;
1400 } else {
1401 return PM3_SUCCESS;
1406 // only run if graphbuffer is just noise as it should be for hitag
1407 // The improved noise detection will find Cotag.
1408 if (getSignalProperties()->isnoise) {
1410 PrintAndLogEx(INPLACE, "Searching for MOTOROLA tag...");
1411 if (readMotorolaUid()) {
1412 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") " found!");
1413 if (search_cont) {
1414 found++;
1415 } else {
1416 return PM3_SUCCESS;
1420 PrintAndLogEx(INPLACE, "Searching for COTAG tag...");
1421 if (readCOTAGUid()) {
1422 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("COTAG ID") " found!");
1423 if (search_cont) {
1424 found++;
1425 } else {
1426 return PM3_SUCCESS;
1430 PrintAndLogEx(NORMAL, "");
1431 PrintAndLogEx(FAILED, _RED_("No data found!"));
1432 PrintAndLogEx(INFO, "Signal looks like noise. Maybe not an LF tag?");
1433 PrintAndLogEx(NORMAL, "");
1434 if (! search_cont) {
1435 return PM3_ESOFT;
1440 int retval = PM3_SUCCESS;
1442 // ask / man
1443 if (demodEM410x(true) == PM3_SUCCESS) {
1444 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!");
1445 if (search_cont) {
1446 found++;
1447 } else {
1448 goto out;
1451 if (demodDestron(true) == PM3_SUCCESS) { // to do before HID
1452 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-A FECAVA Destron ID") " found!");
1453 if (search_cont) {
1454 found++;
1455 } else {
1456 goto out;
1459 if (demodGallagher(true) == PM3_SUCCESS) {
1460 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("GALLAGHER ID") " found!");
1461 if (search_cont) {
1462 found++;
1463 } else {
1464 goto out;
1467 if (demodNoralsy(true) == PM3_SUCCESS) {
1468 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!");
1469 if (search_cont) {
1470 found++;
1471 } else {
1472 goto out;
1475 if (demodPresco(true) == PM3_SUCCESS) {
1476 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Presco ID") " found!");
1477 if (search_cont) {
1478 found++;
1479 } else {
1480 goto out;
1483 if (demodSecurakey(true) == PM3_SUCCESS) {
1484 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Securakey ID") " found!");
1485 if (search_cont) {
1486 found++;
1487 } else {
1488 goto out;
1491 if (demodViking(true) == PM3_SUCCESS) {
1492 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Viking ID") " found!");
1493 if (search_cont) {
1494 found++;
1495 } else {
1496 goto out;
1499 if (demodVisa2k(true) == PM3_SUCCESS) {
1500 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Visa2000 ID") " found!");
1501 if (search_cont) {
1502 found++;
1503 } else {
1504 goto out;
1508 // ask / bi
1509 if (demodFDXB(true) == PM3_SUCCESS) {
1510 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!");
1511 if (search_cont) {
1512 found++;
1513 } else {
1514 goto out;
1517 if (demodJablotron(true) == PM3_SUCCESS) {
1518 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!");
1519 if (search_cont) {
1520 found++;
1521 } else {
1522 goto out;
1525 if (demodGuard(true) == PM3_SUCCESS) {
1526 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!");
1527 if (search_cont) {
1528 found++;
1529 } else {
1530 goto out;
1533 if (demodNedap(true) == PM3_SUCCESS) {
1534 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NEDAP ID") " found!");
1535 if (search_cont) {
1536 found++;
1537 } else {
1538 goto out;
1542 // nrz
1543 if (demodPac(true) == PM3_SUCCESS) {
1544 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!");
1545 if (search_cont) {
1546 found++;
1547 } else {
1548 goto out;
1552 // fsk
1553 if (demodHID(true) == PM3_SUCCESS) {
1554 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!");
1555 if (search_cont) {
1556 found++;
1557 } else {
1558 goto out;
1561 if (demodAWID(true) == PM3_SUCCESS) {
1562 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!");
1563 if (search_cont) {
1564 found++;
1565 } else {
1566 goto out;
1569 if (demodIOProx(true) == PM3_SUCCESS) {
1570 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!");
1571 if (search_cont) {
1572 found++;
1573 } else {
1574 goto out;
1577 if (demodPyramid(true) == PM3_SUCCESS) {
1578 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!");
1579 if (search_cont) {
1580 found++;
1581 } else {
1582 goto out;
1585 if (demodParadox(true) == PM3_SUCCESS) {
1586 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!");
1587 if (search_cont) {
1588 found++;
1589 } else {
1590 goto out;
1594 // psk
1595 if (demodIdteck(true) == PM3_SUCCESS) {
1596 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!");
1597 if (search_cont) {
1598 found++;
1599 } else {
1600 goto out;
1603 if (demodKeri(true) == PM3_SUCCESS) {
1604 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!");
1605 if (search_cont) {
1606 found++;
1607 } else {
1608 goto out;
1611 if (demodNexWatch(true) == PM3_SUCCESS) {
1612 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("NexWatch ID") " found!");
1613 if (search_cont) {
1614 found++;
1615 } else {
1616 goto out;
1619 if (demodIndala(true) == PM3_SUCCESS) {
1620 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!");
1621 if (search_cont) {
1622 found++;
1623 } else {
1624 goto out;
1628 if (demodTI() == PM3_SUCCESS) {
1629 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Texas Instrument ID") " found!");
1630 if (search_cont) {
1631 found++;
1632 } else {
1633 goto out;
1636 if (demodFermax() == PM3_SUCCESS) {
1637 PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Fermax ID") " found!");
1638 if (search_cont) {
1639 found++;
1640 } else {
1641 goto out;
1645 if (found == 0) {
1646 PrintAndLogEx(FAILED, _RED_("No known 125/134 kHz tags found!"));
1649 if (search_unk) {
1650 //test unknown tag formats (raw mode)
1651 PrintAndLogEx(INFO, "\nChecking for unknown tags:\n");
1652 int ans = AutoCorrelate(GraphBuffer, GraphBuffer, GraphTraceLen, 8000, false, false);
1653 if (ans > 0) {
1655 PrintAndLogEx(INFO, "Possible auto correlation of %d repeating samples", ans);
1657 if (ans % 8 == 0)
1658 PrintAndLogEx(INFO, "Possible %d bytes", (ans / 8));
1661 //fsk
1662 if (GetFskClock("", false)) {
1663 if (FSKrawDemod(0, 0, 0, 0, true) == PM3_SUCCESS) {
1664 PrintAndLogEx(INFO, "Unknown FSK Modulated Tag found!");
1665 if (search_cont) {
1666 found++;
1667 } else {
1668 goto out;
1673 bool st = true;
1674 if (ASKDemod_ext(0, 0, 0, 0, false, true, false, 1, &st) == PM3_SUCCESS) {
1675 PrintAndLogEx(INFO, "Unknown ASK Modulated and Manchester encoded Tag found!");
1676 PrintAndLogEx(INFO, "if it does not look right it could instead be ASK/Biphase - try " _YELLOW_("'data rawdemod --ab'"));
1677 if (search_cont) {
1678 found++;
1679 } else {
1680 goto out;
1684 if (CmdPSK1rawDemod("") == PM3_SUCCESS) {
1685 PrintAndLogEx(INFO, "Possible unknown PSK1 Modulated Tag found above!");
1686 PrintAndLogEx(INFO, " Could also be PSK2 - try " _YELLOW_("'data rawdemod --p2'"));
1687 PrintAndLogEx(INFO, " Could also be PSK3 - [currently not supported]");
1688 PrintAndLogEx(INFO, " Could also be NRZ - try " _YELLOW_("'data rawdemod --nr"));
1689 if (search_cont) {
1690 found++;
1691 } else {
1692 goto out;
1696 if (found == 0) {
1697 PrintAndLogEx(FAILED, _RED_("No data found!"));
1701 if (found == 0) {
1702 retval = PM3_ESOFT;
1705 out:
1706 // identify chipset
1707 if (CheckChipType(is_online) == false) {
1708 PrintAndLogEx(DEBUG, "Automatic chip type detection " _RED_("failed"));
1710 return retval;
1713 static command_t CommandTable[] = {
1714 {"help", CmdHelp, AlwaysAvailable, "This help"},
1715 {"-----------", CmdHelp, AlwaysAvailable, "-------------- " _CYAN_("Low Frequency") " --------------"},
1716 {"awid", CmdLFAWID, AlwaysAvailable, "{ AWID RFIDs... }"},
1717 {"cotag", CmdLFCOTAG, AlwaysAvailable, "{ COTAG CHIPs... }"},
1718 {"destron", CmdLFDestron, AlwaysAvailable, "{ FDX-A Destron RFIDs... }"},
1719 {"em", CmdLFEM, AlwaysAvailable, "{ EM CHIPs & RFIDs... }"},
1720 {"fdxb", CmdLFFdxB, AlwaysAvailable, "{ FDX-B RFIDs... }"},
1721 {"gallagher", CmdLFGallagher, AlwaysAvailable, "{ GALLAGHER RFIDs... }"},
1722 {"gproxii", CmdLFGuard, AlwaysAvailable, "{ Guardall Prox II RFIDs... }"},
1723 {"hid", CmdLFHID, AlwaysAvailable, "{ HID Prox RFIDs... }"},
1724 {"hitag", CmdLFHitag, AlwaysAvailable, "{ Hitag CHIPs... }"},
1725 {"idteck", CmdLFIdteck, AlwaysAvailable, "{ Idteck RFIDs... }"},
1726 {"indala", CmdLFINDALA, AlwaysAvailable, "{ Indala RFIDs... }"},
1727 {"io", CmdLFIO, AlwaysAvailable, "{ ioProx RFIDs... }"},
1728 {"jablotron", CmdLFJablotron, AlwaysAvailable, "{ Jablotron RFIDs... }"},
1729 {"keri", CmdLFKeri, AlwaysAvailable, "{ KERI RFIDs... }"},
1730 {"motorola", CmdLFMotorola, AlwaysAvailable, "{ Motorola RFIDs... }"},
1731 {"nedap", CmdLFNedap, AlwaysAvailable, "{ Nedap RFIDs... }"},
1732 {"nexwatch", CmdLFNEXWATCH, AlwaysAvailable, "{ NexWatch RFIDs... }"},
1733 {"noralsy", CmdLFNoralsy, AlwaysAvailable, "{ Noralsy RFIDs... }"},
1734 {"pac", CmdLFPac, AlwaysAvailable, "{ PAC/Stanley RFIDs... }"},
1735 {"paradox", CmdLFParadox, AlwaysAvailable, "{ Paradox RFIDs... }"},
1736 {"pcf7931", CmdLFPCF7931, AlwaysAvailable, "{ PCF7931 CHIPs... }"},
1737 {"presco", CmdLFPresco, AlwaysAvailable, "{ Presco RFIDs... }"},
1738 {"pyramid", CmdLFPyramid, AlwaysAvailable, "{ Farpointe/Pyramid RFIDs... }"},
1739 {"securakey", CmdLFSecurakey, AlwaysAvailable, "{ Securakey RFIDs... }"},
1740 {"ti", CmdLFTI, AlwaysAvailable, "{ TI CHIPs... }"},
1741 {"t55xx", CmdLFT55XX, AlwaysAvailable, "{ T55xx CHIPs... }"},
1742 {"viking", CmdLFViking, AlwaysAvailable, "{ Viking RFIDs... }"},
1743 {"visa2000", CmdLFVisa2k, AlwaysAvailable, "{ Visa2000 RFIDs... }"},
1744 {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("General") " ---------------------"},
1745 {"config", CmdLFConfig, IfPm3Lf, "Get/Set config for LF sampling, bit/sample, decimation, frequency"},
1746 {"cmdread", CmdLFCommandRead, IfPm3Lf, "Modulate LF reader field to send command before read"},
1747 {"read", CmdLFRead, IfPm3Lf, "Read LF tag"},
1748 {"search", CmdLFfind, AlwaysAvailable, "Read and Search for valid known tag"},
1749 {"sim", CmdLFSim, IfPm3Lf, "Simulate LF tag from buffer"},
1750 {"simask", CmdLFaskSim, IfPm3Lf, "Simulate " _YELLOW_("ASK") " tag"},
1751 {"simfsk", CmdLFfskSim, IfPm3Lf, "Simulate " _YELLOW_("FSK") " tag"},
1752 {"simpsk", CmdLFpskSim, IfPm3Lf, "Simulate " _YELLOW_("PSK") " tag"},
1753 // {"simnrz", CmdLFnrzSim, IfPm3Lf, "Simulate " _YELLOW_("NRZ") " tag"},
1754 {"simbidir", CmdLFSimBidir, IfPm3Lf, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
1755 {"sniff", CmdLFSniff, IfPm3Lf, "Sniff LF traffic between reader and tag"},
1756 {"tune", CmdLFTune, IfPm3Lf, "Continuously measure LF antenna tuning"},
1757 // {"vchdemod", CmdVchDemod, AlwaysAvailable, "Demodulate samples for VeriChip"},
1758 // {"flexdemod", CmdFlexdemod, AlwaysAvailable, "Demodulate samples for Motorola FlexPass"},
1759 {NULL, NULL, NULL, NULL}
1762 int CmdLF(const char *Cmd) {
1763 clearCommandBuffer();
1764 return CmdsParse(CommandTable, Cmd);
1767 int CmdHelp(const char *Cmd) {
1768 (void)Cmd; // Cmd is not used so far
1769 CmdsHelp(CommandTable);
1770 return PM3_SUCCESS;