mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-10-23 06:32:37 +00:00
PM5 CEP: data_available() doesn't poll CEP, so CMD_BREAK_LOOP over a
Flipper link can't interrupt a running reader loop Problem: triggering the Flipper FAP's built-in ReadHitag2 demo command turns the RF field on and it stays on even after backing out of the app - only an unrelated USB command clears it. data_available() (armsrc/util.c) is the standard idiom LF/HF reader loops use to notice an incoming CMD_BREAK_LOOP, but it only polled USB/BWM/FPC. CEP's own transport PR never wired it in, so a Flipper-sent break is invisible to any loop that was already running. Fix: add cep_spi_rx_pending() to armsrc/pm5_cep.c/.h - a genuinely non-blocking single SPI1 RDBF flag check, not a reuse of the existing (bounded-wait) cep_spi_data_available(), since this gets called every iteration of every reader loop in the codebase and needs to cost nothing when idle. Wire it into data_available()/data_available_fast() alongside the existing BWM/FPC branches, additive since CEP and BWM can coexist. Hardware-confirmed: field now drops promptly every cycle instead of sticking on, across repeated ReadHitag2 attach/attempt/cancel cycles. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dd93406aa0
commit
ba4016d7e2
3 files changed
+41
-6
No files matched your search
@@ -343,6 +343,17 @@ static bool cep_spi_read_byte(uint8_t *out) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Genuinely non-blocking - a single flag read, no spin-wait at all. For
|
||||
// data_available()'s use (armsrc/util.c): a tight sampling loop calls that
|
||||
// every pass purely to notice an incoming CMD_BREAK_LOOP promptly, so it
|
||||
// needs to cost nothing when idle. cep_spi_data_available() isn't a fit
|
||||
// here - it waits (bounded, but non-zero) for a first byte to actually
|
||||
// arrive, which is fine for receive_ng()'s own cadence but would add that
|
||||
// wait to every iteration of every LF/HF reader loop in the codebase.
|
||||
bool cep_spi_rx_pending(void) {
|
||||
return spi_i2s_flag_get(SPI1, SPI_I2S_RDBF_FLAG) != RESET;
|
||||
}
|
||||
|
||||
bool cep_spi_data_available(void) {
|
||||
uint8_t len_header[2] = {0x00};
|
||||
size_t discarded = 0;
|
||||
|
||||
@@ -58,6 +58,13 @@ void cep_attach_poll(void);
|
||||
// simple non-blocking peek.
|
||||
bool cep_spi_data_available(void);
|
||||
|
||||
// True if SPI1's receive-data register currently holds an unread byte - a
|
||||
// single flag check, zero wait. Gate for data_available() (armsrc/util.c),
|
||||
// which many LF/HF reader loops call every pass to notice an incoming
|
||||
// CMD_BREAK_LOOP - that call site needs to cost nothing when idle, unlike
|
||||
// cep_spi_data_available() above which waits (bounded) for a first byte.
|
||||
bool cep_spi_rx_pending(void);
|
||||
|
||||
// Read up to `len` raw NG bytes off SPI1. Returns the number of bytes
|
||||
// actually read before an internal per-byte timeout gave up early.
|
||||
uint32_t cep_spi_read_ng(uint8_t *data, size_t len);
|
||||
|
||||
+23
-6
@@ -28,6 +28,9 @@
|
||||
#ifdef WITH_BWM_FORWARD
|
||||
#include "bwm_forward.h"
|
||||
#endif
|
||||
#ifdef WITH_CEP
|
||||
#include "pm5_cep.h"
|
||||
#endif
|
||||
#include "BigBuf.h" // trace_restart_timeline
|
||||
#ifdef WITH_SMARTCARD
|
||||
#include "i2c.h" // sc_log_trace_reset
|
||||
@@ -330,28 +333,42 @@ int BUTTON_HELD(int ms) {
|
||||
// This function returns false if no data is available or
|
||||
// the USB connection is invalid.
|
||||
bool data_available(void) {
|
||||
bool avail;
|
||||
#if defined(WITH_BWM_FORWARD)
|
||||
// The BWM (BLE / WiFi) link is the host connection on a Proxmark5, so it
|
||||
// has to be polled here too or CMD_BREAK_LOOP is never seen over it.
|
||||
return usb_poll_validate_length() || (bwm_fwd_rxdata_available() > 0);
|
||||
avail = usb_poll_validate_length() || (bwm_fwd_rxdata_available() > 0);
|
||||
#elif defined(WITH_FPC_USART_HOST)
|
||||
return usb_poll_validate_length() || (usart_rxdata_available() > 0);
|
||||
avail = usb_poll_validate_length() || (usart_rxdata_available() > 0);
|
||||
#else
|
||||
return usb_poll_validate_length();
|
||||
avail = usb_poll_validate_length();
|
||||
#endif
|
||||
#if defined(WITH_CEP)
|
||||
// CEP is independent of BWM/FPC (both may be live at once) - a Flipper
|
||||
// sending CMD_BREAK_LOOP into a running reader loop is otherwise
|
||||
// invisible here, leaving the loop (and its RF field) running until an
|
||||
// unrelated USB command happens to arrive.
|
||||
avail = avail || cep_spi_rx_pending();
|
||||
#endif
|
||||
return avail;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
bool avail;
|
||||
#if defined(WITH_BWM_FORWARD)
|
||||
return usb_available_length() || (bwm_fwd_rxdata_available() > 0);
|
||||
avail = usb_available_length() || (bwm_fwd_rxdata_available() > 0);
|
||||
#elif defined(WITH_FPC_USART_HOST)
|
||||
return usb_available_length() || (usart_rxdata_available() > 0);
|
||||
avail = usb_available_length() || (usart_rxdata_available() > 0);
|
||||
#else
|
||||
return usb_available_length();
|
||||
avail = usb_available_length();
|
||||
#endif
|
||||
#if defined(WITH_CEP)
|
||||
avail = avail || cep_spi_rx_pending();
|
||||
#endif
|
||||
return avail;
|
||||
}
|
||||
|
||||
// Combined function to convert an unsigned int to an array of hex values corresponding to the last three bits of k1
|
||||
|
||||
Reference in new issue
Block a user