Add card detection
This commit is contained in:
@@ -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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user