Remove application-layer CRC from SRAM mailbox protocol
ISO15693 already provides CRC-16 at the transport layer, making the application-layer CRC redundant. Simplifies header from 6 to 4 bytes, removes crc16_continue/verify_crc, and drops STATUS_BAD_CRC. Also updates design doc and fixes markdown table formatting. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -29,16 +29,15 @@ pub const RESPONSE_MARKER: u8 = 0xFF;
|
||||
|
||||
// Status codes
|
||||
pub const STATUS_OK: u8 = 0x00;
|
||||
pub const STATUS_BAD_CRC: u8 = 0x01;
|
||||
pub const STATUS_BAD_CMD: u8 = 0x02;
|
||||
pub const STATUS_EEPROM_FAIL: u8 = 0x03;
|
||||
pub const STATUS_INVALID_INDEX: u8 = 0x04;
|
||||
|
||||
/// Command header size (cmd + seq + payload_len_u16 + crc_u16).
|
||||
pub const CMD_HEADER_SIZE: usize = 6;
|
||||
/// Command header size (cmd + seq + payload_len_u16).
|
||||
pub const CMD_HEADER_SIZE: usize = 4;
|
||||
|
||||
/// Response header size (marker + seq + status + payload_len + crc_u16).
|
||||
pub const RSP_HEADER_SIZE: usize = 6;
|
||||
/// Response header size (marker + seq + status + payload_len).
|
||||
pub const RSP_HEADER_SIZE: usize = 4;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Mailbox state
|
||||
@@ -73,34 +72,11 @@ impl MailboxState {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// CRC helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Compute CRC-16/CCITT-FALSE over the given data, starting from an
|
||||
/// initial CRC value. This allows continuing a CRC computation across
|
||||
/// multiple buffers.
|
||||
fn crc16_continue(init: u16, data: &[u8]) -> u16 {
|
||||
let mut crc = init;
|
||||
for &b in data {
|
||||
crc ^= (b as u16) << 8;
|
||||
for _ in 0..8 {
|
||||
if crc & 0x8000 != 0 {
|
||||
crc = (crc << 1) ^ 0x1021;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
crc &= 0xFFFF;
|
||||
}
|
||||
}
|
||||
crc
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Protocol parse / build
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Parse the 6-byte command header. Returns (cmd, seq, payload_len) or None
|
||||
/// Parse the 4-byte command header. Returns (cmd, seq, payload_len) or None
|
||||
/// if the buffer is too short or the command ID is out of range.
|
||||
fn parse_header(buf: &[u8]) -> Option<(u8, u8, u16)> {
|
||||
if buf.len() < CMD_HEADER_SIZE {
|
||||
@@ -115,20 +91,6 @@ fn parse_header(buf: &[u8]) -> Option<(u8, u8, u16)> {
|
||||
Some((cmd, seq, payload_len))
|
||||
}
|
||||
|
||||
/// Verify CRC over the command packet.
|
||||
/// CRC is computed over bytes 0-3 (header minus CRC) + payload, then
|
||||
/// compared to the big-endian CRC in bytes 4-5.
|
||||
fn verify_crc(buf: &[u8], payload_len: u16) -> bool {
|
||||
let total = CMD_HEADER_SIZE + payload_len as usize;
|
||||
if buf.len() < total {
|
||||
return false;
|
||||
}
|
||||
let expected = ((buf[4] as u16) << 8) | buf[5] as u16;
|
||||
let crc = crc16_continue(0xFFFF, &buf[0..4]);
|
||||
let crc = crc16_continue(crc, &buf[CMD_HEADER_SIZE..total]);
|
||||
crc == expected
|
||||
}
|
||||
|
||||
/// Build a response packet into `buf`. Returns the total number of bytes
|
||||
/// written (padded to a multiple of 4 for SRAM block alignment).
|
||||
fn build_response(buf: &mut [u8], seq: u8, status: u8, payload: &[u8]) -> usize {
|
||||
@@ -137,18 +99,10 @@ fn build_response(buf: &mut [u8], seq: u8, status: u8, payload: &[u8]) -> usize
|
||||
buf[1] = seq;
|
||||
buf[2] = status;
|
||||
buf[3] = plen as u8;
|
||||
// CRC placeholder at [4..6], computed below
|
||||
// Copy payload
|
||||
buf[RSP_HEADER_SIZE..RSP_HEADER_SIZE + plen].copy_from_slice(payload);
|
||||
// Compute CRC over bytes 0-3 + payload
|
||||
let crc = crc16_continue(0xFFFF, &buf[0..4]);
|
||||
let crc = crc16_continue(crc, payload);
|
||||
buf[4] = (crc >> 8) as u8;
|
||||
buf[5] = crc as u8;
|
||||
// Pad total length to multiple of 4
|
||||
let raw_len = RSP_HEADER_SIZE + plen;
|
||||
let padded = (raw_len + 3) & !3;
|
||||
// Zero padding bytes
|
||||
for b in buf[raw_len..padded].iter_mut() {
|
||||
*b = 0;
|
||||
}
|
||||
@@ -522,15 +476,6 @@ where
|
||||
return Ok(false);
|
||||
}
|
||||
|
||||
// Verify CRC
|
||||
if !verify_crc(&sram, payload_len) {
|
||||
// Write BAD_CRC response
|
||||
let mut rsp = [0u8; SRAM_SIZE];
|
||||
let len = build_response(&mut rsp, seq, STATUS_BAD_CRC, &[]);
|
||||
ntag.write_sram_blocks(0, &rsp[..len])?;
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
let payload = &sram[CMD_HEADER_SIZE..total];
|
||||
|
||||
// Dispatch
|
||||
|
||||
Reference in New Issue
Block a user