From 42ab3ee1e60a756cf69a2de2254eda0916e6f598 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Tue, 14 Nov 2023 02:57:52 +0800 Subject: [PATCH] Receive raw LF samples on the client --- client/src/cmddata.c | 28 ++++++---- client/src/cmddata.h | 1 + client/src/cmdlf.c | 127 ++++++++++++++++++++++++++++++++----------- client/src/cmdlf.h | 4 +- 4 files changed, 116 insertions(+), 44 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index cca476c20..534663844 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1776,36 +1776,45 @@ int getSamplesEx(uint32_t start, uint32_t end, bool verbose, bool ignore_lf_conf bits_per_sample = sc->bits_per_sample; } + getSamplesFromBufEx(got, n, bits_per_sample, verbose); + + return PM3_SUCCESS; +} + +void getSamplesFromBufEx(uint8_t *data, size_t sample_num, uint8_t bits_per_sample, bool verbose) { + + size_t max_num = MIN(sample_num, MAX_GRAPH_TRACE_LEN); + if (bits_per_sample < 8) { if (verbose) PrintAndLogEx(INFO, "Unpacking..."); - BitstreamOut_t bout = { got, bits_per_sample * n, 0}; - uint32_t j = 0; - for (j = 0; j * bits_per_sample < n * 8 && j * bits_per_sample < MAX_GRAPH_TRACE_LEN * 8; j++) { + BitstreamOut_t bout = {data, bits_per_sample * sample_num, 0}; + size_t j = 0; + for (j = 0; j < max_num; j++) { uint8_t sample = getByte(bits_per_sample, &bout); g_GraphBuffer[j] = ((int) sample) - 127; } g_GraphTraceLen = j; - if (verbose) PrintAndLogEx(INFO, "Unpacked %d samples", j); + if (verbose) PrintAndLogEx(INFO, "Unpacked %zu samples", j); } else { - for (uint32_t j = 0; j < n; j++) { - g_GraphBuffer[j] = ((int)got[j]) - 127; + for (size_t j = 0; j < max_num; j++) { + g_GraphBuffer[j] = ((int)data[j]) - 127; } - g_GraphTraceLen = n; + g_GraphTraceLen = max_num; } - uint8_t bits[g_GraphTraceLen]; + uint8_t *bits = malloc(g_GraphTraceLen); size_t size = getFromGraphBuf(bits); // set signal properties low/high/mean/amplitude and is_noise detection computeSignalProperties(bits, size); + free(bits); setClockGrid(0, 0); g_DemodBufferLen = 0; RepaintGraphWindow(); - return PM3_SUCCESS; } static int CmdSamples(const char *Cmd) { @@ -3584,4 +3593,3 @@ int CmdData(const char *Cmd) { clearCommandBuffer(); return CmdsParse(CommandTable, Cmd); } - diff --git a/client/src/cmddata.h b/client/src/cmddata.h index 1e4500d32..c9f7398be 100644 --- a/client/src/cmddata.h +++ b/client/src/cmddata.h @@ -86,6 +86,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, size_t window, bool SaveG int getSamples(uint32_t n, bool verbose); int getSamplesEx(uint32_t start, uint32_t end, bool verbose, bool ignore_lf_config); +void getSamplesFromBufEx(uint8_t *data, size_t sample_num, uint8_t bits_per_sample, bool verbose); void setClockGrid(uint32_t clk, int offset); int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t down); diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index ce0e67ff5..f078f795f 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -696,31 +696,58 @@ int CmdLFConfig(const char *Cmd) { return lf_config(&config); } -int lf_read(bool verbose, uint32_t samples) { +static int lf_read_internal(bool realtime, bool verbose, uint64_t samples) { if (!g_session.pm3_present) return PM3_ENOTTY; lf_sample_payload_t payload; + payload.realtime = realtime; payload.verbose = verbose; - payload.samples = samples; + sample_config current_config; + int retval = lf_getconfig(¤t_config); + if (retval != PM3_SUCCESS) { + PrintAndLogEx(ERR, "failed to get current device config"); + return retval; + } clearCommandBuffer(); - SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload)); - PacketResponseNG resp; - if (gs_lf_threshold_set) { - WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp); + const uint8_t bits_per_sample = current_config.bits_per_sample; + + if (realtime) { + uint8_t *realtimeBuf = calloc(samples, sizeof(uint8_t)); + + size_t sample_bytes = samples * bits_per_sample; + sample_bytes = (sample_bytes / 8) + (sample_bytes % 8 != 0); + + SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload)); + sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000, true); + samples = sample_bytes * 8 / bits_per_sample; + getSamplesFromBufEx(realtimeBuf, samples, bits_per_sample, verbose); + + free(realtimeBuf); } else { - if (!WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500)) { - PrintAndLogEx(WARNING, "(lf_read) command execution time out"); - return PM3_ETIMEOUT; + payload.samples = (samples > MAX_LF_SAMPLES) ? MAX_LF_SAMPLES : samples; + SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload)); + PacketResponseNG resp; + if (gs_lf_threshold_set) { + WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp); + } else { + if (!WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500)) { + PrintAndLogEx(WARNING, "(lf_read) command execution time out"); + return PM3_ETIMEOUT; + } } + // response is number of bits read + uint32_t size = (resp.data.asDwords[0] / bits_per_sample); + getSamples(size, verbose); } - // response is number of bits read - uint32_t size = (resp.data.asDwords[0] / 8); - getSamples(size, verbose); return PM3_SUCCESS; } +int lf_read(bool verbose, uint64_t samples) { + return lf_read_internal(false, verbose, samples); +} + int CmdLFRead(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf read", @@ -729,6 +756,7 @@ int CmdLFRead(const char *Cmd) { _CYAN_(" - use ") _YELLOW_("`data plot`") _CYAN_(" to look at it"), "lf read -v -s 12000 --> collect 12000 samples\n" "lf read -s 3000 -@ --> oscilloscope style \n" + "lf read -r --> use real-time mode \n" ); void *argtable[] = { @@ -736,50 +764,78 @@ int CmdLFRead(const char *Cmd) { arg_u64_0("s", "samples", "", "number of samples to collect"), arg_lit0("v", "verbose", "verbose output"), arg_lit0("@", NULL, "continuous reading mode"), + arg_lit0("r", "realtime", "real-time reading mode"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - uint32_t samples = arg_get_u32_def(ctx, 1, 0); + uint64_t samples = arg_get_u64_def(ctx, 1, 0); bool verbose = arg_get_lit(ctx, 2); bool cm = arg_get_lit(ctx, 3); + bool realtime = arg_get_lit(ctx, 4); CLIParserFree(ctx); if (g_session.pm3_present == false) return PM3_ENOTTY; - if (cm) { + if (realtime && samples == 0) { + samples = MAX_GRAPH_TRACE_LEN; + } + + if (cm || realtime) { PrintAndLogEx(INFO, "Press " _GREEN_("") " to exit"); } int ret = PM3_SUCCESS; do { - ret = lf_read(verbose, samples); + ret = lf_read_internal(realtime, verbose, samples); } while (cm && kbd_enter_pressed() == false); return ret; } -int lf_sniff(bool verbose, uint32_t samples) { +int lf_sniff(bool realtime, bool verbose, uint64_t samples) { if (!g_session.pm3_present) return PM3_ENOTTY; lf_sample_payload_t payload; - - payload.samples = (samples & 0xFFFF); + payload.realtime = realtime; payload.verbose = verbose; + sample_config current_config; + int retval = lf_getconfig(¤t_config); + if (retval != PM3_SUCCESS) { + PrintAndLogEx(ERR, "failed to get current device config"); + return retval; + } clearCommandBuffer(); - SendCommandNG(CMD_LF_SNIFF_RAW_ADC, (uint8_t *)&payload, sizeof(payload)); - PacketResponseNG resp; - if (gs_lf_threshold_set) { - WaitForResponse(CMD_LF_SNIFF_RAW_ADC, &resp); + const uint8_t bits_per_sample = current_config.bits_per_sample; + + if (realtime) { + uint8_t *realtimeBuf = calloc(samples, sizeof(uint8_t)); + + size_t sample_bytes = samples * bits_per_sample; + sample_bytes = (sample_bytes / 8) + (sample_bytes % 8 != 0); + + SendCommandNG(CMD_LF_SNIFF_RAW_ADC, (uint8_t *)&payload, sizeof(payload)); + sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000, true); + samples = sample_bytes * 8 / bits_per_sample; + getSamplesFromBufEx(realtimeBuf, samples, bits_per_sample, verbose); + + free(realtimeBuf); } else { - if (WaitForResponseTimeout(CMD_LF_SNIFF_RAW_ADC, &resp, 2500) == false) { - PrintAndLogEx(WARNING, "(lf_read) command execution time out"); - return PM3_ETIMEOUT; + payload.samples = (samples > MAX_LF_SAMPLES) ? MAX_LF_SAMPLES : samples; + SendCommandNG(CMD_LF_SNIFF_RAW_ADC, (uint8_t *)&payload, sizeof(payload)); + PacketResponseNG resp; + if (gs_lf_threshold_set) { + WaitForResponse(CMD_LF_SNIFF_RAW_ADC, &resp); + } else { + if (WaitForResponseTimeout(CMD_LF_SNIFF_RAW_ADC, &resp, 2500) == false) { + PrintAndLogEx(WARNING, "(lf_read) command execution time out"); + return PM3_ETIMEOUT; + } } + // response is number of bits read + uint32_t size = (resp.data.asDwords[0] / bits_per_sample); + getSamples(size, verbose); } - // response is number of bits read - uint32_t size = (resp.data.asDwords[0] / 8); - getSamples(size, verbose); return PM3_SUCCESS; } @@ -794,6 +850,7 @@ int CmdLFSniff(const char *Cmd) { _CYAN_(" - use ") _YELLOW_("`lf search -1`") _CYAN_(" to see if signal can be automatic decoded\n"), "lf sniff -v\n" "lf sniff -s 3000 -@ --> oscilloscope style \n" + "lf sniff -r --> use real-time mode \n" ); void *argtable[] = { @@ -801,24 +858,30 @@ int CmdLFSniff(const char *Cmd) { arg_u64_0("s", "samples", "", "number of samples to collect"), arg_lit0("v", "verbose", "verbose output"), arg_lit0("@", NULL, "continuous sniffing mode"), + arg_lit0("r", "realtime", "real-time sniffing mode"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); - uint32_t samples = (arg_get_u32_def(ctx, 1, 0) & 0xFFFF); + uint64_t samples = arg_get_u64_def(ctx, 1, 0); bool verbose = arg_get_lit(ctx, 2); bool cm = arg_get_lit(ctx, 3); + bool realtime = arg_get_lit(ctx, 4); CLIParserFree(ctx); if (g_session.pm3_present == false) return PM3_ENOTTY; - if (cm) { + if (realtime && samples == 0) { + samples = MAX_GRAPH_TRACE_LEN; + } + + if (cm || realtime) { PrintAndLogEx(INFO, "Press " _GREEN_("") " to exit"); } int ret = PM3_SUCCESS; do { - ret = lf_sniff(verbose, samples); - } while (cm && !kbd_enter_pressed()); + ret = lf_sniff(realtime, verbose, samples); + } while (cm && kbd_enter_pressed() == false); return ret; } diff --git a/client/src/cmdlf.h b/client/src/cmdlf.h index 3bcd3ecf2..b29fd137f 100644 --- a/client/src/cmdlf.h +++ b/client/src/cmdlf.h @@ -40,8 +40,8 @@ int CmdLFSniff(const char *Cmd); int CmdVchDemod(const char *Cmd); int CmdLFfind(const char *Cmd); -int lf_read(bool verbose, uint32_t samples); -int lf_sniff(bool verbose, uint32_t samples); +int lf_read(bool verbose, uint64_t samples); +int lf_sniff(bool realtime, bool verbose, uint64_t samples); int lf_config(sample_config *config); int lf_getconfig(sample_config *config); int lfsim_upload_gb(void);