use alloc::vec::Vec; use embedded_hal::i2c::I2c; use log::{error, info}; use pn532::i2c::I2CInterface; use pn532::requests::SAMMode; use pn532::{Pn532, Request}; pub type Pn532Device = Pn532, (), 34>; pub const PAGES_PER_READ: usize = 4; /// PN532 NFC reader driver. pub struct NfcPn532Driver where I2C: I2c, { pn532: Pn532Device, } impl NfcPn532Driver where I2C: I2c, { pub fn new(i2c: I2C) -> Self { let pn532 = Pn532::new_async(I2CInterface { i2c }); Self { pn532 } } pub async fn configure_sam(&mut self) -> Result<(), ()> { if let Err(e) = self .pn532 .process_async(&Request::sam_configuration(SAMMode::Normal, false), 0) .await { error!("PN532 SAM configuration failed over I2C: {e:?}"); Err(()) } else { info!("PN532 SAM configuration successful on shared I2C bus"); Ok(()) } } pub async fn poll_target(&mut self) -> Result<(), ()> { match self .pn532 .process_async(&Request::INLIST_ONE_ISO_A_TARGET, 23) .await { Ok(uid) => { info!("PN532 detected NFC target UID: {uid:?}"); Ok(()) } Err(e) => { info!("No NFC card found on shared I2C bus: {e:?}"); Err(()) } } } 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(()) } } pub async fn read_card_data(&mut self) -> Result, ()> { if let Err(e) = self.poll_target().await { error!("PN532 I2C target poll failed before reading card data: {e:?}"); return Err(e); } 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 .pn532 .process_async(&Request::ntag_read(i), PAGES_PER_READ * 4 + 1) .await else { continue; }; parse_result = Self::parse_nfc_page(i, result); } let bytes = parse_result.unwrap(); let bytes = if i == 0x0B { &bytes[1..] } else { &bytes }; data.extend(bytes); } Ok(data) } pub fn device_mut(&mut self) -> &mut Pn532Device { &mut self.pn532 } }