Another refactor

This commit is contained in:
2026-08-30 17:37:36 +08:00
parent da83ff6f94
commit 13e64ab91a
23 changed files with 313 additions and 308 deletions
+16
View File
@@ -0,0 +1,16 @@
use bitfields::bitflag;
///! FeliCa commands.
#[derive(PartialEq, Eq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[bitflag(u8)]
pub enum Command {
#[base]
Polling = 0x00,
RequestService = 0x02,
RequestResponse = 0x04,
ReadWithoutEncryption = 0x06,
WriteWithEncryption = 0x08,
RequestSystemCode = 0x0C
}
+19 -9
View File
@@ -1,10 +1,20 @@
// Mifare commands. // Mifare commands.
pub const MIFARE_CMD_AUTH_A: u8 = 0x60;
pub const MIFARE_CMD_AUTH_B: u8 = 0x61; use bitfields::bitflag;
pub const MIFARE_CMD_READ: u8 = 0x30;
pub const MIFARE_CMD_WRITE: u8 = 0xA0; #[derive(PartialEq, Eq, Debug)]
pub const MIFARE_CMD_WRITE_ULTRALIGHT: u8 = 0xA2; #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub const MIFARE_CMD_TRANSFER: u8 = 0xB0; #[bitflag(u8)]
pub const MIFARE_CMD_DECREMENT: u8 = 0xC0; pub enum Command {
pub const MIFARE_CMD_INCREMENT: u8 = 0xC1; #[base]
pub const MIFARE_CMD_STORE: u8 = 0xC2; Unknown = 0x00,
AuthA = 0x60,
AuthB = 0x61,
Read = 0x30,
Write = 0xA0,
WriteUltralight = 0xA2,
Transfer = 0xB0,
Decrement = 0xC0,
Increment = 0xC1,
Store = 0xC2
}
+9 -46
View File
@@ -1,51 +1,14 @@
//! Command and protocol constants for the PN532. //! Command and protocol constants for the PN532.
pub mod ndef; mod pn532;
pub use pn532::Command as PN532Command;
#[cfg(feature = "mifare-classic")] #[cfg(feature = "mifare-classic")]
pub mod mifare; pub mod mifare;
pub mod pn532; #[cfg(feature = "mifare-classic")]
use mifare::Command as MifareCommand;
// PN532 commands. #[cfg(feature = "felica")]
mod felica;
pub const PN532_RESPONSE_INDATAEXCHANGE: u8 = 0x41; #[cfg(feature = "felica")]
pub const PN532_RESPONSE_INLISTPASSIVETARGET: u8 = 0x4B; pub use felica::Command as FelicaCommand;
pub const PN532_MIFARE_ISO14443A: u8 = 0x00;
// FeliCa commands.
pub const FELICA_CMD_POLLING: u8 = 0x00;
pub const FELICA_CMD_REQUEST_SERVICE: u8 = 0x02;
pub const FELICA_CMD_REQUEST_RESPONSE: u8 = 0x04;
pub const FELICA_CMD_READ_WITHOUT_ENCRYPTION: u8 = 0x06;
pub const FELICA_CMD_WRITE_WITHOUT_ENCRYPTION: u8 = 0x08;
pub const FELICA_CMD_REQUEST_SYSTEM_CODE: u8 = 0x0C;
// GPIO.
pub const PN532_GPIO_VALIDATIONBIT: u8 = 0x80;
pub const PN532_GPIO_P30: u8 = 0;
pub const PN532_GPIO_P31: u8 = 1;
pub const PN532_GPIO_P32: u8 = 2;
pub const PN532_GPIO_P33: u8 = 3;
pub const PN532_GPIO_P34: u8 = 4;
pub const PN532_GPIO_P35: u8 = 5;
pub const FELICA_READ_MAX_SERVICE_NUM: usize = 3;
pub const FELICA_READ_MAX_BLOCK_NUM: usize = 3;
pub const FELICA_WRITE_MAX_SERVICE_NUM: usize = 3;
pub const FELICA_WRITE_MAX_BLOCK_NUM: usize = 3;
pub const FELICA_REQ_SERVICE_MAX_NODE_NUM: usize = 32;
// Frame protocol constants.
pub const PN532_PREAMBLE: u8 = 0x00;
pub const PN532_STARTCODE1: u8 = 0x00;
pub const PN532_STARTCODE2: u8 = 0xFF;
pub const PN532_POSTAMBLE: u8 = 0x00;
pub const PN532_HOST_TO_PN532: u8 = 0xD4;
pub const PN532_PN532_TO_HOST: u8 = 0xD5;
pub const PN532_ACK_WAIT_TIME_MS: u16 = 10;
/// The fixed 7-bit I2C address of the PN532 (0x48 >> 1).
pub const PN532_I2C_ADDRESS: u8 = 0x48 >> 1;
-38
View File
@@ -1,38 +0,0 @@
///! NDEF URI record identifier codes (see NFC Forum "URI Record Type Definition").
pub const NONE: u8 = 0x00;
pub const HTTP_WWWDOT: u8 = 0x01;
pub const HTTPS_WWWDOT: u8 = 0x02;
pub const HTTP: u8 = 0x03;
pub const HTTPS: u8 = 0x04;
pub const TEL: u8 = 0x05;
pub const MAILTO: u8 = 0x06;
pub const FTP_ANONAT: u8 = 0x07;
pub const FTP_FTPDOT: u8 = 0x08;
pub const FTPS: u8 = 0x09;
pub const SFTP: u8 = 0x0A;
pub const SMB: u8 = 0x0B;
pub const NFS: u8 = 0x0C;
pub const FTP: u8 = 0x0D;
pub const DAV: u8 = 0x0E;
pub const NEWS: u8 = 0x0F;
pub const TELNET: u8 = 0x10;
pub const IMAP: u8 = 0x11;
pub const RTSP: u8 = 0x12;
pub const URN: u8 = 0x13;
pub const POP: u8 = 0x14;
pub const SIP: u8 = 0x15;
pub const SIPS: u8 = 0x16;
pub const TFTP: u8 = 0x17;
pub const BTSPP: u8 = 0x18;
pub const BTL2CAP: u8 = 0x19;
pub const BTGOEP: u8 = 0x1A;
pub const TCPOBEX: u8 = 0x1B;
pub const IRDAOBEX: u8 = 0x1C;
pub const FILE: u8 = 0x1D;
pub const URN_EPC_ID: u8 = 0x1E;
pub const URN_EPC_TAG: u8 = 0x1F;
pub const URN_EPC_PAT: u8 = 0x20;
pub const URN_EPC_RAW: u8 = 0x21;
pub const URN_EPC: u8 = 0x22;
pub const URN_NFC: u8 = 0x23;
+49 -32
View File
@@ -1,32 +1,49 @@
pub const DIAGNOSE: u8 = 0x00; use bitfields::bitflag;
pub const GETFIRMWAREVERSION: u8 = 0x02;
pub const GETGENERALSTATUS: u8 = 0x04; #[derive(Debug, PartialEq, Eq)]
pub const READREGISTER: u8 = 0x06; #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub const WRITEREGISTER: u8 = 0x08; #[bitflag(u8)]
pub const READGPIO: u8 = 0x0C; pub enum Command {
pub const WRITEGPIO: u8 = 0x0E; #[base]
pub const SETSERIALBAUDRATE: u8 = 0x10; Diagnose = 0x00,
pub const SETPARAMETERS: u8 = 0x12; GetFirmwareVersion = 0x02,
pub const SAMCONFIGURATION: u8 = 0x14; GetGeneralStatus = 0x04,
pub const POWERDOWN: u8 = 0x16; ReadRegister = 0x06,
pub const RFCONFIGURATION: u8 = 0x32; WriteRegister = 0x08,
pub const RFREGULATIONTEST: u8 = 0x58; ReadGpio = 0x0C,
pub const INJUMPFORDEP: u8 = 0x56; WriteGpio = 0x0E,
pub const INJUMPFORPSL: u8 = 0x46; SetSerialBaudRate = 0x10,
pub const INLISTPASSIVETARGET: u8 = 0x4A; SetParameters = 0x12,
pub const INATR: u8 = 0x50; SamConfiguration = 0x14,
pub const INPSL: u8 = 0x4E; PowerDown = 0x16,
pub const INDATAEXCHANGE: u8 = 0x40;
pub const INCOMMUNICATETHRU: u8 = 0x42; RfConfiguration = 0x32,
pub const INDESELECT: u8 = 0x44; RfRegulationTest = 0x58,
pub const INRELEASE: u8 = 0x52;
pub const INSELECT: u8 = 0x54; InJumpForDep = 0x56,
pub const INAUTOPOLL: u8 = 0x60; InJumpForPsl = 0x46,
pub const TGINITASTARGET: u8 = 0x8C; InListPassiveTarget = 0x4A,
pub const TGSETGENERALBYTES: u8 = 0x92; InAtr = 0x50,
pub const TGGETDATA: u8 = 0x86; InPsl = 0x4E,
pub const TGSETDATA: u8 = 0x8E; InDataExchange = 0x40,
pub const TGSETMETADATA: u8 = 0x94; InCommunicateThru = 0x42,
pub const TGGETINITIATORCOMMAND: u8 = 0x88; InDeselect = 0x44,
pub const TGRESPONSETOINITIATOR: u8 = 0x90; InRelease = 0x52,
pub const TGGETTARGETSTATUS: u8 = 0x8A; InSelect = 0x54,
InAutoPoll = 0x60,
TgInitAsTarget = 0x8C,
TgSetGeneralBytes = 0x92,
TgGetData = 0x86,
TgSetData = 0x8E,
TgSetMetadata = 0x94,
TgGetInitiatorCommand = 0x88,
TgResponseToInitiator = 0x90,
TgGetTargetStatus = 0x8A,
}
impl Command {
pub fn as_response(&self) -> u8 {
self.into_bits().wrapping_add(1)
}
}
+15 -43
View File
@@ -5,38 +5,7 @@ use crate::error::Error;
use crate::interface::Interface; use crate::interface::Interface;
use crate::StatusCode; use crate::StatusCode;
use core::time::Duration; use core::time::Duration;
use crate::types::constants::{PN532_GPIO_P32, PN532_GPIO_P34, PN532_GPIO_VALIDATION_BIT};
/// A card UID read by [`Pn532::read_passive_target_id`].
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Uid {
pub bytes: heapless::Vec<u8, 7>,
}
impl core::fmt::Display for Uid {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
#[cfg(feature = "alloc")]
{
write!(f, "{}", hex::encode(&self.bytes))
}
#[cfg(not(feature = "alloc"))]
{
write!(f, "{:?}", self)
}
}
}
/// Outcome of [`Pn532::tg_init_as_target`] / [`Pn532::tg_init_as_target_default`].
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TargetInitStatus {
/// The PN532 entered target mode.
Success,
/// No initiator appeared within the timeout.
Timeout,
/// The operation failed.
Failed,
}
/// Driver for the NXP PN532 NFC controller. /// Driver for the NXP PN532 NFC controller.
pub struct Pn532<B: Interface, const N: usize = 64> { pub struct Pn532<B: Interface, const N: usize = 64> {
@@ -58,7 +27,10 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
/// Initialise the PN532: pulse the reset pin (if provided) and wait for it /// Initialise the PN532: pulse the reset pin (if provided) and wait for it
/// to become ready. /// to become ready.
pub fn begin(&mut self) -> Result<(), Error<B::TransportError>> { pub fn begin(&mut self) -> Result<(), Error<B::TransportError>> {
self.interface.begin() if let Err(Error::UnusedPin) = self.interface.begin() {
crate::debug!("No reset pin")
}
Ok(())
} }
// -- internal helpers --------------------------------------------------- // -- internal helpers ---------------------------------------------------
@@ -88,7 +60,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
/// Read the PN532 firmware version and ID. /// Read the PN532 firmware version and ID.
pub fn get_firmware_version(&mut self) -> Result<u32, Error<B::TransportError>> { pub fn get_firmware_version(&mut self) -> Result<u32, Error<B::TransportError>> {
self.buffer[0] = pn532::GETFIRMWAREVERSION; self.buffer[0] = PN532Command::GetFirmwareVersion.into_bits();
self.send(1)?; self.send(1)?;
let len = self.read()?; let len = self.read()?;
if len < 4 { if len < 4 {
@@ -104,7 +76,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
/// Read a 16-bit PN532 register. /// Read a 16-bit PN532 register.
pub fn read_register(&mut self, reg: u16) -> Result<u8, Error<B::TransportError>> { pub fn read_register(&mut self, reg: u16) -> Result<u8, Error<B::TransportError>> {
self.buffer[0] = pn532::READREGISTER; self.buffer[0] = PN532Command::ReadRegister.into_bits();
self.buffer[1] = (reg >> 8) as u8; self.buffer[1] = (reg >> 8) as u8;
self.buffer[2] = reg as u8; self.buffer[2] = reg as u8;
self.send(3)?; self.send(3)?;
@@ -117,7 +89,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
/// Write to a 16-bit PN532 register. /// Write to a 16-bit PN532 register.
pub fn write_register(&mut self, reg: u16, val: u8) -> Result<(), Error<B::TransportError>> { pub fn write_register(&mut self, reg: u16, val: u8) -> Result<(), Error<B::TransportError>> {
self.buffer[0] = pn532::WRITEREGISTER; self.buffer[0] = PN532Command::WriteRegister.into_bits();
self.buffer[1] = (reg >> 8) as u8; self.buffer[1] = (reg >> 8) as u8;
self.buffer[2] = reg as u8; self.buffer[2] = reg as u8;
self.buffer[3] = val; self.buffer[3] = val;
@@ -129,8 +101,8 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
/// Set the PN532's GPIO pins (see the PN532 user manual for valid pins). /// Set the PN532's GPIO pins (see the PN532 user manual for valid pins).
pub fn write_gpio(&mut self, pinstate: u8) -> Result<(), Error<B::TransportError>> { pub fn write_gpio(&mut self, pinstate: u8) -> Result<(), Error<B::TransportError>> {
let pinstate = pinstate | (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34); let pinstate = pinstate | (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34);
self.buffer[0] = pn532::WRITEGPIO; self.buffer[0] = PN532Command::WriteGpio.into_bits();
self.buffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate; self.buffer[1] = PN532_GPIO_VALIDATION_BIT | pinstate;
self.buffer[2] = 0x00; self.buffer[2] = 0x00;
self.send(3)?; self.send(3)?;
let len = self.read()?; let len = self.read()?;
@@ -142,7 +114,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
/// Read the state of the PN532's GPIO pins. /// Read the state of the PN532's GPIO pins.
pub fn read_gpio(&mut self) -> Result<u8, Error<B::TransportError>> { pub fn read_gpio(&mut self) -> Result<u8, Error<B::TransportError>> {
self.buffer[0] = pn532::READGPIO; self.buffer[0] = PN532Command::ReadGpio.into_bits();
self.send(1)?; self.send(1)?;
self.read()?; self.read()?;
Ok(self.buffer[0]) Ok(self.buffer[0])
@@ -150,7 +122,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
/// Configure the SAM (Secure Access Module) in normal mode. /// Configure the SAM (Secure Access Module) in normal mode.
pub fn sam_config(&mut self) -> Result<(), Error<B::TransportError>> { pub fn sam_config(&mut self) -> Result<(), Error<B::TransportError>> {
self.buffer[0] = pn532::SAMCONFIGURATION; self.buffer[0] = PN532Command::SamConfiguration.into_bits();
self.buffer[1] = 0x01; // normal mode self.buffer[1] = 0x01; // normal mode
self.buffer[2] = 0x14; // timeout 50 ms * 20 = 1 second self.buffer[2] = 0x14; // timeout 50 ms * 20 = 1 second
self.buffer[3] = 0x01; // use IRQ pin self.buffer[3] = 0x01; // use IRQ pin
@@ -164,7 +136,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
&mut self, &mut self,
max_retries: u8, max_retries: u8,
) -> Result<(), Error<B::TransportError>> { ) -> Result<(), Error<B::TransportError>> {
self.buffer[0] = pn532::RFCONFIGURATION; self.buffer[0] = PN532Command::RfConfiguration.into_bits();
self.buffer[1] = 5; self.buffer[1] = 5;
self.buffer[2] = 0xFF; self.buffer[2] = 0xFF;
self.buffer[3] = 0x01; self.buffer[3] = 0x01;
@@ -180,7 +152,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
auto_rfca: u8, auto_rfca: u8,
rf_on_off: u8, rf_on_off: u8,
) -> Result<(), Error<B::TransportError>> { ) -> Result<(), Error<B::TransportError>> {
self.buffer[0] = pn532::RFCONFIGURATION; self.buffer[0] = PN532Command::RfConfiguration.into_bits();
self.buffer[1] = 1; self.buffer[1] = 1;
self.buffer[2] = 0x00 | auto_rfca | rf_on_off; self.buffer[2] = 0x00 | auto_rfca | rf_on_off;
self.send(3)?; self.send(3)?;
@@ -201,7 +173,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
/// Release the card. /// Release the card.
pub fn release(&mut self) -> Result<(), Error<B::TransportError>> { pub fn release(&mut self) -> Result<(), Error<B::TransportError>> {
self.buffer[0] = pn532::INRELEASE; self.buffer[0] = PN532Command::InRelease.into_bits();
self.buffer[1] = 0x00; self.buffer[1] = 0x00;
self.send(2)?; self.send(2)?;
+2
View File
@@ -29,6 +29,8 @@ pub enum Error<E> {
Status(StatusCode), Status(StatusCode),
#[error("Invalid baud rate")] #[error("Invalid baud rate")]
InvalidBaudRate, InvalidBaudRate,
#[error("Unused pin")]
UnusedPin,
#[cfg(feature = "felica")] #[cfg(feature = "felica")]
#[error(transparent)] #[error(transparent)]
FelicaError(#[from] felica::error::Error), FelicaError(#[from] felica::error::Error),
+29 -31
View File
@@ -5,37 +5,35 @@
//! the driver builds logical commands, the interface handles framing and the //! the driver builds logical commands, the interface handles framing and the
//! acknowledgement/response handshake. //! acknowledgement/response handshake.
use core::convert::Infallible;
use embedded_hal::delay::DelayNs; use embedded_hal::delay::DelayNs;
use embedded_hal::digital::{ErrorType, InputPin, OutputPin}; use embedded_hal::digital::{ErrorKind, ErrorType, InputPin, OutputPin};
use embedded_hal::i2c::{I2c, Operation}; use embedded_hal::i2c::{I2c, Operation};
use crate::types::constants::*;
use crate::commands::{
PN532_ACK_WAIT_TIME_MS, PN532_HOST_TO_PN532, PN532_I2C_ADDRESS, PN532_PN532_TO_HOST,
PN532_POSTAMBLE, PN532_PREAMBLE, PN532_STARTCODE1, PN532_STARTCODE2,
};
use crate::error::Error; use crate::error::Error;
use crate::PN532Command;
const ACK: [u8; 6] = [0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00]; #[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct UnreachError;
/// Maximum response data length supported (matches the PN532's 64-byte packet buffer). impl embedded_hal::digital::Error for UnreachError {
const MAX_DATA_LEN: usize = 64; fn kind(&self) -> ErrorKind {
/// Maximum length of an outbound command frame. ErrorKind::Other
const WRITE_FRAME_CAPACITY: usize = 64; }
}
/// Marker type for when no reset pin is connected. /// Marker type for when no reset pin is connected.
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
pub struct NoReset; pub struct NoReset;
impl ErrorType for NoReset { type Error = Infallible; } impl ErrorType for NoReset { type Error = UnreachError; }
impl OutputPin for NoReset { impl OutputPin for NoReset {
fn set_low(&mut self) -> Result<(), Self::Error> { fn set_low(&mut self) -> Result<(), Self::Error> {
panic!("NoReset should not be used") Err(UnreachError)
} }
fn set_high(&mut self) -> Result<(), Self::Error> { fn set_high(&mut self) -> Result<(), Self::Error> {
panic!("NoReset should not be used") Err(UnreachError)
} }
} }
@@ -43,7 +41,7 @@ impl OutputPin for NoReset {
#[derive(Clone, Copy, Debug, Default)] #[derive(Clone, Copy, Debug, Default)]
pub struct NoIrq; pub struct NoIrq;
impl ErrorType for NoIrq { type Error = Infallible; } impl ErrorType for NoIrq { type Error = UnreachError; }
impl InputPin for NoIrq { impl InputPin for NoIrq {
fn is_high(&mut self) -> Result<bool, Self::Error> { fn is_high(&mut self) -> Result<bool, Self::Error> {
@@ -93,7 +91,7 @@ pub struct I2cInterface<I2C, D, RST = NoReset, IRQ = NoIrq> {
delay: D, delay: D,
reset: RST, reset: RST,
irq: IRQ, irq: IRQ,
command: u8, command: Option<PN532Command>,
} }
impl<I2C, D> I2cInterface<I2C, D, NoReset, NoIrq> { impl<I2C, D> I2cInterface<I2C, D, NoReset, NoIrq> {
@@ -105,7 +103,7 @@ impl<I2C, D> I2cInterface<I2C, D, NoReset, NoIrq> {
delay, delay,
reset: NoReset, reset: NoReset,
irq: NoIrq, irq: NoIrq,
command: 0, command: None,
} }
} }
} }
@@ -118,7 +116,7 @@ impl<I2C, D, RST: OutputPin> I2cInterface<I2C, D, RST, NoIrq> {
delay, delay,
reset, reset,
irq: NoIrq, irq: NoIrq,
command: 0, command: None,
} }
} }
} }
@@ -131,7 +129,7 @@ impl<I2C, D, IRQ: InputPin> I2cInterface<I2C, D, NoReset, IRQ> {
delay, delay,
reset: NoReset, reset: NoReset,
irq, irq,
command: 0, command: None,
} }
} }
} }
@@ -144,7 +142,7 @@ impl<I2C, D, RST: OutputPin, IRQ: InputPin> I2cInterface<I2C, D, RST, IRQ> {
delay, delay,
reset, reset,
irq, irq,
command: 0, command: None,
} }
} }
} }
@@ -168,10 +166,10 @@ where
fn begin(&mut self) -> Result<(), Error<Self::TransportError>> { fn begin(&mut self) -> Result<(), Error<Self::TransportError>> {
// Pulse RSTPD_N: high -> low -> wait -> high -> wait. This mirrors the // Pulse RSTPD_N: high -> low -> wait -> high -> wait. This mirrors the
// Adafruit library's begin() reset sequence. // Adafruit library's begin() reset sequence.
self.reset.set_high().unwrap(); self.reset.set_high().map_err(|_| Error::UnusedPin)?;
self.reset.set_low().unwrap(); self.reset.set_low().map_err(|_| Error::UnusedPin)?;
self.delay.delay_ms(400); self.delay.delay_ms(400);
self.reset.set_high().unwrap(); self.reset.set_high().map_err(|_| Error::UnusedPin)?;
// Let the PN532 boot after the reset is released. The Adafruit library // Let the PN532 boot after the reset is released. The Adafruit library
// waits ~10 ms + a 500 ms wakeup here; give it a full 500 ms. // waits ~10 ms + a 500 ms wakeup here; give it a full 500 ms.
self.delay.delay_ms(500); self.delay.delay_ms(500);
@@ -183,7 +181,7 @@ where
header: &[u8], header: &[u8],
body: &[u8], body: &[u8],
) -> Result<(), Error<Self::TransportError>> { ) -> Result<(), Error<Self::TransportError>> {
self.command = header[0]; self.command = Some(PN532Command::from_bits(header[0]));
let data_len = header.len() + body.len() + 1; // TFI + payload let data_len = header.len() + body.len() + 1; // TFI + payload
if data_len > 0xFF { if data_len > 0xFF {
@@ -192,14 +190,14 @@ where
// PREAMBLE + STARTCODE1 + STARTCODE2 + LEN + LCS + TFI + payload + DCS + POSTAMBLE // PREAMBLE + STARTCODE1 + STARTCODE2 + LEN + LCS + TFI + payload + DCS + POSTAMBLE
let frame_len = 6 + header.len() + body.len() + 2; let frame_len = 6 + header.len() + body.len() + 2;
let mut frame = [0u8; WRITE_FRAME_CAPACITY]; let mut frame = [0u8; MAX_DATA_LEN];
if frame_len > frame.len() { if frame_len > frame.len() {
return Err(Error::NoSpace); return Err(Error::NoSpace);
} }
frame[0] = PN532_PREAMBLE; frame[0] = PN532_PREAMBLE;
frame[1] = PN532_STARTCODE1; frame[1] = PN532_START_CODE_1;
frame[2] = PN532_STARTCODE2; frame[2] = PN532_START_CODE_2;
frame[3] = data_len as u8; frame[3] = data_len as u8;
frame[4] = (!(data_len as u8)).wrapping_add(1); frame[4] = (!(data_len as u8)).wrapping_add(1);
frame[5] = PN532_HOST_TO_PN532; frame[5] = PN532_HOST_TO_PN532;
@@ -248,8 +246,8 @@ where
.map_err(Error::Transport)?; .map_err(Error::Transport)?;
if frame[0] != PN532_PREAMBLE if frame[0] != PN532_PREAMBLE
|| frame[1] != PN532_STARTCODE1 || frame[1] != PN532_START_CODE_1
|| frame[2] != PN532_STARTCODE2 || frame[2] != PN532_START_CODE_2
{ {
return Err(Error::InvalidFrame); return Err(Error::InvalidFrame);
} }
@@ -258,7 +256,7 @@ where
return Err(Error::InvalidFrame); return Err(Error::InvalidFrame);
} }
let cmd = self.command.wrapping_add(1); let cmd = self.command.unwrap().as_response();
if frame[5] != PN532_PN532_TO_HOST || frame[6] != cmd { if frame[5] != PN532_PN532_TO_HOST || frame[6] != cmd {
return Err(Error::InvalidFrame); return Err(Error::InvalidFrame);
} }
@@ -2,6 +2,6 @@ use crate::{Interface, Pn532};
impl<B: Interface, const N: usize> Pn532<B, N> { impl<B: Interface, const N: usize> Pn532<B, N> {
pub fn setup_first_issuance(&mut self) { pub fn setup_first_issuance(&mut self) {
todo!()
} }
} }
+13 -90
View File
@@ -10,31 +10,29 @@ use crate::interface::Interface;
use core::time::Duration; use core::time::Duration;
use crate::types::felica::*; use crate::types::felica::*;
use crate::types::BaudRate; use crate::types::BaudRate;
use crate::types::felica::constants::{FELICA_READ_MAX_BLOCK_NUM, FELICA_READ_MAX_SERVICE_NUM, FELICA_WRITE_MAX_BLOCK_NUM, FELICA_WRITE_MAX_SERVICE_NUM};
impl<B: Interface, const N: usize> Pn532<B, N> { impl<B: Interface, const N: usize> Pn532<B, N> {
/// Poll for a FeliCa card. /// Poll for a FeliCa card.
pub fn felica_polling( pub fn felica_polling(
&mut self, &mut self,
system_code: Option<u16>, config: FelicaPollingConfig
baud_rate: BaudRate,
request_code: FelicaPollingRequestCode,
timeout: Duration,
) -> Result<Option<FelicaPollingResponse>, Error<B::TransportError>> { ) -> Result<Option<FelicaPollingResponse>, Error<B::TransportError>> {
if !matches!(baud_rate, BaudRate::Felica212kbps | BaudRate::Felica424kbps) { if !matches!(config.baud_rate, BaudRate::Felica212kbps | BaudRate::Felica424kbps) {
return Err(Error::InvalidBaudRate); return Err(Error::InvalidBaudRate);
} }
let system_code = system_code.unwrap_or(0xFFFF); let system_code = config.system_code;
self.buffer[0] = pn532::INLISTPASSIVETARGET; self.buffer[0] = PN532Command::InListPassiveTarget.into_bits();
self.buffer[1] = 1; self.buffer[1] = 1;
self.buffer[2] = baud_rate.into(); self.buffer[2] = config.baud_rate.into();
self.buffer[3] = FELICA_CMD_POLLING; self.buffer[3] = FelicaCommand::Polling.into_bits();
self.buffer[4] = (system_code >> 8) as u8; self.buffer[4] = (system_code >> 8) as u8;
self.buffer[5] = system_code as u8; self.buffer[5] = system_code as u8;
self.buffer[6] = request_code as u8; self.buffer[6] = config.request_code as u8;
self.buffer[7] = 0; self.buffer[7] = 0;
self.send(8)?; self.send(8)?;
match self.read_timeout(timeout) { match self.read_timeout(config.timeout) {
Err(Error::Timeout) => return Ok(None), Err(Error::Timeout) => return Ok(None),
Err(e) => return Err(e), Err(e) => return Err(e),
Ok(_) => {} Ok(_) => {}
@@ -87,7 +85,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
if command.len() > 0xFE { if command.len() > 0xFE {
return Err(Error::InvalidParam); return Err(Error::InvalidParam);
} }
self.buffer[0] = pn532::INDATAEXCHANGE; self.buffer[0] = PN532Command::InDataExchange.into_bits();
self.buffer[1] = self.in_listed_tag; self.buffer[1] = self.in_listed_tag;
self.buffer[2] = (command.len() + 1) as u8; self.buffer[2] = (command.len() + 1) as u8;
self.send_with_body(3, command)?; self.send_with_body(3, command)?;
@@ -109,7 +107,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
/// Send a FeliCa "Request Response" command, returning the card's mode. /// Send a FeliCa "Request Response" command, returning the card's mode.
pub fn felica_request_response(&mut self, card: &FelicaPollingResponse) -> Result<u8, Error<B::TransportError>> { pub fn felica_request_response(&mut self, card: &FelicaPollingResponse) -> Result<u8, Error<B::TransportError>> {
let mut cmd = [0u8; 9]; let mut cmd = [0u8; 9];
cmd[0] = FELICA_CMD_REQUEST_RESPONSE; cmd[0] = FelicaCommand::RequestResponse.into_bits();
cmd[1..9].copy_from_slice(&card.idm.into_be_bytes()); cmd[1..9].copy_from_slice(&card.idm.into_be_bytes());
let mut response = [0u8; 10]; let mut response = [0u8; 10];
@@ -154,7 +152,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
// command // command
let mut cmd = heapless::Vec::<u8, COMMAND_SIZE>::new(); let mut cmd = heapless::Vec::<u8, COMMAND_SIZE>::new();
cmd.push(FELICA_CMD_READ_WITHOUT_ENCRYPTION).unwrap(); cmd.push(FelicaCommand::ReadWithoutEncryption.into_bits()).unwrap();
cmd.extend_from_slice(&card.idm.into_bytes()).unwrap(); cmd.extend_from_slice(&card.idm.into_bytes()).unwrap();
cmd.push(num_service as u8).unwrap(); cmd.push(num_service as u8).unwrap();
for sc in service_code_list { for sc in service_code_list {
@@ -224,7 +222,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
// command // command
let mut cmd = heapless::Vec::<u8, COMMAND_SIZE>::new(); let mut cmd = heapless::Vec::<u8, COMMAND_SIZE>::new();
cmd.push(FELICA_CMD_WRITE_WITHOUT_ENCRYPTION).unwrap(); cmd.push(FelicaCommand::WriteWithEncryption as u8).unwrap();
cmd.extend_from_slice(&card.idm.into_bytes()).unwrap(); cmd.extend_from_slice(&card.idm.into_bytes()).unwrap();
cmd.push(num_service as u8).unwrap(); cmd.push(num_service as u8).unwrap();
for sc in service_code_list { for sc in service_code_list {
@@ -255,79 +253,4 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
} }
Ok(()) Ok(())
} }
/// Send a FeliCa "Request System Code" command.
///
/// Returns the number of system codes written to `system_code_list`.
#[cfg(not(feature = "felica-lite-s"))]
pub fn felica_request_system_code(
&mut self,
card: &IDm,
system_code_list: &mut [impl AsServiceCode],
) -> Result<usize, Error<B::TransportError>> {
let mut cmd = [0u8; 9];
cmd[0] = FELICA_CMD_REQUEST_SYSTEM_CODE;
cmd[1..9].copy_from_slice(&card.into_be_bytes());
let mut response = [0u8; 10 + 2 * 16];
let response_len = self.felica_send_command(&cmd, &mut response, Duration::from_millis(200))?;
if response_len < 10 {
return Err(Error::InvalidFrame);
}
let num_system_code = response[9] as usize;
if response_len < 10 + 2 * num_system_code {
return Err(Error::InvalidFrame);
}
if num_system_code > system_code_list.len() {
return Err(Error::NoSpace);
}
for (i, out) in system_code_list.iter_mut().enumerate().take(num_system_code) {
*out = AsServiceCode::from_service_code(
u16::from_be_bytes([response[10 + i * 2], response[10 + i * 2 + 1]])
);
}
Ok(num_system_code)
}
/// Send a FeliCa "Request Service" command.
#[cfg(not(feature = "felica-lite-s"))]
pub fn felica_request_service(
&mut self,
card: &IDm,
node_code_list: &[u16],
key_versions: &mut [u16],
) -> Result<(), Error<B::TransportError>> {
let num_node = node_code_list.len();
if num_node > FELICA_REQ_SERVICE_MAX_NODE_NUM || num_node > key_versions.len() {
return Err(Error::InvalidParam);
}
let mut cmd = [0u8; 1 + 8 + 1 + 2 * FELICA_REQ_SERVICE_MAX_NODE_NUM];
let mut j = 0;
cmd[j] = FELICA_CMD_REQUEST_SERVICE;
j += 1;
cmd[j..j + 8].copy_from_slice(&card.into_be_bytes());
j += 8;
cmd[j] = num_node as u8;
j += 1;
for &code in node_code_list {
cmd[j] = code as u8;
cmd[j + 1] = (code >> 8) as u8;
j += 2;
}
let mut response = [0u8; 10 + 2 * FELICA_REQ_SERVICE_MAX_NODE_NUM];
let response_len = self.felica_send_command(
&cmd[..j],
&mut response,
Duration::from_millis(200)
)?;
if response_len != 10 + 2 * num_node {
return Err(Error::InvalidFrame);
}
for (i, kv) in key_versions.iter_mut().enumerate().take(num_node) {
*kv = u16::from_le_bytes([response[10 + i * 2], response[10 + i * 2 + 1]]);
}
Ok(())
}
} }
+2
View File
@@ -1,3 +1,5 @@
///! WIP
use crate::commands::{PN532_COMMAND_INDATAEXCHANGE, PN532_COMMAND_INLISTPASSIVETARGET, PN532_COMMAND_INRELEASE}; use crate::commands::{PN532_COMMAND_INDATAEXCHANGE, PN532_COMMAND_INLISTPASSIVETARGET, PN532_COMMAND_INRELEASE};
use crate::error::StatusCode; use crate::error::StatusCode;
use crate::{BaudRate, Error, Interface, Pn532, Uid}; use crate::{BaudRate, Error, Interface, Pn532, Uid};
+2
View File
@@ -1,3 +1,5 @@
///! WIP
use crate::commands::{MIFARE_CMD_AUTH_A, MIFARE_CMD_AUTH_B, MIFARE_CMD_READ, MIFARE_CMD_WRITE, MIFARE_CMD_WRITE_ULTRALIGHT, PN532_COMMAND_INDATAEXCHANGE}; use crate::commands::{MIFARE_CMD_AUTH_A, MIFARE_CMD_AUTH_B, MIFARE_CMD_READ, MIFARE_CMD_WRITE, MIFARE_CMD_WRITE_ULTRALIGHT, PN532_COMMAND_INDATAEXCHANGE};
use crate::error::StatusCode; use crate::error::StatusCode;
use crate::{Error, Interface, Pn532}; use crate::{Error, Interface, Pn532};
+3 -1
View File
@@ -1,6 +1,8 @@
///! Card protocols
#[cfg(feature = "felica")] #[cfg(feature = "felica")]
pub mod felica; pub mod felica;
#[cfg(feature = "mifare-classic")] #[cfg(feature = "mifare-classic")]
pub mod mifare; mod mifare;
#[cfg(feature = "iso14443a")] #[cfg(feature = "iso14443a")]
pub mod iso14443a; pub mod iso14443a;
+18 -5
View File
@@ -1,8 +1,21 @@
use crate::commands::*; use crate::commands::*;
use crate::error::StatusCode; use crate::error::StatusCode;
use crate::{Error, Interface, Pn532, TargetInitStatus}; use crate::{Error, Interface, Pn532};
use core::time::Duration; use core::time::Duration;
/// Outcome of [`Pn532::tg_init_as_target`] / [`Pn532::tg_init_as_target_default`].
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum TargetInitStatus {
/// The PN532 entered target mode.
Success,
/// No initiator appeared within the timeout.
Timeout,
/// The operation failed.
Failed,
}
impl<B: Interface, const N: usize> Pn532<B, N> { impl<B: Interface, const N: usize> Pn532<B, N> {
/// Initialize the PN532 as a target using a raw command frame. /// Initialize the PN532 as a target using a raw command frame.
pub fn tg_init_as_target( pub fn tg_init_as_target(
@@ -24,7 +37,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
timeout_ms: u16, timeout_ms: u16,
) -> Result<TargetInitStatus, Error<B::TransportError>> { ) -> Result<TargetInitStatus, Error<B::TransportError>> {
const COMMAND: [u8; 44] = [ const COMMAND: [u8; 44] = [
pn532::TGINITASTARGET, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xFE, PN532Command::TgInitAsTarget.into_bits(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xFE,
0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, 0x06, 0x46, 0xFF, 0xFF, 0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, 0x06, 0x46,
0x66, 0x6D, 0x01, 0x01, 0x10, 0x00, 0x66, 0x6D, 0x01, 0x01, 0x10, 0x00,
@@ -34,7 +47,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
/// Retrieve data received from the initiator. /// Retrieve data received from the initiator.
pub fn tg_get_data(&mut self, buf: &mut [u8]) -> Result<usize, Error<B::TransportError>> { pub fn tg_get_data(&mut self, buf: &mut [u8]) -> Result<usize, Error<B::TransportError>> {
self.buffer[0] = pn532::TGGETDATA; self.buffer[0] = PN532Command::TgGetData.into_bits();
self.send(1)?; self.send(1)?;
let len = self.read_timeout(Duration::from_millis(3000))?; let len = self.read_timeout(Duration::from_millis(3000))?;
@@ -57,10 +70,10 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
body: &[u8], body: &[u8],
) -> Result<(), Error<B::TransportError>> { ) -> Result<(), Error<B::TransportError>> {
if header.len() > N - 1 { if header.len() > N - 1 {
self.buffer[0] = pn532::TGSETDATA; self.buffer[0] = PN532Command::TgSetData.into_bits();
self.interface.write_command(&self.buffer[..1], header)?; self.interface.write_command(&self.buffer[..1], header)?;
} else { } else {
self.buffer[0] = pn532::TGSETDATA; self.buffer[0] = PN532Command::TgSetData.into_bits();
self.buffer[1..1 + header.len()].copy_from_slice(header); self.buffer[1..1 + header.len()].copy_from_slice(header);
self.interface self.interface
.write_command(&self.buffer[..1 + header.len()], body)?; .write_command(&self.buffer[..1 + header.len()], body)?;
+34
View File
@@ -0,0 +1,34 @@
// PN532 commands.
pub const PN532_RESPONSE_IN_DATA_EXCHANGE: u8 = 0x41;
pub const PN532_RESPONSE_IN_LIST_PASSIVE_TARGET: u8 = 0x4B;
pub const PN532_MIFARE_ISO14443A: u8 = 0x00;
// GPIO.
pub const PN532_GPIO_VALIDATION_BIT: u8 = 0x80;
pub const PN532_GPIO_P30: u8 = 0;
pub const PN532_GPIO_P31: u8 = 1;
pub const PN532_GPIO_P32: u8 = 2;
pub const PN532_GPIO_P33: u8 = 3;
pub const PN532_GPIO_P34: u8 = 4;
pub const PN532_GPIO_P35: u8 = 5;
// Frame protocol constants.
pub const PN532_PREAMBLE: u8 = 0x00;
pub const PN532_START_CODE_1: u8 = 0x00;
pub const PN532_START_CODE_2: u8 = 0xFF;
pub const PN532_POSTAMBLE: u8 = 0x00;
pub const PN532_HOST_TO_PN532: u8 = 0xD4;
pub const PN532_PN532_TO_HOST: u8 = 0xD5;
pub const PN532_ACK_WAIT_TIME_MS: u16 = 10;
/// The fixed 7-bit I2C address of the PN532 (0x48 >> 1).
pub const PN532_I2C_ADDRESS: u8 = 0x48 >> 1;
pub const ACK: [u8; 6] = [0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00];
/// Maximum response data length supported (matches the PN532's 64-byte packet buffer).
pub const MAX_DATA_LEN: usize = 64;
+5
View File
@@ -0,0 +1,5 @@
pub const FELICA_READ_MAX_SERVICE_NUM: usize = 3;
pub const FELICA_READ_MAX_BLOCK_NUM: usize = 3;
pub const FELICA_WRITE_MAX_SERVICE_NUM: usize = 3;
pub const FELICA_WRITE_MAX_BLOCK_NUM: usize = 3;
pub const FELICA_REQ_SERVICE_MAX_NODE_NUM: usize = 32;
@@ -1,5 +1,5 @@
use crate::types::felica::AsBlock; use crate::types::felica::AsBlock;
use crate::FELICA_READ_MAX_BLOCK_NUM; use crate::types::felica::constants::FELICA_READ_MAX_BLOCK_NUM;
#[derive(Copy, Clone, Eq, PartialEq, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
+2 -4
View File
@@ -1,11 +1,9 @@
pub mod auth;
use core::fmt::{Display, Formatter};
///! Types for Felica Lite-S (RC-S966) ///! Types for Felica Lite-S (RC-S966)
///! User Manual: https://www.sony.net/Products/felica/business/tech-support/data/fls_usmnl_1.4e.pdf ///! User Manual: https://www.sony.net/Products/felica/business/tech-support/data/fls_usmnl_1.4e.pdf
pub mod auth;
use bitfields::bitflag; use bitfields::bitflag;
use crate::types::felica::polling::PollingResponse;
use super::{AsBlock, IDm, PMm}; use super::{AsBlock, IDm, PMm};
use super::AsServiceCode; use super::AsServiceCode;
+49
View File
@@ -4,11 +4,13 @@ mod idm;
#[cfg(feature = "felica-lite-s")] #[cfg(feature = "felica-lite-s")]
pub mod felica_lite_s; pub mod felica_lite_s;
pub mod ic_type; pub mod ic_type;
pub mod constants;
pub use idm::*; pub use idm::*;
pub use pmm::*; pub use pmm::*;
pub use polling::PollingRequestCode as FelicaPollingRequestCode; pub use polling::PollingRequestCode as FelicaPollingRequestCode;
pub use polling::PollingResponse as FelicaPollingResponse; pub use polling::PollingResponse as FelicaPollingResponse;
pub use polling::PollingConfig as FelicaPollingConfig;
pub use polling::CardSession; pub use polling::CardSession;
#[cfg(feature = "felica-lite-s")] #[cfg(feature = "felica-lite-s")]
pub use felica_lite_s::{Block as FelicaLiteSBlock, ServiceCode as FelicaLiteSServiceCode}; pub use felica_lite_s::{Block as FelicaLiteSBlock, ServiceCode as FelicaLiteSServiceCode};
@@ -37,3 +39,50 @@ impl AsServiceCode for u16 {
val val
} }
} }
use bitfields::bitflag;
/// NDEF URI record identifier codes
/// (see NFC Forum "URI Record Type Definition").
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[bitflag(u8)]
pub enum UriIdentifierCode {
#[base]
None = 0x00,
HttpWwwDot = 0x01,
HttpsWwwDot = 0x02,
Http = 0x03,
Https = 0x04,
Tel = 0x05,
Mailto = 0x06,
FtpAnonAt = 0x07,
FtpFtpDot = 0x08,
Ftps = 0x09,
Sftp = 0x0A,
Smb = 0x0B,
Nfs = 0x0C,
Ftp = 0x0D,
Dav = 0x0E,
News = 0x0F,
Telnet = 0x10,
Imap = 0x11,
Rtsp = 0x12,
Urn = 0x13,
Pop = 0x14,
Sip = 0x15,
Sips = 0x16,
Tftp = 0x17,
BtSpp = 0x18,
BtL2cap = 0x19,
BtGoEp = 0x1A,
TcpObex = 0x1B,
IrdaObex = 0x1C,
File = 0x1D,
UrnEpcId = 0x1E,
UrnEpcTag = 0x1F,
UrnEpcPat = 0x20,
UrnEpcRaw = 0x21,
UrnEpc = 0x22,
UrnNfc = 0x23,
}
+23 -1
View File
@@ -1,7 +1,9 @@
use alloc::string::ToString; use alloc::string::ToString;
use core::fmt::{Display, Formatter}; use core::fmt::{Display, Formatter};
use core::time::Duration;
use bitfields::bitflag; use bitfields::bitflag;
use super::{IDm, PMm}; use crate::types::BaudRate;
use super::{FelicaPollingRequestCode, IDm, PMm};
#[derive(Debug, PartialEq, Eq, Default)] #[derive(Debug, PartialEq, Eq, Default)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -76,3 +78,23 @@ impl Display for CardSession {
write!(f, "IDm: {}, PMm: {}", self.idm, self.pmm) write!(f, "IDm: {}, PMm: {}", self.idm, self.pmm)
} }
} }
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct PollingConfig {
pub system_code: u16,
pub baud_rate: BaudRate,
pub request_code: FelicaPollingRequestCode,
pub timeout: Duration,
}
impl Default for PollingConfig {
fn default() -> Self {
Self {
system_code: 0xFFFF,
baud_rate: BaudRate::Felica212kbps,
request_code: FelicaPollingRequestCode::SystemCode,
timeout: Duration::from_secs(1),
}
}
}
+12
View File
@@ -0,0 +1,12 @@
use crate::{Error, PN532Command};
use crate::types::constants::*;
pub struct DataFrame {
command: PN532Command
}
impl DataFrame {
pub fn new<E>(header: &[u8], body: &[u8]) -> Result<Self, Error<E>> {
Ok(Self { command: PN532Command::TgGetData } )
}
}
+8 -2
View File
@@ -1,11 +1,17 @@
use bitfields::bitflag;
#[cfg(feature = "felica")] #[cfg(feature = "felica")]
pub mod felica; pub mod felica;
pub mod constants;
pub mod frame;
/// Passive target baud rates supported by [`crate::Pn532::read_passive_target_id`]. /// Passive target baud rates supported by [`crate::Pn532::read_passive_target_id`].
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(PartialEq, Eq, Debug)]
#[repr(u8)] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[bitflag(u8)]
pub enum BaudRate { pub enum BaudRate {
ISO14443A106kbps = 0x00, ISO14443A106kbps = 0x00,
#[base]
Felica212kbps = 0x01, Felica212kbps = 0x01,
Felica424kbps = 0x02, Felica424kbps = 0x02,
ISO14443B106kbps = 0x03, ISO14443B106kbps = 0x03,
+1 -4
View File
@@ -50,10 +50,7 @@ pub async fn start_card_reader(
loop { loop {
Timer::after_millis(50).await; Timer::after_millis(50).await;
let Some(response) = (match card_reader.driver.felica_polling( let Some(response) = (match card_reader.driver.felica_polling(
None, Default::default()
BaudRate::Felica212kbps,
FelicaPollingRequestCode::SystemCode,
core::time::Duration::from_secs(1),
) { ) {
Ok(v) => v, Ok(v) => v,
Err(e) => { Err(e) => {