diff --git a/src/drivers/nfc_pn532.rs b/src/drivers/nfc_pn532.rs index 1cb6554..9297bd1 100644 --- a/src/drivers/nfc_pn532.rs +++ b/src/drivers/nfc_pn532.rs @@ -1,4 +1,5 @@ use alloc::vec::Vec; +use core::error::Error; use embedded_hal::i2c::I2c; use log::{error, info}; use pn532::i2c::I2CInterface; @@ -8,6 +9,7 @@ use pn532::{Pn532, Request}; pub type Pn532Device = Pn532, (), 34>; pub const PAGES_PER_READ: usize = 4; +pub const BYTES_PER_READ: usize = PAGES_PER_READ * 4; /// PN532 NFC reader driver. pub struct NfcPn532Driver @@ -17,6 +19,35 @@ where pn532: Pn532Device, } +#[derive(Debug, Clone)] +struct PageParseError { + iteration: u8, + bytes: [u8; N], + status_code: Option, +} + +impl Error for PageParseError {} + +impl core::fmt::Display for PageParseError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + let PageParseError { + iteration, + bytes, + status_code, + } = self; + match status_code { + Some(code) => write!( + f, + "NFC pages parse error in iteration {iteration} with error code 0x{code:02x}: {bytes:02x?}" + ), + None => write!( + f, + "No data available for NFC page in iteration {iteration}: {bytes:02x?}" + ), + } + } +} + impl NfcPn532Driver where I2C: I2c, @@ -57,16 +88,21 @@ where } } - pub fn parse_nfc_page(iteration: u8, bytes: &[u8]) -> Result<[u8; PAGES_PER_READ * 4], ()> { - let success = bytes.first().is_some_and(|x| *x == 0); - if success { - let slice_len = bytes.len().min(PAGES_PER_READ * 4 + 1); - let mut arr = [0; PAGES_PER_READ * 4]; - arr[..slice_len - 1].copy_from_slice(&bytes[1..slice_len]); - Ok(arr) - } else { - info!("err {iteration}: {:02x?}", bytes); - Err(()) + fn parse_nfc_page( + iteration: u8, + bytes: &[u8], + ) -> Result<[u8; BYTES_PER_READ], PageParseError> { + let slice_len = bytes.len().min(BYTES_PER_READ + 1); + let mut arr = [0; BYTES_PER_READ]; + arr[..slice_len - 1].copy_from_slice(&bytes[1..slice_len]); + + match bytes.first() { + Some(0x00) => Ok(arr), + error => Err(PageParseError { + iteration, + bytes: arr, + status_code: error.copied(), + }), } } @@ -79,18 +115,25 @@ where let mut data: Vec = Vec::with_capacity(858); for i in (0x0B..=230).step_by(PAGES_PER_READ) { - let mut parse_result = Err(()); - while parse_result.is_err() { - let Ok(result) = self + let bytes = loop { + let read = self .pn532 - .process_async(&Request::ntag_read(i), PAGES_PER_READ * 4 + 1) - .await - else { - continue; + .process_async(&Request::ntag_read(i), BYTES_PER_READ + 1) + .await; + + let bytes = match read { + Ok(bytes) => bytes, + Err(e) => { + error!("Reading page {i} failed: {e:?}"); + continue; + } }; - parse_result = Self::parse_nfc_page(i, result); - } - let bytes = parse_result.unwrap(); + + match Self::parse_nfc_page(i, bytes) { + Ok(data) => break data, + Err(e) => error!("Parsing page failed: {e}"), + } + }; let bytes = if i == 0x0B { &bytes[1..] } else { &bytes }; data.extend(bytes); }