mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-08-28 03:04:18 +00:00
Fix formatting and comments in bwm_forward.c
Signed-off-by: Niel Nielsen <nieldk@gmail.com>
This commit is contained in:
committed by
Philippe Teuwen
parent
426c9f11fd
commit
5fa3ac2446
+48
-13
@@ -14,13 +14,15 @@
|
||||
#include "bwm_forward.h"
|
||||
|
||||
#include "bwm_uart_at32.h"
|
||||
#include "pm3_cmd.h"
|
||||
#include "pm3_cmd.h" // PM3_CMD_DATA_SIZE, PM3_* return codes
|
||||
#include "string.h"
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
// CRC-16/CCITT-FALSE, byte-identical to the BWM firmware's crc16_ccitt()
|
||||
// (poly 0x1021, init 0xFFFF, MSB-first, no reflection, no xorout).
|
||||
static uint16_t bwm_crc16(const uint8_t *data, size_t len, uint16_t crc) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
crc ^= (uint16_t)data[i] << 8;
|
||||
@@ -35,28 +37,43 @@ static uint16_t bwm_crc16(const uint8_t *data, size_t len, uint16_t crc) {
|
||||
return crc;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// TX: wrap one reply frame into a SEND_FORWARD_DATA app_com frame.
|
||||
// A full NG/OLD frame is <= PM3_CMD_DATA_SIZE + a small header/postamble, well
|
||||
// under the BWM 4096-byte payload cap, so a single frame always suffices.
|
||||
// ---------------------------------------------------------------------------
|
||||
#define BWM_TX_OVERHEAD (2 + 2 + 2 + 2) // hdr + cmd + len + crc
|
||||
#define BWM_TX_MAX_PAYLOAD (PM3_CMD_DATA_SIZE + 64) // NG/OLD frame ceiling
|
||||
#define BWM_TX_BUFSZ (BWM_TX_OVERHEAD + BWM_TX_MAX_PAYLOAD)
|
||||
|
||||
static void bwm_pump(void);
|
||||
static void bwm_pump(void); // fwd decl: TX gate pumps RX to collect forward-frame acks
|
||||
|
||||
// --- Flow control (ack window) ---------------------------------------------
|
||||
// s_fwd_inflight: forward frames sent but not yet acked by the ESP. Bumped on
|
||||
// send, decremented when a SLAVE_RESP echoing cmd=SEND_FORWARD_DATA arrives.
|
||||
// We may send while it is below BWM_FC_WINDOW; at the cap we wait for an ack.
|
||||
static volatile int16_t s_fwd_inflight = 0;
|
||||
|
||||
int bwm_fwd_writebuffer_sync(const uint8_t *data, size_t len) {
|
||||
static uint8_t frame[BWM_TX_BUFSZ];
|
||||
static uint8_t frame[BWM_TX_BUFSZ]; // single-threaded bare-metal: static OK
|
||||
|
||||
if (len > BWM_TX_MAX_PAYLOAD) {
|
||||
len = BWM_TX_MAX_PAYLOAD;
|
||||
len = BWM_TX_MAX_PAYLOAD; // defensive; should never trigger
|
||||
}
|
||||
|
||||
size_t idx = 0;
|
||||
// Flow control: block while the in-flight window is full, waiting for the
|
||||
// ESP to ack an earlier forward frame. bwm_pump() drains the IRQ-filled RX
|
||||
// ring, so acks are collected even while we sit inside a tight download loop
|
||||
// (the reply_old firehose). The spin cap is a safety valve so a dead or
|
||||
// disconnected ESP can't hard-hang us. A window >= 1 means single command
|
||||
// replies never block - only sustained bursts hit the cap.
|
||||
{
|
||||
uint32_t spins = 0;
|
||||
while (s_fwd_inflight >= BWM_FC_WINDOW) {
|
||||
bwm_pump();
|
||||
if (++spins > BWM_FC_ACK_TIMEOUT_SPINS) {
|
||||
s_fwd_inflight = 0;
|
||||
s_fwd_inflight = 0; // best-effort: assume the pipe cleared
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -77,10 +94,16 @@ int bwm_fwd_writebuffer_sync(const uint8_t *data, size_t len) {
|
||||
frame[idx++] = (uint8_t)((crc >> 8) & 0xFF);
|
||||
|
||||
int wr = bwm_uart_write(frame, idx);
|
||||
s_fwd_inflight++;
|
||||
s_fwd_inflight++; // one more forward frame awaiting its ack
|
||||
return wr;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// RX: persistent app_com de-framer. Feeds raw FPC bytes through a state machine
|
||||
// and pushes the payloads of valid DATA_FORWARD (0xD2 0xD3 / cmd 8089) frames
|
||||
// into a byte FIFO that bwm_read_ng() drains. Non-DATA_FORWARD frames (slave
|
||||
// responses, forwarded logs, cmd-error reports) are validated and discarded.
|
||||
// ---------------------------------------------------------------------------
|
||||
#define BWM_DEFIFO_SZ 2048 // >= one full NG frame's payload
|
||||
#define BWM_RXFRAME_MAX (PM3_CMD_DATA_SIZE + 64)
|
||||
|
||||
@@ -91,27 +114,28 @@ typedef enum {
|
||||
typedef struct {
|
||||
bwm_state_t state;
|
||||
uint8_t hdr1;
|
||||
bool is_bcast;
|
||||
bool is_bcast; // header pair is 0xD2 0xD3
|
||||
uint16_t cmd;
|
||||
uint16_t len;
|
||||
uint16_t got;
|
||||
uint16_t crc_calc;
|
||||
uint16_t got; // payload bytes received
|
||||
uint16_t crc_calc; // running CRC over hdr..payload
|
||||
uint16_t crc_recv;
|
||||
uint8_t payload[BWM_RXFRAME_MAX];
|
||||
} bwm_parser_t;
|
||||
|
||||
static bwm_parser_t s_p = { .state = S_IDLE };
|
||||
|
||||
// De-framed payload ring
|
||||
static uint8_t s_fifo[BWM_DEFIFO_SZ];
|
||||
static volatile uint16_t s_fifo_head = 0;
|
||||
static volatile uint16_t s_fifo_tail = 0;
|
||||
static volatile uint16_t s_fifo_head = 0; // write
|
||||
static volatile uint16_t s_fifo_tail = 0; // read
|
||||
|
||||
static uint16_t fifo_count(void) {
|
||||
return (uint16_t)((s_fifo_head - s_fifo_tail) & (BWM_DEFIFO_SZ - 1));
|
||||
}
|
||||
static void fifo_push(uint8_t b) {
|
||||
uint16_t next = (uint16_t)((s_fifo_head + 1) & (BWM_DEFIFO_SZ - 1));
|
||||
if (next != s_fifo_tail) {
|
||||
if (next != s_fifo_tail) { // drop on overflow rather than corrupt
|
||||
s_fifo[s_fifo_head] = b;
|
||||
s_fifo_head = next;
|
||||
}
|
||||
@@ -126,6 +150,8 @@ static void bwm_reset_frame(bwm_parser_t *p) {
|
||||
p->state = S_IDLE;
|
||||
}
|
||||
|
||||
// Update running CRC one byte at a time (mirrors the streaming update in the
|
||||
// BWM firmware parser).
|
||||
static void crc_step(bwm_parser_t *p, uint8_t byte) {
|
||||
p->crc_calc = bwm_crc16(&byte, 1, p->crc_calc);
|
||||
}
|
||||
@@ -138,12 +164,14 @@ static void bwm_feed_byte(bwm_parser_t *p, uint8_t byte) {
|
||||
} else if (byte == BWM_HDR_SLAVE_RESP_1) {
|
||||
p->hdr1 = byte; p->is_bcast = false; p->state = S_HDR2;
|
||||
}
|
||||
// any other byte: stay idle (resync)
|
||||
break;
|
||||
|
||||
case S_HDR2: {
|
||||
bool ok = (p->is_bcast && byte == BWM_HDR_SLAVE_BCAST_2) ||
|
||||
(!p->is_bcast && byte == BWM_HDR_SLAVE_RESP_2);
|
||||
if (!ok) {
|
||||
// header mismatch: reset and re-examine this byte as a potential SOF
|
||||
p->state = S_IDLE;
|
||||
bwm_feed_byte(p, byte);
|
||||
return;
|
||||
@@ -161,7 +189,7 @@ static void bwm_feed_byte(bwm_parser_t *p, uint8_t byte) {
|
||||
p->len |= (uint16_t)byte << 8;
|
||||
crc_step(p, byte);
|
||||
p->got = 0;
|
||||
if (p->len > BWM_RXFRAME_MAX) {
|
||||
if (p->len > BWM_RXFRAME_MAX) { // oversized -> drop frame
|
||||
bwm_reset_frame(p);
|
||||
} else {
|
||||
p->state = (p->len == 0) ? S_CRC_LO : S_PAYLOAD;
|
||||
@@ -185,11 +213,13 @@ static void bwm_feed_byte(bwm_parser_t *p, uint8_t byte) {
|
||||
fifo_push(p->payload[i]);
|
||||
}
|
||||
} else if ((p->is_bcast == false) && p->cmd == BWM_CMD_SEND_FORWARD_DATA) {
|
||||
// SLAVE_RESP ack for a forward frame -> one slot freed
|
||||
if (s_fwd_inflight > 0) {
|
||||
s_fwd_inflight--;
|
||||
}
|
||||
}
|
||||
}
|
||||
// valid non-DATA_FORWARD frames and CRC failures alike: just resync
|
||||
bwm_reset_frame(p);
|
||||
break;
|
||||
|
||||
@@ -199,6 +229,7 @@ static void bwm_feed_byte(bwm_parser_t *p, uint8_t byte) {
|
||||
}
|
||||
}
|
||||
|
||||
// Pull whatever raw framed bytes are waiting and run them through the parser.
|
||||
static void bwm_pump(void) {
|
||||
uint8_t scratch[64];
|
||||
uint16_t avail = bwm_uart_rx_available();
|
||||
@@ -218,6 +249,8 @@ uint16_t bwm_fwd_rxdata_available(void) {
|
||||
if (fifo_count() > 0) {
|
||||
return fifo_count();
|
||||
}
|
||||
// No de-framed payload yet, but raw frame bytes may be waiting; pump once so
|
||||
// receive_ng()'s gate reflects real forward data.
|
||||
bwm_pump();
|
||||
return fifo_count();
|
||||
}
|
||||
@@ -227,6 +260,8 @@ uint32_t bwm_read_ng(uint8_t *data, size_t len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Same bounded-retry budget shape as bwm_uart_read(); USART_SLOW_LINK (set
|
||||
// for the BWM/BLE link) widens it so a slow round-trip doesn't time out.
|
||||
uint32_t tryconstant = 0;
|
||||
#ifdef USART_SLOW_LINK
|
||||
tryconstant = 50000;
|
||||
|
||||
Reference in New Issue
Block a user