From 9e8b1ceda748c187c6c4bebec8e34b4c09d0fbd8 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Tue, 14 Nov 2023 01:05:27 +0800 Subject: [PATCH 01/11] Reduce duplicate payload structure for lf read/sniff --- armsrc/appmain.c | 12 ++---------- client/src/cmdlf.c | 12 ++---------- include/pm3_cmd.h | 11 +++++++++++ 3 files changed, 15 insertions(+), 20 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index b8823af3b..dded4be55 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -851,11 +851,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_ACQ_RAW_ADC: { - struct p { - uint32_t samples : 31; - bool verbose : 1; - } PACKED; - struct p *payload = (struct p *)packet->data.asBytes; + lf_sample_payload_t *payload = (lf_sample_payload_t *)packet->data.asBytes; uint32_t bits = SampleLF(payload->verbose, payload->samples, true); reply_ng(CMD_LF_ACQ_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits)); break; @@ -880,11 +876,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_SNIFF_RAW_ADC: { - struct p { - uint32_t samples : 31; - bool verbose : 1; - } PACKED; - struct p *payload = (struct p *)packet->data.asBytes; + lf_sample_payload_t *payload = (lf_sample_payload_t *)packet->data.asBytes; uint32_t bits = SniffLF(payload->verbose, payload->samples, true); reply_ng(CMD_LF_SNIFF_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits)); diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index 1d57378c7..ce0e67ff5 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -699,12 +699,7 @@ int CmdLFConfig(const char *Cmd) { int lf_read(bool verbose, uint32_t samples) { if (!g_session.pm3_present) return PM3_ENOTTY; - struct p { - uint32_t samples : 31; - bool verbose : 1; - } PACKED; - - struct p payload; + lf_sample_payload_t payload; payload.verbose = verbose; payload.samples = samples; @@ -765,10 +760,7 @@ int CmdLFRead(const char *Cmd) { int lf_sniff(bool verbose, uint32_t samples) { if (!g_session.pm3_present) return PM3_ENOTTY; - struct p { - uint32_t samples : 31; - bool verbose : 1; - } PACKED payload; + lf_sample_payload_t payload; payload.samples = (samples & 0xFFFF); payload.verbose = verbose; diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index af019eadd..4b0b21c0e 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -274,6 +274,17 @@ typedef struct { uint8_t data[]; } PACKED lf_hitag_t; +// For CMD_LF_SNIFF_RAW_ADC and CMD_LF_ACQ_RAW_ADC +#define LF_SAMPLES_BITS 30 +#define MAX_LF_SAMPLES ((((uint32_t)1u) << LF_SAMPLES_BITS) - 1) + +typedef struct { + // 64KB SRAM -> 524288 bits(max sample num) < 2^30 + uint32_t samples : LF_SAMPLES_BITS; + bool realtime : 1; + bool verbose : 1; +} PACKED lf_sample_payload_t; + typedef struct { uint8_t blockno; uint8_t keytype; From e1dc17df1ab0ae832c02464d5d170331af8bcfd9 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Tue, 14 Nov 2023 01:12:21 +0800 Subject: [PATCH 02/11] Add async_usb_write_XX() --- common_arm/usb_cdc.c | 122 +++++++++++++++++++++++++++++++++++++++++-- common_arm/usb_cdc.h | 5 ++ 2 files changed, 124 insertions(+), 3 deletions(-) diff --git a/common_arm/usb_cdc.c b/common_arm/usb_cdc.c index 4787ce112..a1fa96f5d 100644 --- a/common_arm/usb_cdc.c +++ b/common_arm/usb_cdc.c @@ -114,6 +114,7 @@ AT91SAM7S256 USB Device Port #define SET_LINE_CODING 0x2021 #define SET_CONTROL_LINE_STATE 0x2221 +static bool isAsyncRequestFinished = false; static AT91PS_UDP pUdp = AT91C_BASE_UDP; static uint8_t btConfiguration = 0; static uint8_t btConnection = 0; @@ -638,6 +639,10 @@ bool usb_poll(void) { return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank); } +inline uint16_t usb_available_length(void) { + return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16); +} + /** In github PR #129, some users appears to get a false positive from usb_poll, which returns true, but the usb_read operation @@ -649,7 +654,7 @@ bool usb_poll(void) { bool usb_poll_validate_length(void) { if (!usb_check()) return false; if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false; - return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0; + return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0; } /* @@ -671,7 +676,7 @@ uint32_t usb_read(uint8_t *data, size_t len) { if (pUdp->UDP_CSR[AT91C_EP_OUT] & bank) { - packetSize = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16; + packetSize = ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16); packetSize = MIN(packetSize, len); len -= packetSize; while (packetSize--) @@ -727,7 +732,7 @@ uint32_t usb_read_ng(uint8_t *data, size_t len) { if ((pUdp->UDP_CSR[AT91C_EP_OUT] & bank)) { - uint32_t available = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16; + uint32_t available = ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16); packetSize = MIN(available, len); available -= packetSize; len -= packetSize; @@ -821,6 +826,117 @@ int usb_write(const uint8_t *data, const size_t len) { return PM3_SUCCESS; } +/* + *---------------------------------------------------------------------------- + * \fn async_usb_write_start + * \brief Start async write process + * \return PM3_EIO if USB is invalid, PM3_SUCCESS if it is ready for write + * + * This function checks if the USB is connected, and wait until the FIFO + * is ready to be filled. + * + * Warning: usb_write() should not be called between + * async_usb_write_start() and async_usb_write_stop(). + *---------------------------------------------------------------------------- +*/ +int async_usb_write_start(void) { + + if (!usb_check()) return PM3_EIO; + + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) { + if (!usb_check()) return PM3_EIO; + } + + isAsyncRequestFinished = false; + return PM3_SUCCESS; +} + +/* + *---------------------------------------------------------------------------- + * \fn async_usb_write_pushByte + * \brief Push one byte to the FIFO of IN endpoint (time-critical) + * + * This function simply push a byte to the FIFO of IN endpoint. + * The FIFO size is AT91C_EP_IN_SIZE. Make sure this function is not called + * over AT91C_EP_IN_SIZE times between each async_usb_write_requestWrite(). + *---------------------------------------------------------------------------- +*/ +inline void async_usb_write_pushByte(uint8_t data) { + pUdp->UDP_FDR[AT91C_EP_IN] = data; + isAsyncRequestFinished = false; +} + +/* + *---------------------------------------------------------------------------- + * \fn async_usb_write_requestWrite + * \brief Request a write operation (time-critical) + * \return false if the last write request is not finished, true if success + * + * This function requests a write operation from FIFO to the USB bus, + * and switch the internal banks of FIFO. It doesn't wait for the end of + * transmission from FIFO to the USB bus. + * + * Note: This function doesn't check if the usb is valid, as it is + * time-critical. + *---------------------------------------------------------------------------- +*/ +inline bool async_usb_write_requestWrite(void) { + + // check if last request is finished + if (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) { + return false; + } + + // clear transmission completed flag + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {}; + + // start of transmission + UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + + // hack: no need to wait if UDP_CSR and UDP_FDR are not used immediately. + // while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY)) {}; + isAsyncRequestFinished = true; + return true; +} + +/* + *---------------------------------------------------------------------------- + * \fn async_usb_write_stop + * \brief Stop async write process + * \return PM3_EIO if USB is invalid, PM3_SUCCESS if data is written + * + * This function makes sure the data left in the FIFO is written to the + * USB bus. + * + * Warning: usb_write() should not be called between + * async_usb_write_start() and async_usb_write_stop(). + *---------------------------------------------------------------------------- +*/ +int async_usb_write_stop(void) { + // Wait for the end of transfer + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) { + if (!usb_check()) return PM3_EIO; + } + + // clear transmission completed flag + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {}; + + // FIFO is not empty, request a write in non-ping-pong mode + if (isAsyncRequestFinished == false) { + UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + + while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { + if (!usb_check()) return PM3_EIO; + } + + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {}; + } + return PM3_SUCCESS; +} + /* *---------------------------------------------------------------------------- * \fn AT91F_USB_SendData diff --git a/common_arm/usb_cdc.h b/common_arm/usb_cdc.h index e7f6f3d09..aab8e2c5c 100644 --- a/common_arm/usb_cdc.h +++ b/common_arm/usb_cdc.h @@ -27,9 +27,14 @@ void usb_disable(void); void usb_enable(void); bool usb_check(void); bool usb_poll(void); +uint16_t usb_available_length(void); bool usb_poll_validate_length(void); uint32_t usb_read(uint8_t *data, size_t len); int usb_write(const uint8_t *data, const size_t len); +int async_usb_write_start(void); +void async_usb_write_pushByte(uint8_t data); +bool async_usb_write_requestWrite(void); +int async_usb_write_stop(void); uint32_t usb_read_ng(uint8_t *data, size_t len); void usb_update_serial(uint64_t newSerialNumber); From b4cc7c02cdfedfc04bd90b682007459acb7902bf Mon Sep 17 00:00:00 2001 From: wh201906 Date: Tue, 14 Nov 2023 01:40:31 +0800 Subject: [PATCH 03/11] Real-time LF sampling mode on armsrc --- armsrc/appmain.c | 17 +++++-- armsrc/lfsampling.c | 121 ++++++++++++++++++++++++++++++++++++++++++++ armsrc/lfsampling.h | 10 ++++ armsrc/util.c | 8 +++ armsrc/util.h | 1 + include/common.h | 14 +++++ 6 files changed, 166 insertions(+), 5 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index dded4be55..f1afc3c62 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -852,8 +852,12 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_LF_ACQ_RAW_ADC: { lf_sample_payload_t *payload = (lf_sample_payload_t *)packet->data.asBytes; - uint32_t bits = SampleLF(payload->verbose, payload->samples, true); - reply_ng(CMD_LF_ACQ_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits)); + if (payload->realtime) { + ReadLF_realtime(true); + } else { + uint32_t bits = SampleLF(payload->verbose, payload->samples, true); + reply_ng(CMD_LF_ACQ_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits)); + } break; } case CMD_LF_MOD_THEN_ACQ_RAW_ADC: { @@ -877,9 +881,12 @@ static void PacketReceived(PacketCommandNG *packet) { } case CMD_LF_SNIFF_RAW_ADC: { lf_sample_payload_t *payload = (lf_sample_payload_t *)packet->data.asBytes; - - uint32_t bits = SniffLF(payload->verbose, payload->samples, true); - reply_ng(CMD_LF_SNIFF_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits)); + if (payload->realtime) { + ReadLF_realtime(false); + } else { + uint32_t bits = SniffLF(payload->verbose, payload->samples, true); + reply_ng(CMD_LF_SNIFF_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits)); + } break; } case CMD_LF_HID_WATCH: { diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index c763bd0c6..123befb3a 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -27,6 +27,7 @@ #include "lfdemod.h" #include "string.h" // memset #include "appmain.h" // print stack +#include "usb_cdc.h" // real-time sampling /* Default LF config is set to: @@ -424,6 +425,126 @@ uint32_t SampleLF(bool verbose, uint32_t sample_size, bool ledcontrol) { BigBuf_Clear_ext(false); return ReadLF(true, verbose, sample_size, ledcontrol); } + +/** + * Do LF sampling and send samples to the USB + * + * Uses parameters in config. Only bits_per_sample = 8 is working now + * + * @param reader_field - true for reading tags, false for sniffing + * @return sampling result +**/ +int ReadLF_realtime(bool reader_field) { + // parameters from config and constants + const uint8_t bits_per_sample = config.bits_per_sample; + const int16_t trigger_threshold = config.trigger_threshold; + int32_t samples_to_skip = config.samples_to_skip; + const uint8_t decimation = config.decimation; + + uint32_t sample_size = 64; + const int8_t size_threshold_table[9] = {0, 64, 64, 60, 64, 60, 60, 56, 64}; + const int8_t size_threshold = size_threshold_table[bits_per_sample]; + + // DoAcquisition() start + uint8_t last_byte = 0; + uint8_t curr_byte = 0; + int return_value = PM3_SUCCESS; + + initSampleBuffer(&sample_size); // sample size in bytes + if (sample_size != 64) { + return PM3_EFAILED; + } + + sample_size <<= 3; // sample size in bits + sample_size /= bits_per_sample; // sample count + + bool trigger_hit = false; + int16_t checked = 0; + + return_value = async_usb_write_start(); + if (return_value != PM3_SUCCESS) { + return return_value; + } + + BigBuf_Clear_ext(false); + LFSetupFPGAForADC(config.divisor, reader_field); + + while (BUTTON_PRESS() == false) { + // only every 4000th times, in order to save time when collecting samples. + // interruptible only when logging not yet triggered + if (unlikely(trigger_hit == false && (checked >= 4000))) { + if (data_available()) { + checked = -1; + break; + } else { + checked = 0; + } + } + ++checked; + + WDT_HIT(); + + if ((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY)) { + LED_D_ON(); + } + + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + + // (RDV4) Test point 8 (TP8) can be used to trigger oscilloscope + LED_D_OFF(); + + // threshold either high or low values 128 = center 0. if trigger = 178 + if (unlikely(trigger_hit == false)) { + if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) { + continue; + } + trigger_hit = true; + } + + if (unlikely(samples_to_skip > 0)) { + samples_to_skip--; + continue; + } + + logSample(sample, decimation, bits_per_sample, false); + + // write to USB FIFO if byte changed + curr_byte = data.numbits >> 3; + if (curr_byte > last_byte) { + async_usb_write_pushByte(data.buffer[last_byte]); + } + last_byte = curr_byte; + + if (samples.total_saved == size_threshold) { + // request usb transmission and change FIFO bank + if (async_usb_write_requestWrite() == false) { + return_value = PM3_EIO; + break; + } + + // reset sample + last_byte = 0; + data.numbits = 0; + samples.counter = size_threshold; + samples.total_saved = 0; + + } else if (samples.total_saved == 1) { + // check if there is any data from client + if (data_available_fast()) { + break; + } + } + } + } + LED_D_OFF(); + return_value = async_usb_write_stop(); + + // DoAcquisition() end + StopTicks(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + return return_value; +} /** * Initializes the FPGA for sniffer-mode (field off), and acquires the samples. * @return number of bits sampled diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 8a8e40868..27844d81c 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -51,6 +51,16 @@ void doT55x7Acquisition(size_t sample_size, bool ledcontrol); **/ uint32_t SampleLF(bool verbose, uint32_t sample_size, bool ledcontrol); +/** + * Do LF sampling and send samples to the USB + * + * Uses parameters in config. Only bits_per_sample = 8 is working now + * + * @param reader_field - true for reading tags, false for sniffing + * @return sampling result +**/ +int ReadLF_realtime(bool reader_field); + /** * Initializes the FPGA for sniff-mode (field off), and acquires the samples. * @return number of bits sampled diff --git a/armsrc/util.c b/armsrc/util.c index fe40b6b43..70a6d01ef 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -305,3 +305,11 @@ bool data_available(void) { return usb_poll_validate_length(); #endif } + +bool data_available_fast(void) { +#ifdef WITH_FPC_USART_HOST + return usb_available_length() || (usart_rxdata_available() > 0); +#else + return usb_available_length(); +#endif +} diff --git a/armsrc/util.h b/armsrc/util.h index 65d24f026..da45219a7 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -101,5 +101,6 @@ void SpinUp(uint32_t speed); int BUTTON_CLICKED(int ms); int BUTTON_HELD(int ms); bool data_available(void); +bool data_available_fast(void); #endif diff --git a/include/common.h b/include/common.h index a97545996..37cf254d9 100644 --- a/include/common.h +++ b/include/common.h @@ -196,4 +196,18 @@ extern bool g_tearoff_enabled; #define CLEAR_BIT(data, i) *(data + (i / 8)) &= ~(1 << (7 - (i % 8))) #define FLIP_BIT(data, i) *(data + (i / 8)) ^= (1 << (7 - (i % 8))) +// GCC extension +// from client/deps/tinycbor/compilersupport_p.h +#ifdef __GNUC__ +#ifndef likely +# define likely(x) __builtin_expect(!!(x), 1) +#endif +#ifndef unlikely +# define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#else +# define likely(x) (x) +# define unlikely(x) (x) +#endif + #endif From 8fdf04fcfbe88fc118b6b158bb3e5ae0cac0f5dd Mon Sep 17 00:00:00 2001 From: wh201906 Date: Tue, 14 Nov 2023 02:17:45 +0800 Subject: [PATCH 04/11] Receive raw data on the client --- client/src/comms.c | 359 ++++++++++++++++++++++++++++++++------------- client/src/comms.h | 8 +- 2 files changed, 260 insertions(+), 107 deletions(-) diff --git a/client/src/comms.c b/client/src/comms.c index 9460c7024..be2d481dc 100644 --- a/client/src/comms.c +++ b/client/src/comms.c @@ -41,6 +41,10 @@ capabilities_t g_pm3_capabilities; static pthread_t communication_thread; static bool comm_thread_dead = false; +static bool comm_raw_mode = false; +static uint8_t *comm_raw_data = NULL; +static size_t comm_raw_len = 0; +static size_t comm_raw_pos = 0; // Transmit buffer. static PacketCommandOLD txBuffer; @@ -346,6 +350,8 @@ __attribute__((force_align_arg_pointer)) bool commfailed = false; PacketResponseNG rx; PacketResponseNGRaw rx_raw; + // stash the last state of is_receiving_raw, to detect if state changed + bool is_receiving_raw_last = false; #if defined(__MACH__) && defined(__APPLE__) disableAppNap("Proxmark3 polling UART"); @@ -368,136 +374,179 @@ __attribute__((force_align_arg_pointer)) break; } - res = uart_receive(sp, (uint8_t *)&rx_raw.pre, sizeof(PacketResponseNGPreamble), &rxlen); + bool is_receiving_raw = __atomic_load_n(&comm_raw_mode, __ATOMIC_SEQ_CST); - if ((res == PM3_SUCCESS) && (rxlen == sizeof(PacketResponseNGPreamble))) { - rx.magic = rx_raw.pre.magic; - uint16_t length = rx_raw.pre.length; - rx.ng = rx_raw.pre.ng; - rx.status = rx_raw.pre.status; - rx.cmd = rx_raw.pre.cmd; - if (rx.magic == RESPONSENG_PREAMBLE_MAGIC) { // New style NG reply - if (length > PM3_CMD_DATA_SIZE) { - PrintAndLogEx(WARNING, "Received packet frame with incompatible length: 0x%04x", length); + if (is_receiving_raw) { + uint8_t *bufferData = __atomic_load_n(&comm_raw_data, __ATOMIC_SEQ_CST); // read only + size_t bufferLen = __atomic_load_n(&comm_raw_len, __ATOMIC_SEQ_CST); // read only + size_t bufferPos = __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST); // read and write + if (bufferPos < bufferLen) { + size_t rxMaxLen = bufferLen - bufferPos; + + rxMaxLen = MIN(COMM_RAW_RECEIVE_LEN, rxMaxLen); + + res = uart_receive(sp, bufferData + bufferPos, rxMaxLen, &rxlen); + if (res == PM3_SUCCESS) { + uint64_t clk = msclock(); + __atomic_store_n(&timeout_start_time, clk, __ATOMIC_SEQ_CST); + __atomic_store_n(&comm_raw_pos, bufferPos + rxlen, __ATOMIC_SEQ_CST); + } else if (res != PM3_ENODATA) { + PrintAndLogEx(WARNING, "Error when reading raw data: %zu/%zu, %d", bufferPos, bufferLen, res); error = true; + if (res == PM3_ENOTTY) { + commfailed = true; + } } + } else { + // ignore data when bufferPos >= bufferLen and is_receiving_raw has not been set to false + uint8_t dummyData[64]; + uint32_t dummyLen; + uart_receive(sp, dummyData, sizeof(dummyData), &dummyLen); - if ((!error) && (length > 0)) { // Get the variable length payload + // set the buffer as undefined + // comm_raw_data == NULL is used in SetCommunicationReceiveMode() + __atomic_store_n(&comm_raw_data, NULL, __ATOMIC_SEQ_CST); + } + } else { + if (is_receiving_raw_last) { + // is_receiving_raw changed from true to false - res = uart_receive(sp, (uint8_t *)&rx_raw.data, length, &rxlen); - if ((res != PM3_SUCCESS) || (rxlen != length)) { - PrintAndLogEx(WARNING, "Received packet frame with variable part too short? %d/%d", rxlen, length); + // set the buffer as undefined + // comm_raw_data == NULL is used in SetCommunicationReceiveMode() + __atomic_store_n(&comm_raw_data, NULL, __ATOMIC_SEQ_CST); + } + res = uart_receive(sp, (uint8_t *)&rx_raw.pre, sizeof(PacketResponseNGPreamble), &rxlen); + + if ((res == PM3_SUCCESS) && (rxlen == sizeof(PacketResponseNGPreamble))) { + rx.magic = rx_raw.pre.magic; + uint16_t length = rx_raw.pre.length; + rx.ng = rx_raw.pre.ng; + rx.status = rx_raw.pre.status; + rx.cmd = rx_raw.pre.cmd; + if (rx.magic == RESPONSENG_PREAMBLE_MAGIC) { // New style NG reply + if (length > PM3_CMD_DATA_SIZE) { + PrintAndLogEx(WARNING, "Received packet frame with incompatible length: 0x%04x", length); error = true; - } else { + } - if (rx.ng) { // Received a valid NG frame - memcpy(&rx.data, &rx_raw.data, length); - rx.length = length; - if ((rx.cmd == g_conn.last_command) && (rx.status == PM3_SUCCESS)) { - ACK_received = true; - } + if ((!error) && (length > 0)) { // Get the variable length payload + + res = uart_receive(sp, (uint8_t *)&rx_raw.data, length, &rxlen); + if ((res != PM3_SUCCESS) || (rxlen != length)) { + PrintAndLogEx(WARNING, "Received packet frame with variable part too short? %d/%d", rxlen, length); + error = true; } else { - uint64_t arg[3]; - if (length < sizeof(arg)) { - PrintAndLogEx(WARNING, "Received MIX packet frame with incompatible length: 0x%04x", length); - error = true; - } - if (!error) { // Received a valid MIX frame - memcpy(arg, &rx_raw.data, sizeof(arg)); - rx.oldarg[0] = arg[0]; - rx.oldarg[1] = arg[1]; - rx.oldarg[2] = arg[2]; - memcpy(&rx.data, ((uint8_t *)&rx_raw.data) + sizeof(arg), length - sizeof(arg)); - rx.length = length - sizeof(arg); - if (rx.cmd == CMD_ACK) { + + if (rx.ng) { // Received a valid NG frame + memcpy(&rx.data, &rx_raw.data, length); + rx.length = length; + if ((rx.cmd == g_conn.last_command) && (rx.status == PM3_SUCCESS)) { ACK_received = true; } + } else { + uint64_t arg[3]; + if (length < sizeof(arg)) { + PrintAndLogEx(WARNING, "Received MIX packet frame with incompatible length: 0x%04x", length); + error = true; + } + if (!error) { // Received a valid MIX frame + memcpy(arg, &rx_raw.data, sizeof(arg)); + rx.oldarg[0] = arg[0]; + rx.oldarg[1] = arg[1]; + rx.oldarg[2] = arg[2]; + memcpy(&rx.data, ((uint8_t *)&rx_raw.data) + sizeof(arg), length - sizeof(arg)); + rx.length = length - sizeof(arg); + if (rx.cmd == CMD_ACK) { + ACK_received = true; + } + } } } - } - } else if ((!error) && (length == 0)) { // we received an empty frame - if (rx.ng) - rx.length = 0; // set received length to 0 - else { // old frames can't be empty - PrintAndLogEx(WARNING, "Received empty MIX packet frame (length: 0x00)"); - error = true; - } - } - - if (!error) { // Get the postamble - res = uart_receive(sp, (uint8_t *)&rx_raw.foopost, sizeof(PacketResponseNGPostamble), &rxlen); - if ((res != PM3_SUCCESS) || (rxlen != sizeof(PacketResponseNGPostamble))) { - PrintAndLogEx(WARNING, "Received packet frame without postamble"); - error = true; - } - } - - if (!error) { // Check CRC, accept MAGIC as placeholder - rx.crc = rx_raw.foopost.crc; - if (rx.crc != RESPONSENG_POSTAMBLE_MAGIC) { - uint8_t first, second; - compute_crc(CRC_14443_A, (uint8_t *)&rx_raw, sizeof(PacketResponseNGPreamble) + length, &first, &second); - if ((first << 8) + second != rx.crc) { - PrintAndLogEx(WARNING, "Received packet frame with invalid CRC %02X%02X <> %04X", first, second, rx.crc); + } else if ((!error) && (length == 0)) { // we received an empty frame + if (rx.ng) + rx.length = 0; // set received length to 0 + else { // old frames can't be empty + PrintAndLogEx(WARNING, "Received empty MIX packet frame (length: 0x00)"); error = true; } } - } - if (!error) { // Received a valid OLD frame -#ifdef COMMS_DEBUG - PrintAndLogEx(NORMAL, "Receiving %s:", rx.ng ? "NG" : "MIX"); -#endif -#ifdef COMMS_DEBUG_RAW - print_hex_break((uint8_t *)&rx_raw.pre, sizeof(PacketResponseNGPreamble), 32); - print_hex_break((uint8_t *)&rx_raw.data, rx_raw.pre.length, 32); - print_hex_break((uint8_t *)&rx_raw.foopost, sizeof(PacketResponseNGPostamble), 32); -#endif - PacketResponseReceived(&rx); - } - } else { // Old style reply - PacketResponseOLD rx_old; - memcpy(&rx_old, &rx_raw.pre, sizeof(PacketResponseNGPreamble)); - res = uart_receive(sp, ((uint8_t *)&rx_old) + sizeof(PacketResponseNGPreamble), sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble), &rxlen); - if ((res != PM3_SUCCESS) || (rxlen != sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble))) { - PrintAndLogEx(WARNING, "Received packet OLD frame with payload too short? %d/%zu", rxlen, sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble)); - error = true; - } - if (!error) { + if (!error) { // Get the postamble + res = uart_receive(sp, (uint8_t *)&rx_raw.foopost, sizeof(PacketResponseNGPostamble), &rxlen); + if ((res != PM3_SUCCESS) || (rxlen != sizeof(PacketResponseNGPostamble))) { + PrintAndLogEx(WARNING, "Received packet frame without postamble"); + error = true; + } + } + + if (!error) { // Check CRC, accept MAGIC as placeholder + rx.crc = rx_raw.foopost.crc; + if (rx.crc != RESPONSENG_POSTAMBLE_MAGIC) { + uint8_t first, second; + compute_crc(CRC_14443_A, (uint8_t *)&rx_raw, sizeof(PacketResponseNGPreamble) + length, &first, &second); + if ((first << 8) + second != rx.crc) { + PrintAndLogEx(WARNING, "Received packet frame with invalid CRC %02X%02X <> %04X", first, second, rx.crc); + error = true; + } + } + } + if (!error) { // Received a valid OLD frame #ifdef COMMS_DEBUG - PrintAndLogEx(NORMAL, "Receiving OLD:"); + PrintAndLogEx(NORMAL, "Receiving %s:", rx.ng ? "NG" : "MIX"); #endif #ifdef COMMS_DEBUG_RAW - print_hex_break((uint8_t *)&rx_old.cmd, sizeof(rx_old.cmd), 32); - print_hex_break((uint8_t *)&rx_old.arg, sizeof(rx_old.arg), 32); - print_hex_break((uint8_t *)&rx_old.d, sizeof(rx_old.d), 32); + print_hex_break((uint8_t *)&rx_raw.pre, sizeof(PacketResponseNGPreamble), 32); + print_hex_break((uint8_t *)&rx_raw.data, rx_raw.pre.length, 32); + print_hex_break((uint8_t *)&rx_raw.foopost, sizeof(PacketResponseNGPostamble), 32); #endif - rx.ng = false; - rx.magic = 0; - rx.status = 0; - rx.crc = 0; - rx.cmd = rx_old.cmd; - rx.oldarg[0] = rx_old.arg[0]; - rx.oldarg[1] = rx_old.arg[1]; - rx.oldarg[2] = rx_old.arg[2]; - rx.length = PM3_CMD_DATA_SIZE; - memcpy(&rx.data, &rx_old.d, rx.length); - PacketResponseReceived(&rx); - if (rx.cmd == CMD_ACK) { - ACK_received = true; + PacketResponseReceived(&rx); + } + } else { // Old style reply + PacketResponseOLD rx_old; + memcpy(&rx_old, &rx_raw.pre, sizeof(PacketResponseNGPreamble)); + + res = uart_receive(sp, ((uint8_t *)&rx_old) + sizeof(PacketResponseNGPreamble), sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble), &rxlen); + if ((res != PM3_SUCCESS) || (rxlen != sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble))) { + PrintAndLogEx(WARNING, "Received packet OLD frame with payload too short? %d/%zu", rxlen, sizeof(PacketResponseOLD) - sizeof(PacketResponseNGPreamble)); + error = true; + } + if (!error) { +#ifdef COMMS_DEBUG + PrintAndLogEx(NORMAL, "Receiving OLD:"); +#endif +#ifdef COMMS_DEBUG_RAW + print_hex_break((uint8_t *)&rx_old.cmd, sizeof(rx_old.cmd), 32); + print_hex_break((uint8_t *)&rx_old.arg, sizeof(rx_old.arg), 32); + print_hex_break((uint8_t *)&rx_old.d, sizeof(rx_old.d), 32); +#endif + rx.ng = false; + rx.magic = 0; + rx.status = 0; + rx.crc = 0; + rx.cmd = rx_old.cmd; + rx.oldarg[0] = rx_old.arg[0]; + rx.oldarg[1] = rx_old.arg[1]; + rx.oldarg[2] = rx_old.arg[2]; + rx.length = PM3_CMD_DATA_SIZE; + memcpy(&rx.data, &rx_old.d, rx.length); + PacketResponseReceived(&rx); + if (rx.cmd == CMD_ACK) { + ACK_received = true; + } } } - } - } else { - if (rxlen > 0) { - PrintAndLogEx(WARNING, "Received packet frame preamble too short: %d/%zu", rxlen, sizeof(PacketResponseNGPreamble)); - error = true; - } - if (res == PM3_ENOTTY) { - commfailed = true; + } else { + if (rxlen > 0) { + PrintAndLogEx(WARNING, "Received packet frame preamble too short: %d/%zu", rxlen, sizeof(PacketResponseNGPreamble)); + error = true; + } + if (res == PM3_ENOTTY) { + commfailed = true; + } } } + is_receiving_raw_last = is_receiving_raw; // TODO if error, shall we resync ? pthread_mutex_lock(&txBufferMutex); @@ -560,6 +609,45 @@ bool IsCommunicationThreadDead(void) { return ret; } +// To start raw receive mode: +// 1. Call SetCommunicationRawReceiveBuffer(...) +// 2. Call SetCommunicationReceiveMode(true) +// +// To stop raw receive mode: +// Call SetCommunicationReceiveMode(false) +// +// Note: +// 1. The receiving thread won't accept any normal packets after calling +// SetCommunicationReceiveMode(true). You need to call +// SetCommunicationReceiveMode(false) to stop the raw receiving process. +// 2. If the received size >= len used in SetCommunicationRawReceiveBuffer(), +// The receiving thread will ignore the incoming data to prevent overflow. +// 3. Normally you only need WaitForRawDataTimeout() rather than the +// low level functions like SetCommunicationReceiveMode(), +// SetCommunicationRawReceiveBuffer() and GetCommunicationRawReceiveNum() + +bool SetCommunicationReceiveMode(bool isRawMode) { + if (isRawMode) { + uint8_t *buffer = __atomic_load_n(&comm_raw_data, __ATOMIC_SEQ_CST); + if (buffer == NULL) { + PrintAndLogEx(ERR, "Buffer for raw data is not set"); + return false; + } + } + __atomic_store_n(&comm_raw_mode, isRawMode, __ATOMIC_SEQ_CST); + return true; +} + +void SetCommunicationRawReceiveBuffer(uint8_t *buffer, size_t len) { + __atomic_store_n(&comm_raw_data, buffer, __ATOMIC_SEQ_CST); + __atomic_store_n(&comm_raw_len, len, __ATOMIC_SEQ_CST); + __atomic_store_n(&comm_raw_pos, 0, __ATOMIC_SEQ_CST); +} + +size_t GetCommunicationRawReceiveNum(void) { + return __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST); +} + bool OpenProxmark(pm3_device_t **dev, const char *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed) { if (!wait_for_port) { @@ -738,6 +826,67 @@ static size_t communication_delay(void) { return 0; } + +/** + * @brief Wait for receiving a specified amount of bytes + * + * @param buffer The receive buffer + * @param len The maximum receive byte size + * @param ms_timeout the maximum timeout + * @param show_process print how many bytes are received + * @return the number of received bytes + */ +size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, bool show_process) { + uint8_t print_counter = 0; + size_t last_pos = 0; + + // Add delay depending on the communication channel & speed + if (ms_timeout != (size_t) - 1) { + ms_timeout += communication_delay(); + } + __atomic_store_n(&timeout_start_time, msclock(), __ATOMIC_SEQ_CST); + + SetCommunicationRawReceiveBuffer(buffer, len); + SetCommunicationReceiveMode(true); + + size_t pos = 0; + while (pos < len) { + + if (kbd_enter_pressed()) { + // send anything to stop the transfer + PrintAndLogEx(INFO, "Stopping"); + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + } + + pos = __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST); + + // check the timeout if pos is not updated + if (last_pos == pos) { + uint64_t tmp_clk = __atomic_load_n(&timeout_start_time, __ATOMIC_SEQ_CST); + if ((msclock() - tmp_clk > ms_timeout)) { + break; + } + } else { + // print when (print_counter % 64) == 0 + if (show_process && (print_counter & 0x3F) == 0) { + PrintAndLogEx(INFO, "[%zu/%zu]", pos, len); + } + } + + print_counter++; + last_pos = pos; + msleep(10); + } + if (pos == len) { + SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + msleep(ms_timeout); + } + SetCommunicationReceiveMode(false); + pos = __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST); + PrintAndLogEx(INFO, "Done: [%zu/%zu]", pos, len); + return pos; +} + /** * @brief Waits for a certain response type. This method waits for a maximum of * ms_timeout milliseconds for a specified response command. diff --git a/client/src/comms.h b/client/src/comms.h index 333b2bf1c..632f0d29f 100644 --- a/client/src/comms.h +++ b/client/src/comms.h @@ -45,6 +45,8 @@ extern "C" { #define CMD_BUFFER_SIZE 100 #endif +#define COMM_RAW_RECEIVE_LEN (1024) + typedef enum { BIG_BUF, BIG_BUF_EML, @@ -96,10 +98,14 @@ void clearCommandBuffer(void); #define FLASHMODE_SPEED 460800 bool IsCommunicationThreadDead(void); +bool SetCommunicationReceiveMode(bool isRawMode); +void SetCommunicationRawReceiveBuffer(uint8_t *buffer, size_t len); +size_t GetCommunicationRawReceiveNum(void); bool OpenProxmark(pm3_device_t **dev, const char *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed); int TestProxmark(pm3_device_t *dev); void CloseProxmark(pm3_device_t *dev); +size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, bool show_process); bool WaitForResponseTimeoutW(uint32_t cmd, PacketResponseNG *response, size_t ms_timeout, bool show_warning); bool WaitForResponseTimeout(uint32_t cmd, PacketResponseNG *response, size_t ms_timeout); bool WaitForResponse(uint32_t cmd, PacketResponseNG *response); @@ -111,5 +117,3 @@ bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint3 } #endif #endif - - From 42ab3ee1e60a756cf69a2de2254eda0916e6f598 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Tue, 14 Nov 2023 02:57:52 +0800 Subject: [PATCH 05/11] 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); From 8b6a274e289cd96f16616de741f0d02fb10d1e6e Mon Sep 17 00:00:00 2001 From: wh201906 Date: Tue, 14 Nov 2023 10:05:13 +0800 Subject: [PATCH 06/11] Bigger graph buffer 1280000 samples -> 10.24s for 125kHz 8bit sampling Allocate graph related memory on heap --- client/src/cmddata.c | 27 ++++++++++++++++++--------- client/src/cmdlf.c | 4 +++- client/src/cmdlfhid.c | 4 +++- client/src/cmdlfindala.c | 3 ++- client/src/cmdlfio.c | 7 +++++-- client/src/cmdlfparadox.c | 8 +++++--- client/src/cmdlfpyramid.c | 7 +++++-- client/src/graph.h | 2 +- 8 files changed, 42 insertions(+), 20 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 534663844..3339f9681 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1011,7 +1011,7 @@ static int CmdUndecimate(const char *Cmd) { CLIParserFree(ctx); //We have memory, don't we? - int swap[MAX_GRAPH_TRACE_LEN] = {0}; + int *swap = calloc(MAX_GRAPH_TRACE_LEN, sizeof(int)); uint32_t g_index = 0, s_index = 0; while (g_index < g_GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN) { int count = 0; @@ -1028,6 +1028,7 @@ static int CmdUndecimate(const char *Cmd) { memcpy(g_GraphBuffer, swap, s_index * sizeof(int)); g_GraphTraceLen = s_index; RepaintGraphWindow(); + free(swap); return PM3_SUCCESS; } @@ -1707,7 +1708,7 @@ int CmdHpf(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, true); CLIParserFree(ctx); - uint8_t bits[g_GraphTraceLen]; + uint8_t *bits = malloc(g_GraphTraceLen); size_t size = getFromGraphBuf(bits); removeSignalOffset(bits, size); // push it back to graph @@ -1716,6 +1717,7 @@ int CmdHpf(const char *Cmd) { computeSignalProperties(bits, size); RepaintGraphWindow(); + free(bits); return PM3_SUCCESS; } @@ -2103,12 +2105,13 @@ static int CmdLoad(const char *Cmd) { PrintAndLogEx(SUCCESS, "loaded " _YELLOW_("%zu") " samples", g_GraphTraceLen); if (nofix == false) { - uint8_t bits[g_GraphTraceLen]; + uint8_t *bits = malloc(g_GraphTraceLen); size_t size = getFromGraphBuf(bits); removeSignalOffset(bits, size); setGraphBuf(bits, size); computeSignalProperties(bits, size); + free(bits); } setClockGrid(0, 0); @@ -2240,12 +2243,13 @@ int CmdNorm(const char *Cmd) { } } - 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); RepaintGraphWindow(); + free(bits); return PM3_SUCCESS; } @@ -2386,12 +2390,13 @@ static int CmdDirectionalThreshold(const char *Cmd) { directionalThreshold(g_GraphBuffer, g_GraphBuffer, g_GraphTraceLen, up, down); // set signal properties low/high/mean/amplitude and isnoice detection - 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_noice detection computeSignalProperties(bits, size); RepaintGraphWindow(); + free(bits); return PM3_SUCCESS; } @@ -2429,11 +2434,12 @@ static int CmdZerocrossings(const char *Cmd) { } } - 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); RepaintGraphWindow(); + free(bits); return PM3_SUCCESS; } @@ -2742,11 +2748,12 @@ static int CmdDataIIR(const char *Cmd) { iceSimple_Filter(g_GraphBuffer, g_GraphTraceLen, k); - 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); RepaintGraphWindow(); + free(bits); return PM3_SUCCESS; } @@ -3369,11 +3376,12 @@ static int CmdCenterThreshold(const char *Cmd) { centerThreshold(g_GraphBuffer, g_GraphBuffer, g_GraphTraceLen, up, down); // set signal properties low/high/mean/amplitude and isnoice detection - 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_noice detection computeSignalProperties(bits, size); RepaintGraphWindow(); + free(bits); return PM3_SUCCESS; } @@ -3414,11 +3422,12 @@ static int CmdEnvelope(const char *Cmd) { envelope_square(g_GraphBuffer, g_GraphBuffer, g_GraphTraceLen); - 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_noice detection computeSignalProperties(bits, size); RepaintGraphWindow(); + free(bits); return PM3_SUCCESS; } diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index f078f795f..02f630f30 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -433,7 +433,7 @@ int CmdFlexdemod(const char *Cmd) { #endif int i, j, start, bit, sum; - int data[g_GraphTraceLen]; + int *data = malloc(g_GraphTraceLen * sizeof(int)); memcpy(data, g_GraphBuffer, g_GraphTraceLen); size_t size = g_GraphTraceLen; @@ -454,6 +454,7 @@ int CmdFlexdemod(const char *Cmd) { if (start == size - LONG_WAIT) { PrintAndLogEx(WARNING, "nothing to wait for"); + free(data); return PM3_ENODATA; } @@ -497,6 +498,7 @@ int CmdFlexdemod(const char *Cmd) { } } RepaintGraphWindow(); + free(data); return PM3_SUCCESS; } diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index 7e3763ec5..8e3a1e8eb 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -117,10 +117,11 @@ int demodHID(bool verbose) { //raw fsk demod no manchester decoding no start bit finding just get binary from wave uint32_t hi2 = 0, hi = 0, lo = 0; - uint8_t bits[g_GraphTraceLen]; + uint8_t *bits = malloc(g_GraphTraceLen); size_t size = getFromGraphBuf(bits); if (size == 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID not enough samples")); + free(bits); return PM3_ESOFT; } //get binary from fsk wave @@ -146,6 +147,7 @@ int demodHID(bool verbose) { setDemodBuff(bits, size, idx); setClockGrid(50, waveIdx + (idx * 50)); + free(bits); if (hi2 == 0 && hi == 0 && lo == 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID no values found")); diff --git a/client/src/cmdlfindala.c b/client/src/cmdlfindala.c index ba1d14205..3e8b3bcd7 100644 --- a/client/src/cmdlfindala.c +++ b/client/src/cmdlfindala.c @@ -403,7 +403,7 @@ static int CmdIndalaDemodAlt(const char *Cmd) { // worst case with g_GraphTraceLen=40000 is < 4096 // under normal conditions it's < 2048 - uint8_t data[MAX_GRAPH_TRACE_LEN] = {0}; + uint8_t *data = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); size_t datasize = getFromGraphBuf(data); uint8_t rawbits[4096] = {0}; @@ -446,6 +446,7 @@ static int CmdIndalaDemodAlt(const char *Cmd) { count = 0; } } + free(data); if (rawbit > 0) { PrintAndLogEx(INFO, "Recovered %d raw bits, expected: %zu", rawbit, g_GraphTraceLen / 32); diff --git a/client/src/cmdlfio.c b/client/src/cmdlfio.c index 454d01a54..a5507ce33 100644 --- a/client/src/cmdlfio.c +++ b/client/src/cmdlfio.c @@ -66,10 +66,11 @@ static int CmdIOProxWatch(const char *Cmd) { int demodIOProx(bool verbose) { (void) verbose; // unused so far int idx = 0, retval = PM3_SUCCESS; - uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); size_t size = getFromGraphBuf(bits); if (size < 65) { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples in GraphBuffer"); + free(bits); return PM3_ESOFT; } //get binary from fsk wave @@ -93,6 +94,7 @@ int demodIOProx(bool verbose) { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox error demoding fsk %d", idx); } } + free(bits); return PM3_ESOFT; } setDemodBuff(bits, size, idx); @@ -103,6 +105,7 @@ int demodIOProx(bool verbose) { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox data not found - FSK Bits: %zu", size); if (size > 92) PrintAndLogEx(DEBUG, "%s", sprint_bytebits_bin_break(bits, 92, 16)); } + free(bits); return PM3_ESOFT; } @@ -156,6 +159,7 @@ int demodIOProx(bool verbose) { printDemodBuff(0, false, false, true); printDemodBuff(0, false, false, false); } + free(bits); return retval; } @@ -441,4 +445,3 @@ int getIOProxBits(uint8_t version, uint8_t fc, uint16_t cn, uint8_t *bits) { PrintAndLogEx(SUCCESS, "IO raw bits:\n %s \n", sprint_bytebits_bin(bits, 64)); return PM3_SUCCESS; } - diff --git a/client/src/cmdlfparadox.c b/client/src/cmdlfparadox.c index d750efa51..f82ef52f2 100644 --- a/client/src/cmdlfparadox.c +++ b/client/src/cmdlfparadox.c @@ -103,10 +103,11 @@ static uint8_t GetParadoxBits(const uint32_t fc, const uint32_t cn, unsigned int int demodParadox(bool verbose, bool oldChksum) { (void) verbose; // unused so far //raw fsk demod no manchester decoding no start bit finding just get binary from wave - uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); size_t size = getFromGraphBuf(bits); if (size == 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox not enough samples"); + free(bits); return PM3_ESOFT; } @@ -125,6 +126,7 @@ int demodParadox(bool verbose, bool oldChksum) { else PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox error demoding fsk %d", idx); + free(bits); return PM3_ESOFT; } @@ -175,6 +177,7 @@ int demodParadox(bool verbose, bool oldChksum) { if (hi2 == 0 && hi == 0 && lo == 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox no value found"); + free(bits); return PM3_ESOFT; } @@ -230,6 +233,7 @@ int demodParadox(bool verbose, bool oldChksum) { printDemodBuff(0, false, false, false); } + free(bits); return PM3_SUCCESS; } @@ -500,5 +504,3 @@ int detectParadox(uint8_t *dest, size_t *size, int *wave_start_idx) { return (int)idx; } - - diff --git a/client/src/cmdlfpyramid.c b/client/src/cmdlfpyramid.c index 80eeb251c..4edc2b287 100644 --- a/client/src/cmdlfpyramid.c +++ b/client/src/cmdlfpyramid.c @@ -43,10 +43,11 @@ static int CmdHelp(const char *Cmd); int demodPyramid(bool verbose) { (void) verbose; // unused so far //raw fsk demod no manchester decoding no start bit finding just get binary from wave - uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); size_t size = getFromGraphBuf(bits); if (size == 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid not enough samples"); + free(bits); return PM3_ESOFT; } //get binary from fsk wave @@ -65,6 +66,7 @@ int demodPyramid(bool verbose) { PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: size not correct: %zu", size); else PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: error demoding fsk idx: %d", idx); + free(bits); return PM3_ESOFT; } setDemodBuff(bits, size, idx); @@ -113,6 +115,7 @@ int demodPyramid(bool verbose) { PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: parity check failed - IDX: %d, hi3: %08X", idx, rawHi3); else PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: at parity check - tag size does not match Pyramid format, SIZE: %zu, IDX: %d, hi3: %08X", size, idx, rawHi3); + free(bits); return PM3_ESOFT; } @@ -181,6 +184,7 @@ int demodPyramid(bool verbose) { printDemodBuff(0, false, false, false); } + free(bits); return PM3_SUCCESS; } @@ -507,4 +511,3 @@ int detectPyramid(uint8_t *dest, size_t *size, int *waveStartIdx) { return (int)startIdx; } - diff --git a/client/src/graph.h b/client/src/graph.h index 3be6c9852..4963fb2b1 100644 --- a/client/src/graph.h +++ b/client/src/graph.h @@ -42,7 +42,7 @@ int GetNrzClock(const char *str, bool verbose); int GetFskClock(const char *str, bool verbose); bool fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge); -#define MAX_GRAPH_TRACE_LEN (40000 * 8) +#define MAX_GRAPH_TRACE_LEN (40000 * 32) #define GRAPH_SAVE 1 #define GRAPH_RESTORE 0 From ab9f49f86ef0ed4b0358b8fadee5707bb1b91a21 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Tue, 14 Nov 2023 10:34:50 +0800 Subject: [PATCH 07/11] Some minor fixes Use longer timeout in WaitForRawDataTimeout() to handle CMD_WTX Fix a wrong type Apply changes to other similar part Remove unused instructions --- armsrc/fpgaloader.c | 2 +- armsrc/lfsampling.c | 23 ++++++++++------------- armsrc/lfzx.c | 2 +- client/src/cmdlf.c | 6 ++++-- include/common.h | 3 +++ 5 files changed, 19 insertions(+), 17 deletions(-) diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index ccc47bcde..7ac52a42a 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -493,7 +493,7 @@ void FpgaDownloadAndGo(int bitstream_version) { #endif // Send waiting time extension request as this will take a while - send_wtx(1500); + send_wtx(FPGA_LOAD_WAIT_TIME); bool verbose = (g_dbglevel > 3); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 123befb3a..df1c7454a 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -229,7 +229,7 @@ void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool // write the current byte data.buffer[data.numbits >> 3] |= sample >> bits_offset; - int numbits = data.numbits + bits_cap; + uint32_t numbits = data.numbits + bits_cap; // write the remaining bits to the next byte data.buffer[numbits >> 3] |= sample << (bits_cap); @@ -306,7 +306,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in // only every 4000th times, in order to save time when collecting samples. // interruptible only when logging not yet triggered - if ((checked >= 4000) && trigger_hit == false) { + if (unlikely(trigger_hit == false && (checked >= 4000))) { if (data_available()) { checked = -1; break; @@ -325,11 +325,11 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - // Test point 8 (TP8) can be used to trigger oscilloscope + // (RDV4) Test point 8 (TP8) can be used to trigger oscilloscope if (ledcontrol) LED_D_OFF(); // threshold either high or low values 128 = center 0. if trigger = 178 - if (trigger_hit == false) { + if (unlikely(trigger_hit == false)) { if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) { if (cancel_after > 0) { cancel_counter++; @@ -338,11 +338,10 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in } continue; } + trigger_hit = true; } - trigger_hit = true; - - if (samples_to_skip > 0) { + if (unlikely(samples_to_skip > 0)) { samples_to_skip--; continue; } @@ -371,6 +370,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in } return data.numbits; } + /** * @brief Does sample acquisition, ignoring the config values set in the sample_config. * This method is typically used by tag-specific readers who just wants to read the samples @@ -441,7 +441,7 @@ int ReadLF_realtime(bool reader_field) { int32_t samples_to_skip = config.samples_to_skip; const uint8_t decimation = config.decimation; - uint32_t sample_size = 64; + uint32_t sample_buffer_len = 64; const int8_t size_threshold_table[9] = {0, 64, 64, 60, 64, 60, 60, 56, 64}; const int8_t size_threshold = size_threshold_table[bits_per_sample]; @@ -450,14 +450,11 @@ int ReadLF_realtime(bool reader_field) { uint8_t curr_byte = 0; int return_value = PM3_SUCCESS; - initSampleBuffer(&sample_size); // sample size in bytes - if (sample_size != 64) { + initSampleBuffer(&sample_buffer_len); + if (sample_buffer_len != 64) { return PM3_EFAILED; } - sample_size <<= 3; // sample size in bits - sample_size /= bits_per_sample; // sample count - bool trigger_hit = false; int16_t checked = 0; diff --git a/armsrc/lfzx.c b/armsrc/lfzx.c index f086c2d71..f95b2c2b7 100644 --- a/armsrc/lfzx.c +++ b/armsrc/lfzx.c @@ -153,7 +153,7 @@ static void zx_get(bool ledcontrol) { volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; (void)sample; - // Test point 8 (TP8) can be used to trigger oscilloscope + // (RDV4) Test point 8 (TP8) can be used to trigger oscilloscope if (ledcontrol) LED_D_OFF(); } diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index 02f630f30..b32f67897 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -721,7 +721,7 @@ static int lf_read_internal(bool realtime, bool verbose, uint64_t samples) { 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); + sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000 + FPGA_LOAD_WAIT_TIME, true); samples = sample_bytes * 8 / bits_per_sample; getSamplesFromBufEx(realtimeBuf, samples, bits_per_sample, verbose); @@ -751,6 +751,7 @@ int lf_read(bool verbose, uint64_t samples) { } int CmdLFRead(const char *Cmd) { + // In real-time mode, the first few bytes might be the response of CMD_WTX rather than the real samples CLIParserContext *ctx; CLIParserInit(&ctx, "lf read", "Sniff low frequency signal.\n" @@ -816,7 +817,7 @@ int lf_sniff(bool realtime, bool verbose, uint64_t samples) { 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); + sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000 + FPGA_LOAD_WAIT_TIME, true); samples = sample_bytes * 8 / bits_per_sample; getSamplesFromBufEx(realtimeBuf, samples, bits_per_sample, verbose); @@ -842,6 +843,7 @@ int lf_sniff(bool realtime, bool verbose, uint64_t samples) { } int CmdLFSniff(const char *Cmd) { + // In real-time mode, the first few bytes might be the response of CMD_WTX rather than the real samples CLIParserContext *ctx; CLIParserInit(&ctx, "lf sniff", "Sniff low frequency signal. You need to configure the LF part on the Proxmark3 device manually.\n" diff --git a/include/common.h b/include/common.h index 37cf254d9..b3d4598c5 100644 --- a/include/common.h +++ b/include/common.h @@ -196,6 +196,9 @@ extern bool g_tearoff_enabled; #define CLEAR_BIT(data, i) *(data + (i / 8)) &= ~(1 << (7 - (i % 8))) #define FLIP_BIT(data, i) *(data + (i / 8)) ^= (1 << (7 - (i % 8))) +// time for decompressing and loading the image to the FPGA +#define FPGA_LOAD_WAIT_TIME (1500) + // GCC extension // from client/deps/tinycbor/compilersupport_p.h #ifdef __GNUC__ From 835b7a9150c9774102b8c803b50aab7e570c29cb Mon Sep 17 00:00:00 2001 From: wh201906 Date: Tue, 14 Nov 2023 13:12:35 +0800 Subject: [PATCH 08/11] Add support for trigger threshold --- client/src/cmdlf.c | 40 ++++++++++++++++++++++++++++++---------- client/src/comms.c | 21 ++++++++++++++------- 2 files changed, 44 insertions(+), 17 deletions(-) diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index b32f67897..17805b9b1 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -66,8 +66,6 @@ #include "crc.h" #include "pm3_cmd.h" // for LF_CMDREAD_MAX_EXTRA_SYMBOLS -static bool gs_lf_threshold_set = false; - static int CmdHelp(const char *Cmd); // Informative user function. @@ -646,7 +644,6 @@ int CmdLFConfig(const char *Cmd) { config.divisor = LF_DIVISOR_125; config.samples_to_skip = 0; config.trigger_threshold = 0; - gs_lf_threshold_set = false; } if (use_125) @@ -691,7 +688,6 @@ int CmdLFConfig(const char *Cmd) { if (trigg > -1) { config.trigger_threshold = trigg; - gs_lf_threshold_set = (config.trigger_threshold > 0); } config.samples_to_skip = skip; @@ -713,6 +709,7 @@ static int lf_read_internal(bool realtime, bool verbose, uint64_t samples) { } clearCommandBuffer(); const uint8_t bits_per_sample = current_config.bits_per_sample; + const bool is_trigger_threshold_set = (current_config.trigger_threshold > 0); if (realtime) { uint8_t *realtimeBuf = calloc(samples, sizeof(uint8_t)); @@ -721,16 +718,27 @@ static int lf_read_internal(bool realtime, bool verbose, uint64_t samples) { 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 + FPGA_LOAD_WAIT_TIME, true); + if (is_trigger_threshold_set) { + size_t first_receive_len = 32; // larger than the response of CMD_WTX + // wait until a bunch of data arrives + first_receive_len = WaitForRawDataTimeout(realtimeBuf, first_receive_len, -1, false); + sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000 + FPGA_LOAD_WAIT_TIME, true); + sample_bytes += first_receive_len; + } else { + sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000 + FPGA_LOAD_WAIT_TIME, true); + } samples = sample_bytes * 8 / bits_per_sample; - getSamplesFromBufEx(realtimeBuf, samples, bits_per_sample, verbose); + PrintAndLogEx(INFO, "Done: %" PRIu64 " samples (%zu bytes)", samples, sample_bytes); + if (samples != 0) { + getSamplesFromBufEx(realtimeBuf, samples, bits_per_sample, verbose); + } free(realtimeBuf); } else { 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) { + if (is_trigger_threshold_set) { WaitForResponse(CMD_LF_ACQ_RAW_ADC, &resp); } else { if (!WaitForResponseTimeout(CMD_LF_ACQ_RAW_ADC, &resp, 2500)) { @@ -809,6 +817,7 @@ int lf_sniff(bool realtime, bool verbose, uint64_t samples) { } clearCommandBuffer(); const uint8_t bits_per_sample = current_config.bits_per_sample; + const bool is_trigger_threshold_set = (current_config.trigger_threshold > 0); if (realtime) { uint8_t *realtimeBuf = calloc(samples, sizeof(uint8_t)); @@ -817,16 +826,27 @@ int lf_sniff(bool realtime, bool verbose, uint64_t samples) { 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 + FPGA_LOAD_WAIT_TIME, true); + if (is_trigger_threshold_set) { + size_t first_receive_len = 32; // larger than the response of CMD_WTX + // wait until a bunch of data arrives + first_receive_len = WaitForRawDataTimeout(realtimeBuf, first_receive_len, -1, false); + sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000 + FPGA_LOAD_WAIT_TIME, true); + sample_bytes += first_receive_len; + } else { + sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000 + FPGA_LOAD_WAIT_TIME, true); + } samples = sample_bytes * 8 / bits_per_sample; - getSamplesFromBufEx(realtimeBuf, samples, bits_per_sample, verbose); + PrintAndLogEx(INFO, "Done: %" PRIu64 " samples (%zu bytes)", samples, sample_bytes); + if (samples != 0) { + getSamplesFromBufEx(realtimeBuf, samples, bits_per_sample, verbose); + } free(realtimeBuf); } else { 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) { + if (is_trigger_threshold_set) { WaitForResponse(CMD_LF_SNIFF_RAW_ADC, &resp); } else { if (WaitForResponseTimeout(CMD_LF_SNIFF_RAW_ADC, &resp, 2500) == false) { diff --git a/client/src/comms.c b/client/src/comms.c index be2d481dc..1cd01d728 100644 --- a/client/src/comms.c +++ b/client/src/comms.c @@ -402,10 +402,6 @@ __attribute__((force_align_arg_pointer)) uint8_t dummyData[64]; uint32_t dummyLen; uart_receive(sp, dummyData, sizeof(dummyData), &dummyLen); - - // set the buffer as undefined - // comm_raw_data == NULL is used in SetCommunicationReceiveMode() - __atomic_store_n(&comm_raw_data, NULL, __ATOMIC_SEQ_CST); } } else { if (is_receiving_raw_last) { @@ -856,6 +852,12 @@ size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, boo // send anything to stop the transfer PrintAndLogEx(INFO, "Stopping"); SendCommandNG(CMD_BREAK_LOOP, NULL, 0); + + // for ms_timeout == -1, pos < len might always be true + // so user need a spectial way to break this loop + if (ms_timeout == (size_t) - 1) { + break; + } } pos = __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST); @@ -863,7 +865,8 @@ size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, boo // check the timeout if pos is not updated if (last_pos == pos) { uint64_t tmp_clk = __atomic_load_n(&timeout_start_time, __ATOMIC_SEQ_CST); - if ((msclock() - tmp_clk > ms_timeout)) { + // if ms_timeout == -1, the loop can only be breaked by pressing Enter or receiving enough data + if ((ms_timeout != (size_t) - 1) && (msclock() - tmp_clk > ms_timeout)) { break; } } else { @@ -877,13 +880,17 @@ size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, boo last_pos = pos; msleep(10); } - if (pos == len) { + if (pos == len && (ms_timeout != (size_t) - 1)) { + // if ms_timeout != -1, when the desired data is received, tell the arm side + // to stop the current process, and wait for some time to make sure the process + // has been stopped + // if ms_timeout == -1, the user might not want to break the existing process + // on the arm side SendCommandNG(CMD_BREAK_LOOP, NULL, 0); msleep(ms_timeout); } SetCommunicationReceiveMode(false); pos = __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST); - PrintAndLogEx(INFO, "Done: [%zu/%zu]", pos, len); return pos; } From 3ee13c9ba63ae2d4e508427b3cb620f2278a1040 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Wed, 15 Nov 2023 18:04:52 +0800 Subject: [PATCH 09/11] Apply suggestions from @henrygab Check if memory allocation fails Fix memory leak Initialize struct in declaration Add/Fix some notes Remove unlikely() in favor of readability Remove a hard-coded magic number --- armsrc/lfsampling.c | 24 ++++++++++++------------ armsrc/util.c | 5 +++++ client/src/cmddata.c | 36 ++++++++++++++++++++++++++++++++++++ client/src/cmdlf.c | 18 ++++++++++++------ client/src/cmdlfhid.c | 5 +++++ client/src/cmdlfindala.c | 4 ++++ client/src/cmdlfio.c | 4 ++++ client/src/cmdlfparadox.c | 4 ++++ client/src/cmdlfpyramid.c | 4 ++++ client/src/comms.c | 24 ++++++++++++------------ common_arm/usb_cdc.c | 25 +++++++++++-------------- common_arm/usb_cdc.h | 4 ++++ 12 files changed, 113 insertions(+), 44 deletions(-) diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index df1c7454a..e4f9ff2e8 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -306,7 +306,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in // only every 4000th times, in order to save time when collecting samples. // interruptible only when logging not yet triggered - if (unlikely(trigger_hit == false && (checked >= 4000))) { + if (trigger_hit == false && (checked >= 4000)) { if (data_available()) { checked = -1; break; @@ -329,7 +329,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in if (ledcontrol) LED_D_OFF(); // threshold either high or low values 128 = center 0. if trigger = 178 - if (unlikely(trigger_hit == false)) { + if (trigger_hit == false) { if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) { if (cancel_after > 0) { cancel_counter++; @@ -341,7 +341,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in trigger_hit = true; } - if (unlikely(samples_to_skip > 0)) { + if (samples_to_skip > 0) { samples_to_skip--; continue; } @@ -441,7 +441,6 @@ int ReadLF_realtime(bool reader_field) { int32_t samples_to_skip = config.samples_to_skip; const uint8_t decimation = config.decimation; - uint32_t sample_buffer_len = 64; const int8_t size_threshold_table[9] = {0, 64, 64, 60, 64, 60, 60, 56, 64}; const int8_t size_threshold = size_threshold_table[bits_per_sample]; @@ -450,8 +449,9 @@ int ReadLF_realtime(bool reader_field) { uint8_t curr_byte = 0; int return_value = PM3_SUCCESS; + uint32_t sample_buffer_len = AT91C_USB_EP_IN_SIZE; initSampleBuffer(&sample_buffer_len); - if (sample_buffer_len != 64) { + if (sample_buffer_len != AT91C_USB_EP_IN_SIZE) { return PM3_EFAILED; } @@ -469,7 +469,7 @@ int ReadLF_realtime(bool reader_field) { while (BUTTON_PRESS() == false) { // only every 4000th times, in order to save time when collecting samples. // interruptible only when logging not yet triggered - if (unlikely(trigger_hit == false && (checked >= 4000))) { + if (trigger_hit == false && (checked >= 4000)) { if (data_available()) { checked = -1; break; @@ -492,21 +492,21 @@ int ReadLF_realtime(bool reader_field) { LED_D_OFF(); // threshold either high or low values 128 = center 0. if trigger = 178 - if (unlikely(trigger_hit == false)) { + if (trigger_hit == false) { if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) { continue; } trigger_hit = true; } - if (unlikely(samples_to_skip > 0)) { + if (samples_to_skip > 0) { samples_to_skip--; continue; } logSample(sample, decimation, bits_per_sample, false); - // write to USB FIFO if byte changed + // Write to USB FIFO if byte changed curr_byte = data.numbits >> 3; if (curr_byte > last_byte) { async_usb_write_pushByte(data.buffer[last_byte]); @@ -514,20 +514,20 @@ int ReadLF_realtime(bool reader_field) { last_byte = curr_byte; if (samples.total_saved == size_threshold) { - // request usb transmission and change FIFO bank + // Request USB transmission and change FIFO bank if (async_usb_write_requestWrite() == false) { return_value = PM3_EIO; break; } - // reset sample + // Reset sample last_byte = 0; data.numbits = 0; samples.counter = size_threshold; samples.total_saved = 0; } else if (samples.total_saved == 1) { - // check if there is any data from client + // Check if there is any data from client if (data_available_fast()) { break; } diff --git a/armsrc/util.c b/armsrc/util.c index 70a6d01ef..9f42c0b08 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -298,6 +298,8 @@ int BUTTON_HELD(int ms) { return BUTTON_ERROR; } +// This function returns false if no data is available or +// the USB connection is invalid. bool data_available(void) { #ifdef WITH_FPC_USART_HOST return usb_poll_validate_length() || (usart_rxdata_available() > 0); @@ -306,6 +308,9 @@ bool data_available(void) { #endif } +// This function doesn't check if the USB connection is valid. +// In most of the cases, you should use data_available() unless +// the timing is critical. bool data_available_fast(void) { #ifdef WITH_FPC_USART_HOST return usb_available_length() || (usart_rxdata_available() > 0); diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 3339f9681..734b87644 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1012,6 +1012,10 @@ static int CmdUndecimate(const char *Cmd) { //We have memory, don't we? int *swap = calloc(MAX_GRAPH_TRACE_LEN, sizeof(int)); + if (swap == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } uint32_t g_index = 0, s_index = 0; while (g_index < g_GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN) { int count = 0; @@ -1709,6 +1713,10 @@ int CmdHpf(const char *Cmd) { CLIParserFree(ctx); uint8_t *bits = malloc(g_GraphTraceLen); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); removeSignalOffset(bits, size); // push it back to graph @@ -2106,6 +2114,10 @@ static int CmdLoad(const char *Cmd) { if (nofix == false) { uint8_t *bits = malloc(g_GraphTraceLen); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); removeSignalOffset(bits, size); @@ -2244,6 +2256,10 @@ int CmdNorm(const char *Cmd) { } uint8_t *bits = malloc(g_GraphTraceLen); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); // set signal properties low/high/mean/amplitude and is_noise detection computeSignalProperties(bits, size); @@ -2391,6 +2407,10 @@ static int CmdDirectionalThreshold(const char *Cmd) { // set signal properties low/high/mean/amplitude and isnoice detection uint8_t *bits = malloc(g_GraphTraceLen); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); // set signal properties low/high/mean/amplitude and is_noice detection computeSignalProperties(bits, size); @@ -2435,6 +2455,10 @@ static int CmdZerocrossings(const char *Cmd) { } uint8_t *bits = malloc(g_GraphTraceLen); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); // set signal properties low/high/mean/amplitude and is_noise detection computeSignalProperties(bits, size); @@ -2749,6 +2773,10 @@ static int CmdDataIIR(const char *Cmd) { iceSimple_Filter(g_GraphBuffer, g_GraphTraceLen, k); uint8_t *bits = malloc(g_GraphTraceLen); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); // set signal properties low/high/mean/amplitude and is_noise detection computeSignalProperties(bits, size); @@ -3377,6 +3405,10 @@ static int CmdCenterThreshold(const char *Cmd) { // set signal properties low/high/mean/amplitude and isnoice detection uint8_t *bits = malloc(g_GraphTraceLen); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); // set signal properties low/high/mean/amplitude and is_noice detection computeSignalProperties(bits, size); @@ -3423,6 +3455,10 @@ static int CmdEnvelope(const char *Cmd) { envelope_square(g_GraphBuffer, g_GraphBuffer, g_GraphTraceLen); uint8_t *bits = malloc(g_GraphTraceLen); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); // set signal properties low/high/mean/amplitude and is_noice detection computeSignalProperties(bits, size); diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index 17805b9b1..3c4e44af8 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -432,6 +432,10 @@ int CmdFlexdemod(const char *Cmd) { int i, j, start, bit, sum; int *data = malloc(g_GraphTraceLen * sizeof(int)); + if (data == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } memcpy(data, g_GraphBuffer, g_GraphTraceLen); size_t size = g_GraphTraceLen; @@ -697,7 +701,7 @@ int CmdLFConfig(const char *Cmd) { 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; + lf_sample_payload_t payload = {0}; payload.realtime = realtime; payload.verbose = verbose; @@ -720,7 +724,7 @@ static int lf_read_internal(bool realtime, bool verbose, uint64_t samples) { SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload)); if (is_trigger_threshold_set) { size_t first_receive_len = 32; // larger than the response of CMD_WTX - // wait until a bunch of data arrives + // Wait until a bunch of data arrives first_receive_len = WaitForRawDataTimeout(realtimeBuf, first_receive_len, -1, false); sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000 + FPGA_LOAD_WAIT_TIME, true); sample_bytes += first_receive_len; @@ -759,7 +763,8 @@ int lf_read(bool verbose, uint64_t samples) { } int CmdLFRead(const char *Cmd) { - // In real-time mode, the first few bytes might be the response of CMD_WTX rather than the real samples + // In real-time mode, the first few bytes might be the response of CMD_WTX + // rather than the real samples if the LF FPGA image is not ready. CLIParserContext *ctx; CLIParserInit(&ctx, "lf read", "Sniff low frequency signal.\n" @@ -805,7 +810,7 @@ int CmdLFRead(const char *Cmd) { int lf_sniff(bool realtime, bool verbose, uint64_t samples) { if (!g_session.pm3_present) return PM3_ENOTTY; - lf_sample_payload_t payload; + lf_sample_payload_t payload = {0}; payload.realtime = realtime; payload.verbose = verbose; @@ -828,7 +833,7 @@ int lf_sniff(bool realtime, bool verbose, uint64_t samples) { SendCommandNG(CMD_LF_SNIFF_RAW_ADC, (uint8_t *)&payload, sizeof(payload)); if (is_trigger_threshold_set) { size_t first_receive_len = 32; // larger than the response of CMD_WTX - // wait until a bunch of data arrives + // Wait until a bunch of data arrives first_receive_len = WaitForRawDataTimeout(realtimeBuf, first_receive_len, -1, false); sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000 + FPGA_LOAD_WAIT_TIME, true); sample_bytes += first_receive_len; @@ -863,7 +868,8 @@ int lf_sniff(bool realtime, bool verbose, uint64_t samples) { } int CmdLFSniff(const char *Cmd) { - // In real-time mode, the first few bytes might be the response of CMD_WTX rather than the real samples + // In real-time mode, the first few bytes might be the response of CMD_WTX + // rather than the real samples if the LF FPGA image is not ready. CLIParserContext *ctx; CLIParserInit(&ctx, "lf sniff", "Sniff low frequency signal. You need to configure the LF part on the Proxmark3 device manually.\n" diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index 8e3a1e8eb..e8b0d179e 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -118,6 +118,10 @@ int demodHID(bool verbose) { uint32_t hi2 = 0, hi = 0, lo = 0; uint8_t *bits = malloc(g_GraphTraceLen); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); if (size == 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID not enough samples")); @@ -142,6 +146,7 @@ int demodHID(bool verbose) { else PrintAndLogEx(DEBUG, "DEBUG: Error - " _RED_("HID error demoding fsk %d"), idx); + free(bits); return PM3_ESOFT; } diff --git a/client/src/cmdlfindala.c b/client/src/cmdlfindala.c index 3e8b3bcd7..5417bf158 100644 --- a/client/src/cmdlfindala.c +++ b/client/src/cmdlfindala.c @@ -404,6 +404,10 @@ static int CmdIndalaDemodAlt(const char *Cmd) { // worst case with g_GraphTraceLen=40000 is < 4096 // under normal conditions it's < 2048 uint8_t *data = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); + if (data == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t datasize = getFromGraphBuf(data); uint8_t rawbits[4096] = {0}; diff --git a/client/src/cmdlfio.c b/client/src/cmdlfio.c index a5507ce33..5ef0df99a 100644 --- a/client/src/cmdlfio.c +++ b/client/src/cmdlfio.c @@ -67,6 +67,10 @@ int demodIOProx(bool verbose) { (void) verbose; // unused so far int idx = 0, retval = PM3_SUCCESS; uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); if (size < 65) { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples in GraphBuffer"); diff --git a/client/src/cmdlfparadox.c b/client/src/cmdlfparadox.c index f82ef52f2..ad6b42bf8 100644 --- a/client/src/cmdlfparadox.c +++ b/client/src/cmdlfparadox.c @@ -104,6 +104,10 @@ int demodParadox(bool verbose, bool oldChksum) { (void) verbose; // unused so far //raw fsk demod no manchester decoding no start bit finding just get binary from wave uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); if (size == 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox not enough samples"); diff --git a/client/src/cmdlfpyramid.c b/client/src/cmdlfpyramid.c index 4edc2b287..5ed9ef576 100644 --- a/client/src/cmdlfpyramid.c +++ b/client/src/cmdlfpyramid.c @@ -44,6 +44,10 @@ int demodPyramid(bool verbose) { (void) verbose; // unused so far //raw fsk demod no manchester decoding no start bit finding just get binary from wave uint8_t *bits = calloc(MAX_GRAPH_TRACE_LEN, sizeof(uint8_t)); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); if (size == 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid not enough samples"); diff --git a/client/src/comms.c b/client/src/comms.c index 1cd01d728..1cf42f0b1 100644 --- a/client/src/comms.c +++ b/client/src/comms.c @@ -350,7 +350,7 @@ __attribute__((force_align_arg_pointer)) bool commfailed = false; PacketResponseNG rx; PacketResponseNGRaw rx_raw; - // stash the last state of is_receiving_raw, to detect if state changed + // Stash the last state of is_receiving_raw, to detect if state changed bool is_receiving_raw_last = false; #if defined(__MACH__) && defined(__APPLE__) @@ -398,7 +398,7 @@ __attribute__((force_align_arg_pointer)) } } } else { - // ignore data when bufferPos >= bufferLen and is_receiving_raw has not been set to false + // Ignore data when bufferPos >= bufferLen and is_receiving_raw has not been set to false uint8_t dummyData[64]; uint32_t dummyLen; uart_receive(sp, dummyData, sizeof(dummyData), &dummyLen); @@ -407,7 +407,7 @@ __attribute__((force_align_arg_pointer)) if (is_receiving_raw_last) { // is_receiving_raw changed from true to false - // set the buffer as undefined + // Set the buffer as undefined // comm_raw_data == NULL is used in SetCommunicationReceiveMode() __atomic_store_n(&comm_raw_data, NULL, __ATOMIC_SEQ_CST); } @@ -849,11 +849,11 @@ size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, boo while (pos < len) { if (kbd_enter_pressed()) { - // send anything to stop the transfer + // Send anything to stop the transfer PrintAndLogEx(INFO, "Stopping"); SendCommandNG(CMD_BREAK_LOOP, NULL, 0); - // for ms_timeout == -1, pos < len might always be true + // For ms_timeout == -1, pos < len might always be true // so user need a spectial way to break this loop if (ms_timeout == (size_t) - 1) { break; @@ -862,15 +862,15 @@ size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, boo pos = __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST); - // check the timeout if pos is not updated + // Check the timeout if pos is not updated if (last_pos == pos) { uint64_t tmp_clk = __atomic_load_n(&timeout_start_time, __ATOMIC_SEQ_CST); - // if ms_timeout == -1, the loop can only be breaked by pressing Enter or receiving enough data + // If ms_timeout == -1, the loop can only be breaked by pressing Enter or receiving enough data if ((ms_timeout != (size_t) - 1) && (msclock() - tmp_clk > ms_timeout)) { break; } } else { - // print when (print_counter % 64) == 0 + // Print process when (print_counter % 64) == 0 if (show_process && (print_counter & 0x3F) == 0) { PrintAndLogEx(INFO, "[%zu/%zu]", pos, len); } @@ -881,11 +881,11 @@ size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, boo msleep(10); } if (pos == len && (ms_timeout != (size_t) - 1)) { - // if ms_timeout != -1, when the desired data is received, tell the arm side + // If ms_timeout != -1, when the desired data is received, tell the arm side // to stop the current process, and wait for some time to make sure the process - // has been stopped - // if ms_timeout == -1, the user might not want to break the existing process - // on the arm side + // has been stopped. + // If ms_timeout == -1, the user might not want to break the existing process + // on the arm side. SendCommandNG(CMD_BREAK_LOOP, NULL, 0); msleep(ms_timeout); } diff --git a/common_arm/usb_cdc.c b/common_arm/usb_cdc.c index a1fa96f5d..37774aeeb 100644 --- a/common_arm/usb_cdc.c +++ b/common_arm/usb_cdc.c @@ -37,10 +37,7 @@ AT91SAM7S256 USB Device Port #define AT91C_EP_IN 2 // cfg bulk in #define AT91C_EP_NOTIFY 3 // cfg cdc notification interrup -#define AT91C_EP_CONTROL_SIZE 8 -#define AT91C_EP_OUT_SIZE 64 -#define AT91C_EP_IN_SIZE 64 - +// The endpoint size is defined in usb_cdc.h // Section: USB Descriptors #define USB_DESCRIPTOR_DEVICE 0x01 // DescriptorType for a Device Descriptor. @@ -128,7 +125,7 @@ static const char devDescriptor[] = { 2, // Device Class: Communication Device Class 0, // Device Subclass: CDC class sub code ACM [ice 0x02 = win10 virtual comport ] 0, // Device Protocol: CDC Device protocol (unused) - AT91C_EP_CONTROL_SIZE, // MaxPacketSize0 + AT91C_USB_EP_CONTROL_SIZE, // MaxPacketSize0 0xc4, 0x9a, // Vendor ID [0x9ac4 = J. Westhues] 0x8f, 0x4b, // Product ID [0x4b8f = Proxmark-3 RFID Instrument] 0x00, 0x01, // BCD Device release number (1.00) @@ -218,7 +215,7 @@ static const char cfgDescriptor[] = { USB_DESCRIPTOR_ENDPOINT, // Descriptor Type _EP03_IN, // EndpointAddress: Endpoint 03 - IN _INTERRUPT, // Attributes - AT91C_EP_CONTROL_SIZE, 0x00, // MaxPacket Size: EP0 - 8 + AT91C_USB_EP_CONTROL_SIZE, 0x00, // MaxPacket Size: EP0 - 8 0xFF, // Interval polling @@ -239,7 +236,7 @@ static const char cfgDescriptor[] = { USB_DESCRIPTOR_ENDPOINT, // Descriptor Type _EP01_OUT, // Endpoint Address: Endpoint 01 - OUT _BULK, // Attributes: BULK - AT91C_EP_OUT_SIZE, 0x00, // MaxPacket Size: 64 bytes + AT91C_USB_EP_OUT_SIZE, 0x00, // MaxPacket Size: 64 bytes 0, // Interval: ignored for bulk /* Endpoint descriptor */ @@ -247,7 +244,7 @@ static const char cfgDescriptor[] = { USB_DESCRIPTOR_ENDPOINT, // Descriptor Type _EP02_IN, // Endpoint Address: Endpoint 02 - IN _BULK, // Attribute: BULK - AT91C_EP_IN_SIZE, 0x00, // MaxPacket Size: 64 bytes + AT91C_USB_EP_IN_SIZE, 0x00, // MaxPacket Size: 64 bytes 0 // Interval: ignored for bulk }; @@ -775,7 +772,7 @@ int usb_write(const uint8_t *data, const size_t len) { // send first chunk - cpt = MIN(length, AT91C_EP_IN_SIZE); + cpt = MIN(length, AT91C_USB_EP_IN_SIZE); length -= cpt; while (cpt--) { pUdp->UDP_FDR[AT91C_EP_IN] = *data++; @@ -786,7 +783,7 @@ int usb_write(const uint8_t *data, const size_t len) { while (length) { // Send next chunk - cpt = MIN(length, AT91C_EP_IN_SIZE); + cpt = MIN(length, AT91C_USB_EP_IN_SIZE); length -= cpt; while (cpt--) { pUdp->UDP_FDR[AT91C_EP_IN] = *data++; @@ -814,7 +811,7 @@ int usb_write(const uint8_t *data, const size_t len) { while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP) {}; - if (len % AT91C_EP_IN_SIZE == 0) { + if (len % AT91C_USB_EP_IN_SIZE == 0) { // like AT91F_USB_SendZlp(), in non ping-pong mode UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) {}; @@ -857,8 +854,8 @@ int async_usb_write_start(void) { * \brief Push one byte to the FIFO of IN endpoint (time-critical) * * This function simply push a byte to the FIFO of IN endpoint. - * The FIFO size is AT91C_EP_IN_SIZE. Make sure this function is not called - * over AT91C_EP_IN_SIZE times between each async_usb_write_requestWrite(). + * The FIFO size is AT91C_USB_EP_IN_SIZE. Make sure this function is not called + * over AT91C_USB_EP_IN_SIZE times between each async_usb_write_requestWrite(). *---------------------------------------------------------------------------- */ inline void async_usb_write_pushByte(uint8_t data) { @@ -947,7 +944,7 @@ void AT91F_USB_SendData(AT91PS_UDP pudp, const char *pData, uint32_t length) { AT91_REG csr; do { - uint32_t cpt = MIN(length, AT91C_EP_CONTROL_SIZE); + uint32_t cpt = MIN(length, AT91C_USB_EP_CONTROL_SIZE); length -= cpt; while (cpt--) diff --git a/common_arm/usb_cdc.h b/common_arm/usb_cdc.h index aab8e2c5c..9c7cb7299 100644 --- a/common_arm/usb_cdc.h +++ b/common_arm/usb_cdc.h @@ -23,6 +23,10 @@ #include "common.h" #include "at91sam7s512.h" +#define AT91C_USB_EP_CONTROL_SIZE 8 +#define AT91C_USB_EP_OUT_SIZE 64 +#define AT91C_USB_EP_IN_SIZE 64 + void usb_disable(void); void usb_enable(void); bool usb_check(void); From e82fb8b67fe83a6c5ee9dfa8d8de57eb85a98895 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Fri, 17 Nov 2023 12:23:58 +0800 Subject: [PATCH 10/11] Use calloc() instead of malloc() Suggested by @iceman1001 Mainly for 8b6a274e289cd96f16616de741f0d02fb10d1e6e Replaced the malloc() in getSamplesFromBufEx() Added memory allocation result check for getSamplesFromBufEx(), lf_read_internal(), and lf_sniff() --- client/src/cmddata.c | 36 ++++++++++++++++++++---------------- client/src/cmddata.h | 2 +- client/src/cmdlf.c | 10 +++++++++- client/src/cmdlfhid.c | 2 +- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 734b87644..7445f3759 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -1712,7 +1712,7 @@ int CmdHpf(const char *Cmd) { CLIExecWithReturn(ctx, Cmd, argtable, true); CLIParserFree(ctx); - uint8_t *bits = malloc(g_GraphTraceLen); + uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t)); if (bits == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; @@ -1786,12 +1786,10 @@ 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; + return getSamplesFromBufEx(got, n, bits_per_sample, verbose);; } -void getSamplesFromBufEx(uint8_t *data, size_t sample_num, uint8_t bits_per_sample, bool verbose) { +int 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); @@ -1816,7 +1814,11 @@ void getSamplesFromBufEx(uint8_t *data, size_t sample_num, uint8_t bits_per_samp g_GraphTraceLen = max_num; } - uint8_t *bits = malloc(g_GraphTraceLen); + uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t)); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); // set signal properties low/high/mean/amplitude and is_noise detection computeSignalProperties(bits, size); @@ -1825,6 +1827,8 @@ void getSamplesFromBufEx(uint8_t *data, size_t sample_num, uint8_t bits_per_samp setClockGrid(0, 0); g_DemodBufferLen = 0; RepaintGraphWindow(); + + return PM3_SUCCESS; } static int CmdSamples(const char *Cmd) { @@ -2113,11 +2117,11 @@ static int CmdLoad(const char *Cmd) { PrintAndLogEx(SUCCESS, "loaded " _YELLOW_("%zu") " samples", g_GraphTraceLen); if (nofix == false) { - uint8_t *bits = malloc(g_GraphTraceLen); + uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t)); if (bits == NULL) { - PrintAndLogEx(FAILED, "failed to allocate memory"); - return PM3_EMALLOC; - } + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t size = getFromGraphBuf(bits); removeSignalOffset(bits, size); @@ -2255,7 +2259,7 @@ int CmdNorm(const char *Cmd) { } } - uint8_t *bits = malloc(g_GraphTraceLen); + uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t)); if (bits == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; @@ -2406,7 +2410,7 @@ static int CmdDirectionalThreshold(const char *Cmd) { directionalThreshold(g_GraphBuffer, g_GraphBuffer, g_GraphTraceLen, up, down); // set signal properties low/high/mean/amplitude and isnoice detection - uint8_t *bits = malloc(g_GraphTraceLen); + uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t)); if (bits == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; @@ -2454,7 +2458,7 @@ static int CmdZerocrossings(const char *Cmd) { } } - uint8_t *bits = malloc(g_GraphTraceLen); + uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t)); if (bits == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; @@ -2772,7 +2776,7 @@ static int CmdDataIIR(const char *Cmd) { iceSimple_Filter(g_GraphBuffer, g_GraphTraceLen, k); - uint8_t *bits = malloc(g_GraphTraceLen); + uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t)); if (bits == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; @@ -3404,7 +3408,7 @@ static int CmdCenterThreshold(const char *Cmd) { centerThreshold(g_GraphBuffer, g_GraphBuffer, g_GraphTraceLen, up, down); // set signal properties low/high/mean/amplitude and isnoice detection - uint8_t *bits = malloc(g_GraphTraceLen); + uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t)); if (bits == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; @@ -3454,7 +3458,7 @@ static int CmdEnvelope(const char *Cmd) { envelope_square(g_GraphBuffer, g_GraphBuffer, g_GraphTraceLen); - uint8_t *bits = malloc(g_GraphTraceLen); + uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t)); if (bits == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; diff --git a/client/src/cmddata.h b/client/src/cmddata.h index c9f7398be..0767412cb 100644 --- a/client/src/cmddata.h +++ b/client/src/cmddata.h @@ -86,7 +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); +int 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 3c4e44af8..2247236fe 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -431,7 +431,7 @@ int CmdFlexdemod(const char *Cmd) { #endif int i, j, start, bit, sum; - int *data = malloc(g_GraphTraceLen * sizeof(int)); + int *data = calloc(g_GraphTraceLen, sizeof(int)); if (data == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; @@ -717,6 +717,10 @@ static int lf_read_internal(bool realtime, bool verbose, uint64_t samples) { if (realtime) { uint8_t *realtimeBuf = calloc(samples, sizeof(uint8_t)); + if (realtimeBuf == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t sample_bytes = samples * bits_per_sample; sample_bytes = (sample_bytes / 8) + (sample_bytes % 8 != 0); @@ -826,6 +830,10 @@ int lf_sniff(bool realtime, bool verbose, uint64_t samples) { if (realtime) { uint8_t *realtimeBuf = calloc(samples, sizeof(uint8_t)); + if (realtimeBuf == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } size_t sample_bytes = samples * bits_per_sample; sample_bytes = (sample_bytes / 8) + (sample_bytes % 8 != 0); diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index e8b0d179e..0526b16db 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -117,7 +117,7 @@ int demodHID(bool verbose) { //raw fsk demod no manchester decoding no start bit finding just get binary from wave uint32_t hi2 = 0, hi = 0, lo = 0; - uint8_t *bits = malloc(g_GraphTraceLen); + uint8_t *bits = calloc(g_GraphTraceLen, sizeof(uint8_t)); if (bits == NULL) { PrintAndLogEx(FAILED, "failed to allocate memory"); return PM3_EMALLOC; From 45df618b7c58fc17d5507e47daa10388bcf65470 Mon Sep 17 00:00:00 2001 From: wh201906 Date: Thu, 30 Nov 2023 13:39:59 +0800 Subject: [PATCH 11/11] Fix segmentation fault --- client/src/cmddata.c | 40 ++++++++++++++++++++++++++++++++++------ client/src/graph.c | 10 ++++++++-- client/src/graph.h | 1 + 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/client/src/cmddata.c b/client/src/cmddata.c index 7445f3759..47c8ef910 100644 --- a/client/src/cmddata.c +++ b/client/src/cmddata.c @@ -564,7 +564,11 @@ static int Cmdmandecoderaw(const char *Cmd) { return PM3_ESOFT; } - uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; + uint8_t *bits = calloc(MAX_DEMOD_BUF_LEN, sizeof(uint8_t)); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } // make sure its just binary data 0|1|7 in buffer int high = 0, low = 0; @@ -579,6 +583,7 @@ static int Cmdmandecoderaw(const char *Cmd) { if (high > 7 || low < 0) { PrintAndLogEx(ERR, "Error: please first raw demod then manchester raw decode"); + free(bits); return PM3_ESOFT; } @@ -587,6 +592,7 @@ static int Cmdmandecoderaw(const char *Cmd) { uint16_t err_cnt = manrawdecode(bits, &size, invert, &offset); if (err_cnt > max_err) { PrintAndLogEx(ERR, "Too many errors attempting to decode " _RED_("%i"), err_cnt); + free(bits); return PM3_ESOFT; } @@ -611,6 +617,7 @@ static int Cmdmandecoderaw(const char *Cmd) { } setDemodBuff(bits, size, 0); setClockGrid(g_DemodClock * 2, g_DemodStartIdx); + free(bits); return PM3_SUCCESS; } @@ -651,17 +658,27 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) { return PM3_ESOFT; } - uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; - size_t size = sizeof(bits); - if (!getDemodBuff(bits, &size)) return PM3_ESOFT; + uint8_t *bits = calloc(MAX_DEMOD_BUF_LEN, sizeof(uint8_t)); + if (bits == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } + + size_t size = MAX_DEMOD_BUF_LEN; + if (!getDemodBuff(bits, &size)) { + free(bits); + return PM3_ESOFT; + } int err_cnt = BiphaseRawDecode(bits, &size, &offset, invert); if (err_cnt < 0) { PrintAndLogEx(ERR, "Error during decode " _RED_("%i"), err_cnt); + free(bits); return PM3_ESOFT; } if (err_cnt > max_err) { PrintAndLogEx(ERR, "Too many errors attempting to decode " _RED_("%i"), err_cnt); + free(bits); return PM3_ESOFT; } @@ -674,6 +691,7 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) { setDemodBuff(bits, size, 0); setClockGrid(g_DemodClock * 2, g_DemodStartIdx + g_DemodClock * offset); + free(bits); return PM3_SUCCESS; } @@ -681,10 +699,16 @@ static int CmdBiphaseDecodeRaw(const char *Cmd) { int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) { //ask raw demod g_GraphBuffer first - uint8_t bs[MAX_DEMOD_BUF_LEN]; - size_t size = getFromGraphBuf(bs); + uint8_t *bs = calloc(MAX_DEMOD_BUF_LEN, sizeof(uint8_t)); + if (bs == NULL) { + PrintAndLogEx(FAILED, "failed to allocate memory"); + return PM3_EMALLOC; + } + + size_t size = getFromGraphBufEx(bs, MAX_DEMOD_BUF_LEN); if (size == 0) { PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf"); + free(bs); return PM3_ESOFT; } int startIdx = 0; @@ -692,6 +716,7 @@ int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) { int errCnt = askdemod_ext(bs, &size, &clk, &invert, maxErr, 0, 0, &startIdx); if (errCnt < 0 || errCnt > maxErr) { PrintAndLogEx(DEBUG, "DEBUG: no data or error found %d, clock: %d", errCnt, clk); + free(bs); return PM3_ESOFT; } @@ -699,10 +724,12 @@ int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) { errCnt = BiphaseRawDecode(bs, &size, &offset, invert); if (errCnt < 0) { if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode: %d", errCnt); + free(bs); return PM3_ESOFT; } if (errCnt > maxErr) { if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode too many errors: %d", errCnt); + free(bs); return PM3_ESOFT; } @@ -716,6 +743,7 @@ int ASKbiphaseDemod(int offset, int clk, int invert, int maxErr, bool verbose) { PrintAndLogEx(DEBUG, "Biphase Decoded using offset %d | clock %d | #errors %d | start index %d\ndata\n", offset, clk, errCnt, (startIdx + clk * offset / 2)); printDemodBuff(offset, false, false, false); } + free(bs); return PM3_SUCCESS; } diff --git a/client/src/graph.c b/client/src/graph.c index 851e49d5a..8b97dcfad 100644 --- a/client/src/graph.c +++ b/client/src/graph.c @@ -113,12 +113,19 @@ void setGraphBuf(const uint8_t *src, size_t size) { RepaintGraphWindow(); } +// This function assumes that the length of dest array >= g_GraphTraceLen. +// If the length of dest array is less than g_GraphTraceLen, use getFromGraphBufEx(dest, maxLen) instead. size_t getFromGraphBuf(uint8_t *dest) { + return getFromGraphBufEx(dest, g_GraphTraceLen); +} + +size_t getFromGraphBufEx(uint8_t *dest, size_t maxLen) { if (dest == NULL) return 0; if (g_GraphTraceLen == 0) return 0; size_t i; - for (i = 0; i < g_GraphTraceLen; ++i) { + maxLen = (maxLen < g_GraphTraceLen) ? maxLen : g_GraphTraceLen; + for (i = 0; i < maxLen; ++i) { //trim if (g_GraphBuffer[i] > 127) g_GraphBuffer[i] = 127; if (g_GraphBuffer[i] < -127) g_GraphBuffer[i] = -127; @@ -387,4 +394,3 @@ bool fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge) { } return true; } - diff --git a/client/src/graph.h b/client/src/graph.h index 4963fb2b1..3a05dd8eb 100644 --- a/client/src/graph.h +++ b/client/src/graph.h @@ -31,6 +31,7 @@ bool HasGraphData(void); void setGraphBuf(const uint8_t *src, size_t size); void save_restoreGB(uint8_t saveOpt); size_t getFromGraphBuf(uint8_t *dest); +size_t getFromGraphBufEx(uint8_t *dest, size_t maxLen); void convertGraphFromBitstream(void); void convertGraphFromBitstreamEx(int hi, int low); bool isGraphBitstream(void);