diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 8f9c74a05..7d4fe8b8b 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1737,7 +1737,7 @@ static void PacketReceived(PacketCommandNG *packet) { case CMD_LF_ACQ_RAW_ADC: { lf_sample_payload_t *payload = (lf_sample_payload_t *)packet->data.asBytes; if (payload->realtime) { - ReadLF_realtime(true, payload->cotag); + ReadLF_realtime(true, payload->cotag, payload->samples); } else { uint32_t bits = SampleLF(payload->verbose, payload->samples, true, payload->cotag); reply_ng(CMD_LF_ACQ_RAW_ADC, PM3_SUCCESS, (uint8_t *)&bits, sizeof(bits)); @@ -1766,7 +1766,7 @@ static void PacketReceived(PacketCommandNG *packet) { case CMD_LF_SNIFF_RAW_ADC: { lf_sample_payload_t *payload = (lf_sample_payload_t *)packet->data.asBytes; if (payload->realtime) { - ReadLF_realtime(false, false); + ReadLF_realtime(false, false, payload->samples); } else { 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/armsrc/lfsampling.c b/armsrc/lfsampling.c index 25245adec..ed6f32658 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -455,7 +455,7 @@ uint32_t SampleLF(bool verbose, uint32_t sample_size, bool ledcontrol, bool cota * @param reader_field - true for reading tags, false for sniffing * @return sampling result **/ -int ReadLF_realtime(bool reader_field, bool cotag) { +int ReadLF_realtime(bool reader_field, bool cotag, uint32_t sample_limit) { // parameters from config and constants const uint8_t bits_per_sample = config.bits_per_sample; const int16_t trigger_threshold = config.trigger_threshold; @@ -469,6 +469,8 @@ int ReadLF_realtime(bool reader_field, bool cotag) { uint8_t last_byte = 0; uint8_t curr_byte = 0; int return_value = PM3_SUCCESS; + // Total samples streamed so far + uint32_t total_logged = 0; uint32_t usb_buffer_len = 0, sample_buffer_len; usb_get_ep_size(NULL, &usb_buffer_len, NULL); @@ -536,6 +538,7 @@ int ReadLF_realtime(bool reader_field, bool cotag) { curr_byte = data.numbits >> 3; if (curr_byte > last_byte) { async_usb_write_pushByte(data.buffer[last_byte]); + total_logged++; } last_byte = curr_byte; @@ -558,6 +561,10 @@ int ReadLF_realtime(bool reader_field, bool cotag) { break; } } + + if (sample_limit > 0 && total_logged >= sample_limit) { + break; + } } } diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 010bc076f..3ed11ca3e 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -57,9 +57,10 @@ uint32_t SampleLF(bool verbose, uint32_t sample_size, bool ledcontrol, bool cota * Uses parameters in config. Only bits_per_sample = 8 is working now * * @param reader_field - true for reading tags, false for sniffing + * @param sample_limit - stop once this many samples have been streamed, 0 = unlimited * @return sampling result **/ -int ReadLF_realtime(bool reader_field, bool cotag); +int ReadLF_realtime(bool reader_field, bool cotag, uint32_t sample_limit); /** * Initializes the FPGA for sniff-mode (field off), and acquires the samples. diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index 988ccd473..340baffda 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -787,6 +787,7 @@ static int lf_read_internal(bool realtime, bool verbose, uint64_t samples, bool payload.realtime = realtime; payload.verbose = verbose; payload.cotag = cotag; + payload.samples = (samples > MAX_LF_SAMPLES) ? MAX_LF_SAMPLES : samples; sample_config current_config; int retval = lf_getconfig(¤t_config); @@ -820,12 +821,14 @@ static int lf_read_internal(bool realtime, bool verbose, uint64_t samples, bool SendCommandNG(CMD_LF_ACQ_RAW_ADC, (uint8_t *)&payload, sizeof(payload)); if (is_trigger_threshold_set) { size_t first_receive_len = 32; - // 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, true); + // Wait until a bunch of data arrives. Keep raw mode on across both + // calls so the comm thread doesn't briefly fall back to parsing + // framed packets out of the still-arriving sample stream. + first_receive_len = WaitForRawDataTimeout(realtimeBuf, first_receive_len, -1, false, true); + sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000, true, false); sample_bytes += first_receive_len; } else { - sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000, true); + sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000, true, false); } samples = sample_bytes * 8 / bits_per_sample; PrintAndLogEx(INFO, "Done: %" PRIu64 " samples (%zu bytes)", samples, sample_bytes); @@ -835,7 +838,6 @@ static int lf_read_internal(bool realtime, bool verbose, uint64_t samples, bool 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; @@ -920,6 +922,7 @@ int lf_sniff(bool realtime, bool verbose, uint64_t samples) { lf_sample_payload_t payload = {0}; payload.realtime = realtime; payload.verbose = verbose; + payload.samples = (samples > MAX_LF_SAMPLES) ? MAX_LF_SAMPLES : samples; sample_config current_config; int retval = lf_getconfig(¤t_config); @@ -953,12 +956,14 @@ 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; - // 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, true); + // Wait until a bunch of data arrives. Keep raw mode on across both + // calls so the comm thread doesn't briefly fall back to parsing + // framed packets out of the still-arriving sample stream. + first_receive_len = WaitForRawDataTimeout(realtimeBuf, first_receive_len, -1, false, true); + sample_bytes = WaitForRawDataTimeout(realtimeBuf + first_receive_len, sample_bytes - first_receive_len, 1000, true, false); sample_bytes += first_receive_len; } else { - sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000, true); + sample_bytes = WaitForRawDataTimeout(realtimeBuf, sample_bytes, 1000, true, false); } samples = sample_bytes * 8 / bits_per_sample; PrintAndLogEx(INFO, "Done: %" PRIu64 " samples (%zu bytes)", samples, sample_bytes); @@ -968,7 +973,6 @@ int lf_sniff(bool realtime, bool verbose, uint64_t samples) { 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 (is_trigger_threshold_set) { diff --git a/client/src/comms.c b/client/src/comms.c index de8045930..a45bf3962 100644 --- a/client/src/comms.c +++ b/client/src/comms.c @@ -1010,7 +1010,7 @@ static size_t communication_delay(void) { * @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) { +size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, bool show_process, bool keep_raw_mode) { uint8_t print_counter = 0; size_t last_pos = 0; @@ -1058,7 +1058,7 @@ size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, boo last_pos = pos; msleep(10); } - if (pos == len && (ms_timeout != (size_t) - 1)) { + if (pos == len && (ms_timeout != (size_t) - 1) && (keep_raw_mode == false)) { // 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. @@ -1067,7 +1067,14 @@ size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, boo SendCommandNG(CMD_BREAK_LOOP, NULL, 0); msleep(ms_timeout); } - SetCommunicationReceiveMode(false); + // Caller is about to chain another raw read: keep raw-receive mode + // on so the comm thread never drops back into normal framed-packet + // parsing in between the two reads. Doing so - even briefly - lets it + // misparse in-flight sample bytes as a PacketResponseNG preamble and + // corrupts every USB exchange that follows. + if (keep_raw_mode == false) { + SetCommunicationReceiveMode(false); + } pos = __atomic_load_n(&comm_raw_pos, __ATOMIC_SEQ_CST); return pos; } diff --git a/client/src/comms.h b/client/src/comms.h index b127010cf..029e36cfa 100644 --- a/client/src/comms.h +++ b/client/src/comms.h @@ -110,7 +110,7 @@ int TestProxmark(pm3_device_t *dev); void CloseProxmark(pm3_device_t *dev); void StartReconnectProxmark(void); -size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, bool show_process); +size_t WaitForRawDataTimeout(uint8_t *buffer, size_t len, size_t ms_timeout, bool show_process, bool keep_raw_mode); 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);