Add card detection

This commit is contained in:
2026-08-26 00:08:47 +08:00
parent 5c95cc40f7
commit 261b04fec3
69 changed files with 2178 additions and 5928 deletions
+91
View File
@@ -0,0 +1,91 @@
use crate::{BaudRate, Error, Interface, Pn532, Uid};
use crate::commands::{PN532_COMMAND_INDATAEXCHANGE, PN532_COMMAND_INLISTPASSIVETARGET, PN532_COMMAND_INRELEASE};
use crate::error::StatusCode;
impl<B: Interface> Pn532<B> {
/// Wait for an ISO14443A target and read its UID.
///
/// Returns `Ok(None)` when no card appears within `timeout_ms` milliseconds.
pub fn read_passive_target_id(
&mut self,
card_baudrate: BaudRate,
timeout_ms: u16,
) -> Result<Option<Uid>, Error<B::TransportError>> {
self.buffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
self.buffer[1] = 1;
self.buffer[2] = card_baudrate.into();
self.send(3)?;
match self.read_timeout(timeout_ms) {
Err(Error::Timeout) => return Ok(None),
Err(e) => return Err(e),
Ok(_) => {}
}
if self.buffer[0] != 1 {
return Ok(None);
}
let uid_len = self.buffer[5];
if uid_len > 7 {
return Err(Error::InvalidFrame);
}
let mut bytes = [0u8; 7];
bytes[..uid_len as usize].copy_from_slice(&self.buffer[6..6 + uid_len as usize]);
Ok(Some(Uid { bytes: heapless::Vec::from_array(bytes) }))
}
/// In-list a passive target (used before [`Self::in_data_exchange`]).
pub fn in_list_passive_target(&mut self) -> Result<bool, Error<B::TransportError>> {
self.buffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
self.buffer[1] = 1;
self.buffer[2] = 0;
self.send(3)?;
match self.read_timeout(30_000) {
Err(Error::Timeout) => return Ok(false),
Err(e) => return Err(e),
Ok(_) => {}
}
if self.buffer[0] != 1 {
return Ok(false);
}
self.in_listed_tag = self.buffer[1];
Ok(true)
}
/// Exchange data with the currently in-listed peer.
///
/// Returns the number of bytes written to `response`. The response buffer
/// is limited to 64 bytes.
pub fn in_data_exchange(
&mut self,
send: &[u8],
response: &mut [u8],
) -> Result<usize, Error<B::TransportError>> {
self.buffer[0] = PN532_COMMAND_INDATAEXCHANGE;
self.buffer[1] = self.in_listed_tag;
self.send_with_body(2, send)?;
let len = self.read_timeout(1000)?;
if len == 0 || (self.buffer[0] & 0x3F) != 0 {
return Err(Error::Status(StatusCode::from_repr(self.buffer[0] & 0x3F).unwrap()));
}
let data_len = len - 1;
let copy_len = data_len.min(response.len());
response[..copy_len].copy_from_slice(&self.buffer[1..1 + copy_len]);
Ok(copy_len)
}
/// Release an in-listed target.
pub fn in_release(&mut self, relevant_target: u8) -> Result<usize, Error<B::TransportError>> {
self.buffer[0] = PN532_COMMAND_INRELEASE;
self.buffer[1] = relevant_target;
self.send(2)?;
self.read()
}
}