Another refactor
This commit is contained in:
@@ -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
|
||||
}
|
||||
@@ -1,10 +1,20 @@
|
||||
// Mifare commands.
|
||||
pub const MIFARE_CMD_AUTH_A: u8 = 0x60;
|
||||
pub const MIFARE_CMD_AUTH_B: u8 = 0x61;
|
||||
pub const MIFARE_CMD_READ: u8 = 0x30;
|
||||
pub const MIFARE_CMD_WRITE: u8 = 0xA0;
|
||||
pub const MIFARE_CMD_WRITE_ULTRALIGHT: u8 = 0xA2;
|
||||
pub const MIFARE_CMD_TRANSFER: u8 = 0xB0;
|
||||
pub const MIFARE_CMD_DECREMENT: u8 = 0xC0;
|
||||
pub const MIFARE_CMD_INCREMENT: u8 = 0xC1;
|
||||
pub const MIFARE_CMD_STORE: u8 = 0xC2;
|
||||
|
||||
use bitfields::bitflag;
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[bitflag(u8)]
|
||||
pub enum Command {
|
||||
#[base]
|
||||
Unknown = 0x00,
|
||||
AuthA = 0x60,
|
||||
AuthB = 0x61,
|
||||
Read = 0x30,
|
||||
Write = 0xA0,
|
||||
WriteUltralight = 0xA2,
|
||||
Transfer = 0xB0,
|
||||
Decrement = 0xC0,
|
||||
Increment = 0xC1,
|
||||
Store = 0xC2
|
||||
}
|
||||
@@ -1,51 +1,14 @@
|
||||
//! Command and protocol constants for the PN532.
|
||||
|
||||
pub mod ndef;
|
||||
mod pn532;
|
||||
pub use pn532::Command as PN532Command;
|
||||
|
||||
#[cfg(feature = "mifare-classic")]
|
||||
pub mod mifare;
|
||||
pub mod pn532;
|
||||
#[cfg(feature = "mifare-classic")]
|
||||
use mifare::Command as MifareCommand;
|
||||
|
||||
// PN532 commands.
|
||||
|
||||
pub const PN532_RESPONSE_INDATAEXCHANGE: u8 = 0x41;
|
||||
pub const PN532_RESPONSE_INLISTPASSIVETARGET: u8 = 0x4B;
|
||||
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;
|
||||
#[cfg(feature = "felica")]
|
||||
mod felica;
|
||||
#[cfg(feature = "felica")]
|
||||
pub use felica::Command as FelicaCommand;
|
||||
|
||||
@@ -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
@@ -1,32 +1,49 @@
|
||||
pub const DIAGNOSE: u8 = 0x00;
|
||||
pub const GETFIRMWAREVERSION: u8 = 0x02;
|
||||
pub const GETGENERALSTATUS: u8 = 0x04;
|
||||
pub const READREGISTER: u8 = 0x06;
|
||||
pub const WRITEREGISTER: u8 = 0x08;
|
||||
pub const READGPIO: u8 = 0x0C;
|
||||
pub const WRITEGPIO: u8 = 0x0E;
|
||||
pub const SETSERIALBAUDRATE: u8 = 0x10;
|
||||
pub const SETPARAMETERS: u8 = 0x12;
|
||||
pub const SAMCONFIGURATION: u8 = 0x14;
|
||||
pub const POWERDOWN: u8 = 0x16;
|
||||
pub const RFCONFIGURATION: u8 = 0x32;
|
||||
pub const RFREGULATIONTEST: u8 = 0x58;
|
||||
pub const INJUMPFORDEP: u8 = 0x56;
|
||||
pub const INJUMPFORPSL: u8 = 0x46;
|
||||
pub const INLISTPASSIVETARGET: u8 = 0x4A;
|
||||
pub const INATR: u8 = 0x50;
|
||||
pub const INPSL: u8 = 0x4E;
|
||||
pub const INDATAEXCHANGE: u8 = 0x40;
|
||||
pub const INCOMMUNICATETHRU: u8 = 0x42;
|
||||
pub const INDESELECT: u8 = 0x44;
|
||||
pub const INRELEASE: u8 = 0x52;
|
||||
pub const INSELECT: u8 = 0x54;
|
||||
pub const INAUTOPOLL: u8 = 0x60;
|
||||
pub const TGINITASTARGET: u8 = 0x8C;
|
||||
pub const TGSETGENERALBYTES: u8 = 0x92;
|
||||
pub const TGGETDATA: u8 = 0x86;
|
||||
pub const TGSETDATA: u8 = 0x8E;
|
||||
pub const TGSETMETADATA: u8 = 0x94;
|
||||
pub const TGGETINITIATORCOMMAND: u8 = 0x88;
|
||||
pub const TGRESPONSETOINITIATOR: u8 = 0x90;
|
||||
pub const TGGETTARGETSTATUS: u8 = 0x8A;
|
||||
use bitfields::bitflag;
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[bitflag(u8)]
|
||||
pub enum Command {
|
||||
#[base]
|
||||
Diagnose = 0x00,
|
||||
GetFirmwareVersion = 0x02,
|
||||
GetGeneralStatus = 0x04,
|
||||
ReadRegister = 0x06,
|
||||
WriteRegister = 0x08,
|
||||
ReadGpio = 0x0C,
|
||||
WriteGpio = 0x0E,
|
||||
SetSerialBaudRate = 0x10,
|
||||
SetParameters = 0x12,
|
||||
SamConfiguration = 0x14,
|
||||
PowerDown = 0x16,
|
||||
|
||||
RfConfiguration = 0x32,
|
||||
RfRegulationTest = 0x58,
|
||||
|
||||
InJumpForDep = 0x56,
|
||||
InJumpForPsl = 0x46,
|
||||
InListPassiveTarget = 0x4A,
|
||||
InAtr = 0x50,
|
||||
InPsl = 0x4E,
|
||||
InDataExchange = 0x40,
|
||||
InCommunicateThru = 0x42,
|
||||
InDeselect = 0x44,
|
||||
InRelease = 0x52,
|
||||
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
@@ -5,38 +5,7 @@ use crate::error::Error;
|
||||
use crate::interface::Interface;
|
||||
use crate::StatusCode;
|
||||
use core::time::Duration;
|
||||
|
||||
/// 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,
|
||||
}
|
||||
use crate::types::constants::{PN532_GPIO_P32, PN532_GPIO_P34, PN532_GPIO_VALIDATION_BIT};
|
||||
|
||||
/// Driver for the NXP PN532 NFC controller.
|
||||
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
|
||||
/// to become ready.
|
||||
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 ---------------------------------------------------
|
||||
@@ -88,7 +60,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
|
||||
/// Read the PN532 firmware version and ID.
|
||||
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)?;
|
||||
let len = self.read()?;
|
||||
if len < 4 {
|
||||
@@ -104,7 +76,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
|
||||
/// Read a 16-bit PN532 register.
|
||||
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[2] = reg as u8;
|
||||
self.send(3)?;
|
||||
@@ -117,7 +89,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
|
||||
/// Write to a 16-bit PN532 register.
|
||||
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[2] = reg as u8;
|
||||
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).
|
||||
pub fn write_gpio(&mut self, pinstate: u8) -> Result<(), Error<B::TransportError>> {
|
||||
let pinstate = pinstate | (1 << PN532_GPIO_P32) | (1 << PN532_GPIO_P34);
|
||||
self.buffer[0] = pn532::WRITEGPIO;
|
||||
self.buffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate;
|
||||
self.buffer[0] = PN532Command::WriteGpio.into_bits();
|
||||
self.buffer[1] = PN532_GPIO_VALIDATION_BIT | pinstate;
|
||||
self.buffer[2] = 0x00;
|
||||
self.send(3)?;
|
||||
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.
|
||||
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.read()?;
|
||||
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.
|
||||
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[2] = 0x14; // timeout 50 ms * 20 = 1 second
|
||||
self.buffer[3] = 0x01; // use IRQ pin
|
||||
@@ -164,7 +136,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
&mut self,
|
||||
max_retries: u8,
|
||||
) -> Result<(), Error<B::TransportError>> {
|
||||
self.buffer[0] = pn532::RFCONFIGURATION;
|
||||
self.buffer[0] = PN532Command::RfConfiguration.into_bits();
|
||||
self.buffer[1] = 5;
|
||||
self.buffer[2] = 0xFF;
|
||||
self.buffer[3] = 0x01;
|
||||
@@ -180,7 +152,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
auto_rfca: u8,
|
||||
rf_on_off: u8,
|
||||
) -> Result<(), Error<B::TransportError>> {
|
||||
self.buffer[0] = pn532::RFCONFIGURATION;
|
||||
self.buffer[0] = PN532Command::RfConfiguration.into_bits();
|
||||
self.buffer[1] = 1;
|
||||
self.buffer[2] = 0x00 | auto_rfca | rf_on_off;
|
||||
self.send(3)?;
|
||||
@@ -201,7 +173,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
|
||||
/// Release the card.
|
||||
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.send(2)?;
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ pub enum Error<E> {
|
||||
Status(StatusCode),
|
||||
#[error("Invalid baud rate")]
|
||||
InvalidBaudRate,
|
||||
#[error("Unused pin")]
|
||||
UnusedPin,
|
||||
#[cfg(feature = "felica")]
|
||||
#[error(transparent)]
|
||||
FelicaError(#[from] felica::error::Error),
|
||||
|
||||
+29
-31
@@ -5,37 +5,35 @@
|
||||
//! the driver builds logical commands, the interface handles framing and the
|
||||
//! acknowledgement/response handshake.
|
||||
|
||||
use core::convert::Infallible;
|
||||
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 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::types::constants::*;
|
||||
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).
|
||||
const MAX_DATA_LEN: usize = 64;
|
||||
/// Maximum length of an outbound command frame.
|
||||
const WRITE_FRAME_CAPACITY: usize = 64;
|
||||
impl embedded_hal::digital::Error for UnreachError {
|
||||
fn kind(&self) -> ErrorKind {
|
||||
ErrorKind::Other
|
||||
}
|
||||
}
|
||||
|
||||
/// Marker type for when no reset pin is connected.
|
||||
#[derive(Clone, Copy, Debug, Default)]
|
||||
pub struct NoReset;
|
||||
|
||||
impl ErrorType for NoReset { type Error = Infallible; }
|
||||
impl ErrorType for NoReset { type Error = UnreachError; }
|
||||
|
||||
impl OutputPin for NoReset {
|
||||
fn set_low(&mut self) -> Result<(), Self::Error> {
|
||||
panic!("NoReset should not be used")
|
||||
Err(UnreachError)
|
||||
}
|
||||
|
||||
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)]
|
||||
pub struct NoIrq;
|
||||
|
||||
impl ErrorType for NoIrq { type Error = Infallible; }
|
||||
impl ErrorType for NoIrq { type Error = UnreachError; }
|
||||
|
||||
impl InputPin for NoIrq {
|
||||
fn is_high(&mut self) -> Result<bool, Self::Error> {
|
||||
@@ -93,7 +91,7 @@ pub struct I2cInterface<I2C, D, RST = NoReset, IRQ = NoIrq> {
|
||||
delay: D,
|
||||
reset: RST,
|
||||
irq: IRQ,
|
||||
command: u8,
|
||||
command: Option<PN532Command>,
|
||||
}
|
||||
|
||||
impl<I2C, D> I2cInterface<I2C, D, NoReset, NoIrq> {
|
||||
@@ -105,7 +103,7 @@ impl<I2C, D> I2cInterface<I2C, D, NoReset, NoIrq> {
|
||||
delay,
|
||||
reset: NoReset,
|
||||
irq: NoIrq,
|
||||
command: 0,
|
||||
command: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,7 +116,7 @@ impl<I2C, D, RST: OutputPin> I2cInterface<I2C, D, RST, NoIrq> {
|
||||
delay,
|
||||
reset,
|
||||
irq: NoIrq,
|
||||
command: 0,
|
||||
command: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -131,7 +129,7 @@ impl<I2C, D, IRQ: InputPin> I2cInterface<I2C, D, NoReset, IRQ> {
|
||||
delay,
|
||||
reset: NoReset,
|
||||
irq,
|
||||
command: 0,
|
||||
command: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -144,7 +142,7 @@ impl<I2C, D, RST: OutputPin, IRQ: InputPin> I2cInterface<I2C, D, RST, IRQ> {
|
||||
delay,
|
||||
reset,
|
||||
irq,
|
||||
command: 0,
|
||||
command: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,10 +166,10 @@ where
|
||||
fn begin(&mut self) -> Result<(), Error<Self::TransportError>> {
|
||||
// Pulse RSTPD_N: high -> low -> wait -> high -> wait. This mirrors the
|
||||
// Adafruit library's begin() reset sequence.
|
||||
self.reset.set_high().unwrap();
|
||||
self.reset.set_low().unwrap();
|
||||
self.reset.set_high().map_err(|_| Error::UnusedPin)?;
|
||||
self.reset.set_low().map_err(|_| Error::UnusedPin)?;
|
||||
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
|
||||
// waits ~10 ms + a 500 ms wakeup here; give it a full 500 ms.
|
||||
self.delay.delay_ms(500);
|
||||
@@ -183,7 +181,7 @@ where
|
||||
header: &[u8],
|
||||
body: &[u8],
|
||||
) -> 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
|
||||
if data_len > 0xFF {
|
||||
@@ -192,14 +190,14 @@ where
|
||||
|
||||
// PREAMBLE + STARTCODE1 + STARTCODE2 + LEN + LCS + TFI + payload + DCS + POSTAMBLE
|
||||
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() {
|
||||
return Err(Error::NoSpace);
|
||||
}
|
||||
|
||||
frame[0] = PN532_PREAMBLE;
|
||||
frame[1] = PN532_STARTCODE1;
|
||||
frame[2] = PN532_STARTCODE2;
|
||||
frame[1] = PN532_START_CODE_1;
|
||||
frame[2] = PN532_START_CODE_2;
|
||||
frame[3] = data_len as u8;
|
||||
frame[4] = (!(data_len as u8)).wrapping_add(1);
|
||||
frame[5] = PN532_HOST_TO_PN532;
|
||||
@@ -248,8 +246,8 @@ where
|
||||
.map_err(Error::Transport)?;
|
||||
|
||||
if frame[0] != PN532_PREAMBLE
|
||||
|| frame[1] != PN532_STARTCODE1
|
||||
|| frame[2] != PN532_STARTCODE2
|
||||
|| frame[1] != PN532_START_CODE_1
|
||||
|| frame[2] != PN532_START_CODE_2
|
||||
{
|
||||
return Err(Error::InvalidFrame);
|
||||
}
|
||||
@@ -258,7 +256,7 @@ where
|
||||
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 {
|
||||
return Err(Error::InvalidFrame);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@ use crate::{Interface, Pn532};
|
||||
|
||||
impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
pub fn setup_first_issuance(&mut self) {
|
||||
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -10,31 +10,29 @@ use crate::interface::Interface;
|
||||
use core::time::Duration;
|
||||
use crate::types::felica::*;
|
||||
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> {
|
||||
/// Poll for a FeliCa card.
|
||||
pub fn felica_polling(
|
||||
&mut self,
|
||||
system_code: Option<u16>,
|
||||
baud_rate: BaudRate,
|
||||
request_code: FelicaPollingRequestCode,
|
||||
timeout: Duration,
|
||||
config: FelicaPollingConfig
|
||||
) -> 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);
|
||||
}
|
||||
let system_code = system_code.unwrap_or(0xFFFF);
|
||||
self.buffer[0] = pn532::INLISTPASSIVETARGET;
|
||||
let system_code = config.system_code;
|
||||
self.buffer[0] = PN532Command::InListPassiveTarget.into_bits();
|
||||
self.buffer[1] = 1;
|
||||
self.buffer[2] = baud_rate.into();
|
||||
self.buffer[3] = FELICA_CMD_POLLING;
|
||||
self.buffer[2] = config.baud_rate.into();
|
||||
self.buffer[3] = FelicaCommand::Polling.into_bits();
|
||||
self.buffer[4] = (system_code >> 8) 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.send(8)?;
|
||||
|
||||
match self.read_timeout(timeout) {
|
||||
match self.read_timeout(config.timeout) {
|
||||
Err(Error::Timeout) => return Ok(None),
|
||||
Err(e) => return Err(e),
|
||||
Ok(_) => {}
|
||||
@@ -87,7 +85,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
if command.len() > 0xFE {
|
||||
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[2] = (command.len() + 1) as u8;
|
||||
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.
|
||||
pub fn felica_request_response(&mut self, card: &FelicaPollingResponse) -> Result<u8, Error<B::TransportError>> {
|
||||
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());
|
||||
|
||||
let mut response = [0u8; 10];
|
||||
@@ -154,7 +152,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
|
||||
// command
|
||||
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.push(num_service as u8).unwrap();
|
||||
for sc in service_code_list {
|
||||
@@ -224,7 +222,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
|
||||
// command
|
||||
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.push(num_service as u8).unwrap();
|
||||
for sc in service_code_list {
|
||||
@@ -255,79 +253,4 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
}
|
||||
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(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
///! WIP
|
||||
|
||||
use crate::commands::{PN532_COMMAND_INDATAEXCHANGE, PN532_COMMAND_INLISTPASSIVETARGET, PN532_COMMAND_INRELEASE};
|
||||
use crate::error::StatusCode;
|
||||
use crate::{BaudRate, Error, Interface, Pn532, Uid};
|
||||
|
||||
@@ -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::error::StatusCode;
|
||||
use crate::{Error, Interface, Pn532};
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
///! Card protocols
|
||||
|
||||
#[cfg(feature = "felica")]
|
||||
pub mod felica;
|
||||
#[cfg(feature = "mifare-classic")]
|
||||
pub mod mifare;
|
||||
mod mifare;
|
||||
#[cfg(feature = "iso14443a")]
|
||||
pub mod iso14443a;
|
||||
+18
-5
@@ -1,8 +1,21 @@
|
||||
use crate::commands::*;
|
||||
use crate::error::StatusCode;
|
||||
use crate::{Error, Interface, Pn532, TargetInitStatus};
|
||||
use crate::{Error, Interface, Pn532};
|
||||
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> {
|
||||
/// Initialize the PN532 as a target using a raw command frame.
|
||||
pub fn tg_init_as_target(
|
||||
@@ -24,7 +37,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
timeout_ms: u16,
|
||||
) -> Result<TargetInitStatus, Error<B::TransportError>> {
|
||||
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,
|
||||
0xFF, 0xFF, 0x01, 0xFE, 0x0F, 0xBB, 0xBA, 0xA6, 0xC9, 0x89, 0x00, 0x00, 0x06, 0x46,
|
||||
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.
|
||||
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)?;
|
||||
|
||||
let len = self.read_timeout(Duration::from_millis(3000))?;
|
||||
@@ -57,10 +70,10 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
body: &[u8],
|
||||
) -> Result<(), Error<B::TransportError>> {
|
||||
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)?;
|
||||
} else {
|
||||
self.buffer[0] = pn532::TGSETDATA;
|
||||
self.buffer[0] = PN532Command::TgSetData.into_bits();
|
||||
self.buffer[1..1 + header.len()].copy_from_slice(header);
|
||||
self.interface
|
||||
.write_command(&self.buffer[..1 + header.len()], body)?;
|
||||
|
||||
@@ -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;
|
||||
@@ -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::FELICA_READ_MAX_BLOCK_NUM;
|
||||
use crate::types::felica::constants::FELICA_READ_MAX_BLOCK_NUM;
|
||||
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
pub mod auth;
|
||||
|
||||
use core::fmt::{Display, Formatter};
|
||||
///! Types for Felica Lite-S (RC-S966)
|
||||
///! User Manual: https://www.sony.net/Products/felica/business/tech-support/data/fls_usmnl_1.4e.pdf
|
||||
|
||||
pub mod auth;
|
||||
|
||||
use bitfields::bitflag;
|
||||
use crate::types::felica::polling::PollingResponse;
|
||||
use super::{AsBlock, IDm, PMm};
|
||||
use super::AsServiceCode;
|
||||
|
||||
|
||||
@@ -4,11 +4,13 @@ mod idm;
|
||||
#[cfg(feature = "felica-lite-s")]
|
||||
pub mod felica_lite_s;
|
||||
pub mod ic_type;
|
||||
pub mod constants;
|
||||
|
||||
pub use idm::*;
|
||||
pub use pmm::*;
|
||||
pub use polling::PollingRequestCode as FelicaPollingRequestCode;
|
||||
pub use polling::PollingResponse as FelicaPollingResponse;
|
||||
pub use polling::PollingConfig as FelicaPollingConfig;
|
||||
pub use polling::CardSession;
|
||||
#[cfg(feature = "felica-lite-s")]
|
||||
pub use felica_lite_s::{Block as FelicaLiteSBlock, ServiceCode as FelicaLiteSServiceCode};
|
||||
@@ -36,4 +38,51 @@ impl AsServiceCode for u16 {
|
||||
fn from_service_code(val: u16) -> Self {
|
||||
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,
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
use alloc::string::ToString;
|
||||
use core::fmt::{Display, Formatter};
|
||||
use core::time::Duration;
|
||||
use bitfields::bitflag;
|
||||
use super::{IDm, PMm};
|
||||
use crate::types::BaudRate;
|
||||
use super::{FelicaPollingRequestCode, IDm, PMm};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Default)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
@@ -75,4 +77,24 @@ impl Display for CardSession {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||
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),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 } )
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,17 @@
|
||||
use bitfields::bitflag;
|
||||
|
||||
#[cfg(feature = "felica")]
|
||||
pub mod felica;
|
||||
pub mod constants;
|
||||
pub mod frame;
|
||||
|
||||
/// Passive target baud rates supported by [`crate::Pn532::read_passive_target_id`].
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u8)]
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||
#[bitflag(u8)]
|
||||
pub enum BaudRate {
|
||||
ISO14443A106kbps = 0x00,
|
||||
#[base]
|
||||
Felica212kbps = 0x01,
|
||||
Felica424kbps = 0x02,
|
||||
ISO14443B106kbps = 0x03,
|
||||
|
||||
Reference in New Issue
Block a user