refactor structure
This commit is contained in:
Generated
+1
@@ -5,6 +5,7 @@
|
|||||||
<w>felica</w>
|
<w>felica</w>
|
||||||
<w>gpst</w>
|
<w>gpst</w>
|
||||||
<w>trng</w>
|
<w>trng</w>
|
||||||
|
<w>wcnt</w>
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
</component>
|
</component>
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
//! Command and protocol constants for the PN532.
|
|
||||||
|
|
||||||
// PN532 commands.
|
|
||||||
pub const PN532_COMMAND_DIAGNOSE: u8 = 0x00;
|
|
||||||
pub const PN532_COMMAND_GETFIRMWAREVERSION: u8 = 0x02;
|
|
||||||
pub const PN532_COMMAND_GETGENERALSTATUS: u8 = 0x04;
|
|
||||||
pub const PN532_COMMAND_READREGISTER: u8 = 0x06;
|
|
||||||
pub const PN532_COMMAND_WRITEREGISTER: u8 = 0x08;
|
|
||||||
pub const PN532_COMMAND_READGPIO: u8 = 0x0C;
|
|
||||||
pub const PN532_COMMAND_WRITEGPIO: u8 = 0x0E;
|
|
||||||
pub const PN532_COMMAND_SETSERIALBAUDRATE: u8 = 0x10;
|
|
||||||
pub const PN532_COMMAND_SETPARAMETERS: u8 = 0x12;
|
|
||||||
pub const PN532_COMMAND_SAMCONFIGURATION: u8 = 0x14;
|
|
||||||
pub const PN532_COMMAND_POWERDOWN: u8 = 0x16;
|
|
||||||
pub const PN532_COMMAND_RFCONFIGURATION: u8 = 0x32;
|
|
||||||
pub const PN532_COMMAND_RFREGULATIONTEST: u8 = 0x58;
|
|
||||||
pub const PN532_COMMAND_INJUMPFORDEP: u8 = 0x56;
|
|
||||||
pub const PN532_COMMAND_INJUMPFORPSL: u8 = 0x46;
|
|
||||||
pub const PN532_COMMAND_INLISTPASSIVETARGET: u8 = 0x4A;
|
|
||||||
pub const PN532_COMMAND_INATR: u8 = 0x50;
|
|
||||||
pub const PN532_COMMAND_INPSL: u8 = 0x4E;
|
|
||||||
pub const PN532_COMMAND_INDATAEXCHANGE: u8 = 0x40;
|
|
||||||
pub const PN532_COMMAND_INCOMMUNICATETHRU: u8 = 0x42;
|
|
||||||
pub const PN532_COMMAND_INDESELECT: u8 = 0x44;
|
|
||||||
pub const PN532_COMMAND_INRELEASE: u8 = 0x52;
|
|
||||||
pub const PN532_COMMAND_INSELECT: u8 = 0x54;
|
|
||||||
pub const PN532_COMMAND_INAUTOPOLL: u8 = 0x60;
|
|
||||||
pub const PN532_COMMAND_TGINITASTARGET: u8 = 0x8C;
|
|
||||||
pub const PN532_COMMAND_TGSETGENERALBYTES: u8 = 0x92;
|
|
||||||
pub const PN532_COMMAND_TGGETDATA: u8 = 0x86;
|
|
||||||
pub const PN532_COMMAND_TGSETDATA: u8 = 0x8E;
|
|
||||||
pub const PN532_COMMAND_TGSETMETADATA: u8 = 0x94;
|
|
||||||
pub const PN532_COMMAND_TGGETINITIATORCOMMAND: u8 = 0x88;
|
|
||||||
pub const PN532_COMMAND_TGRESPONSETOINITIATOR: u8 = 0x90;
|
|
||||||
pub const PN532_COMMAND_TGGETTARGETSTATUS: u8 = 0x8A;
|
|
||||||
|
|
||||||
pub const PN532_RESPONSE_INDATAEXCHANGE: u8 = 0x41;
|
|
||||||
pub const PN532_RESPONSE_INLISTPASSIVETARGET: u8 = 0x4B;
|
|
||||||
|
|
||||||
pub const PN532_MIFARE_ISO14443A: u8 = 0x00;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
/// NDEF URI record identifier codes (see NFC Forum "URI Record Type Definition").
|
|
||||||
pub mod ndef {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
|
|
||||||
/// Passive target baud rates supported by [`crate::Pn532::read_passive_target_id`].
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
||||||
#[repr(u8)]
|
|
||||||
pub enum BaudRate {
|
|
||||||
ISO14443A106kbps = 0x00,
|
|
||||||
Felica212kbps = 0x01,
|
|
||||||
Felica424kbps = 0x02,
|
|
||||||
ISO14443B106kbps = 0x03,
|
|
||||||
InnovisionJewel106kbps = 0x04,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<BaudRate> for u8 {
|
|
||||||
fn from(value: BaudRate) -> Self {
|
|
||||||
value as u8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
// 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;
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
//! Command and protocol constants for the PN532.
|
||||||
|
|
||||||
|
pub mod ndef;
|
||||||
|
#[cfg(feature = "mifare-classic")]
|
||||||
|
pub mod mifare;
|
||||||
|
pub mod pn532;
|
||||||
|
|
||||||
|
// 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;
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
///! 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;
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
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;
|
||||||
+9
-9
@@ -88,7 +88,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_COMMAND_GETFIRMWAREVERSION;
|
self.buffer[0] = pn532::GETFIRMWAREVERSION;
|
||||||
self.send(1)?;
|
self.send(1)?;
|
||||||
let len = self.read()?;
|
let len = self.read()?;
|
||||||
if len < 4 {
|
if len < 4 {
|
||||||
@@ -104,7 +104,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_COMMAND_READREGISTER;
|
self.buffer[0] = pn532::READREGISTER;
|
||||||
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 +117,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_COMMAND_WRITEREGISTER;
|
self.buffer[0] = pn532::WRITEREGISTER;
|
||||||
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,7 +129,7 @@ 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_COMMAND_WRITEGPIO;
|
self.buffer[0] = pn532::WRITEGPIO;
|
||||||
self.buffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate;
|
self.buffer[1] = PN532_GPIO_VALIDATIONBIT | pinstate;
|
||||||
self.buffer[2] = 0x00;
|
self.buffer[2] = 0x00;
|
||||||
self.send(3)?;
|
self.send(3)?;
|
||||||
@@ -142,7 +142,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_COMMAND_READGPIO;
|
self.buffer[0] = pn532::READGPIO;
|
||||||
self.send(1)?;
|
self.send(1)?;
|
||||||
self.read()?;
|
self.read()?;
|
||||||
Ok(self.buffer[0])
|
Ok(self.buffer[0])
|
||||||
@@ -150,7 +150,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_COMMAND_SAMCONFIGURATION;
|
self.buffer[0] = pn532::SAMCONFIGURATION;
|
||||||
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 +164,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_COMMAND_RFCONFIGURATION;
|
self.buffer[0] = pn532::RFCONFIGURATION;
|
||||||
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 +180,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_COMMAND_RFCONFIGURATION;
|
self.buffer[0] = pn532::RFCONFIGURATION;
|
||||||
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 +201,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_COMMAND_INRELEASE;
|
self.buffer[0] = pn532::INRELEASE;
|
||||||
self.buffer[1] = 0x00;
|
self.buffer[1] = 0x00;
|
||||||
self.send(2)?;
|
self.send(2)?;
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
use bitfields::bitflag;
|
use bitfields::bitflag;
|
||||||
use crate::felica;
|
use crate::protocol::felica;
|
||||||
|
|
||||||
/// Driver-level error type, generic over the transport (I2C) error.
|
/// Driver-level error type, generic over the transport (I2C) error.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
|
||||||
|
|||||||
+3
-7
@@ -47,15 +47,11 @@ extern crate alloc;
|
|||||||
|
|
||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
#[cfg(feature = "felica")]
|
|
||||||
pub mod felica;
|
|
||||||
pub mod interface;
|
pub mod interface;
|
||||||
pub(crate) mod driver;
|
pub(crate) mod driver;
|
||||||
pub mod tg;
|
pub mod tg;
|
||||||
#[cfg(feature = "mifare-classic")]
|
pub mod types;
|
||||||
pub mod mifare;
|
pub mod protocol;
|
||||||
#[cfg(feature = "iso14443a")]
|
|
||||||
pub mod iso14443a;
|
|
||||||
|
|
||||||
pub use commands::*;
|
pub use commands::*;
|
||||||
pub use driver::*;
|
pub use driver::*;
|
||||||
@@ -64,7 +60,7 @@ pub use interface::*;
|
|||||||
|
|
||||||
#[cfg(feature = "defmt")]
|
#[cfg(feature = "defmt")]
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use defmt::{error, warn, info, debug, trace};
|
use defmt::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
#[cfg(not(feature = "defmt"))]
|
#[cfg(not(feature = "defmt"))]
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
|||||||
+7
-47
@@ -1,53 +1,13 @@
|
|||||||
pub mod issuance;
|
|
||||||
|
|
||||||
use des::cipher::{Block, BlockCipherEncrypt, Key, KeyInit};
|
use des::cipher::{Block, BlockCipherEncrypt, Key, KeyInit};
|
||||||
use des::TdesEde2;
|
use des::TdesEde2;
|
||||||
use rand_core::Rng;
|
use rand_core::Rng;
|
||||||
use crate::{Interface, Pn532};
|
use crate::{Interface, Pn532};
|
||||||
use crate::felica::error::Error;
|
use crate::types::felica::{CardSession, FelicaLiteSBlock, FelicaLiteSServiceCode};
|
||||||
use crate::felica::types::{AsBlock, CardSession, FelicaLiteSBlock, FelicaLiteSServiceCode};
|
use crate::types::felica::felica_lite_s::auth::{AuthSession, CardKey, MacInput, RandomChallenge, SessionKeys};
|
||||||
use crate::felica::types::felica_lite_s::auth::{AuthSession, CardKey, MacInput, RandomChallenge, SessionKeys};
|
|
||||||
|
|
||||||
impl<B: Interface, const N: usize> Pn532<B, N> {
|
impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||||
pub fn try_authenticate(&mut self, rng: &mut impl Rng, card: &CardSession, key: &CardKey)
|
pub(crate) fn set_random_challenge(&mut self, card: &CardSession, rng: &mut impl Rng)
|
||||||
-> Result<Option<AuthSession>, crate::Error<B::TransportError>>
|
-> Result<RandomChallenge, crate::Error<B::TransportError>>
|
||||||
{
|
|
||||||
let rc = self.set_random_challenge(card, rng)?;
|
|
||||||
let sk = self.get_session_keys(&rc, key)?;
|
|
||||||
let session = AuthSession::new(sk, rc);
|
|
||||||
let is_valid_auth = self.check_auth(card, &session)?;
|
|
||||||
if is_valid_auth {
|
|
||||||
Ok(Some(session))
|
|
||||||
} else {
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_with_mac(
|
|
||||||
&mut self,
|
|
||||||
card: &CardSession,
|
|
||||||
session: &AuthSession,
|
|
||||||
block: impl AsBlock
|
|
||||||
) -> Result<[u8; 16], crate::Error<B::TransportError>> {
|
|
||||||
let mut block_data = [[0u8; 16]; 2];
|
|
||||||
let block_list = [block.as_block(), FelicaLiteSBlock::MACA as u16];
|
|
||||||
self.felica_read_without_encryption(
|
|
||||||
card,
|
|
||||||
&[FelicaLiteSServiceCode::Read],
|
|
||||||
&block_list,
|
|
||||||
&mut block_data
|
|
||||||
)?;
|
|
||||||
let input = MacInput::new(&block_data, &block_list);
|
|
||||||
let mac = self.compute_mac(session, &input);
|
|
||||||
if mac != input.maca() {
|
|
||||||
return Err(crate::Error::FelicaError(Error::MACMismatch));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(block_data[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn set_random_challenge(&mut self, card: &CardSession, rng: &mut impl Rng)
|
|
||||||
-> Result<RandomChallenge, crate::Error<B::TransportError>>
|
|
||||||
{
|
{
|
||||||
let mut data = [[0u8; 16]];
|
let mut data = [[0u8; 16]];
|
||||||
rng.fill_bytes(&mut data[0]);
|
rng.fill_bytes(&mut data[0]);
|
||||||
@@ -61,7 +21,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
Ok(rc)
|
Ok(rc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_session_keys(
|
pub(crate) fn get_session_keys(
|
||||||
&mut self,
|
&mut self,
|
||||||
rc: &RandomChallenge,
|
rc: &RandomChallenge,
|
||||||
card_key: &CardKey,
|
card_key: &CardKey,
|
||||||
@@ -82,7 +42,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
// crate::trace!("SK2: {:02X}", sk2);
|
// crate::trace!("SK2: {:02X}", sk2);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_mac<const U: usize>(
|
pub(crate) fn compute_mac<const U: usize>(
|
||||||
&mut self,
|
&mut self,
|
||||||
session: &AuthSession,
|
session: &AuthSession,
|
||||||
input: &MacInput<U>
|
input: &MacInput<U>
|
||||||
@@ -149,7 +109,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
mac
|
mac
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_auth(
|
pub(crate) fn check_auth(
|
||||||
&mut self,
|
&mut self,
|
||||||
card: &CardSession,
|
card: &CardSession,
|
||||||
session: &AuthSession,
|
session: &AuthSession,
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
pub mod issuance;
|
||||||
|
pub mod auth;
|
||||||
|
|
||||||
|
use rand_core::Rng;
|
||||||
|
use crate::{Interface, Pn532};
|
||||||
|
use crate::protocol::felica::error::Error;
|
||||||
|
use crate::types::felica::{AsBlock, CardSession, FelicaLiteSBlock, FelicaLiteSServiceCode};
|
||||||
|
use crate::types::felica::felica_lite_s::auth::{AuthSession, CardKey, MacInput};
|
||||||
|
|
||||||
|
impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||||
|
pub fn try_authenticate(&mut self, rng: &mut impl Rng, card: &CardSession, key: &CardKey)
|
||||||
|
-> Result<Option<AuthSession>, crate::Error<B::TransportError>>
|
||||||
|
{
|
||||||
|
let rc = self.set_random_challenge(card, rng)?;
|
||||||
|
let sk = self.get_session_keys(&rc, key)?;
|
||||||
|
let session = AuthSession::new(sk, rc);
|
||||||
|
let is_valid_auth = self.check_auth(card, &session)?;
|
||||||
|
if is_valid_auth {
|
||||||
|
Ok(Some(session))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_with_mac(
|
||||||
|
&mut self,
|
||||||
|
card: &CardSession,
|
||||||
|
session: &AuthSession,
|
||||||
|
block: impl AsBlock
|
||||||
|
) -> Result<[u8; 16], crate::Error<B::TransportError>> {
|
||||||
|
let mut block_data = [[0u8; 16]; 2];
|
||||||
|
let block_list = [block.as_block(), FelicaLiteSBlock::MACA as u16];
|
||||||
|
self.read_block(card, &block_list, &mut block_data)?;
|
||||||
|
let input = MacInput::new(&block_data, &block_list);
|
||||||
|
let mac = self.compute_mac(session, &input);
|
||||||
|
if mac != input.maca() {
|
||||||
|
return Err(crate::Error::FelicaError(Error::MACMismatch));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(block_data[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_block<const U: usize>(
|
||||||
|
&mut self,
|
||||||
|
card: &CardSession,
|
||||||
|
list: &[impl AsBlock; U],
|
||||||
|
data: &mut [[u8; 16]; U]
|
||||||
|
) -> Result<(), crate::Error<B::TransportError>> {
|
||||||
|
self.felica_read_without_encryption(
|
||||||
|
card,
|
||||||
|
&[FelicaLiteSServiceCode::Read],
|
||||||
|
list,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_block<const U: usize>(
|
||||||
|
&mut self,
|
||||||
|
card: &CardSession,
|
||||||
|
list: &[impl AsBlock; U],
|
||||||
|
data: &[[u8; 16]; U]
|
||||||
|
) -> Result<(), crate::Error<B::TransportError>> {
|
||||||
|
self.felica_write_without_encryption(
|
||||||
|
card,
|
||||||
|
&[FelicaLiteSServiceCode::Write],
|
||||||
|
list,
|
||||||
|
data
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
pub mod types;
|
|
||||||
#[cfg(feature="felica-lite-s")]
|
#[cfg(feature="felica-lite-s")]
|
||||||
mod felica_lite_s;
|
mod felica_lite_s;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
@@ -8,9 +7,9 @@ use crate::commands::*;
|
|||||||
use crate::driver::Pn532;
|
use crate::driver::Pn532;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::interface::Interface;
|
use crate::interface::Interface;
|
||||||
use crate::BaudRate;
|
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use types::*;
|
use crate::types::felica::*;
|
||||||
|
use crate::types::BaudRate;
|
||||||
|
|
||||||
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.
|
||||||
@@ -25,7 +24,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
return Err(Error::InvalidBaudRate);
|
return Err(Error::InvalidBaudRate);
|
||||||
}
|
}
|
||||||
let system_code = system_code.unwrap_or(0xFFFF);
|
let system_code = system_code.unwrap_or(0xFFFF);
|
||||||
self.buffer[0] = PN532_COMMAND_INLISTPASSIVETARGET;
|
self.buffer[0] = pn532::INLISTPASSIVETARGET;
|
||||||
self.buffer[1] = 1;
|
self.buffer[1] = 1;
|
||||||
self.buffer[2] = baud_rate.into();
|
self.buffer[2] = baud_rate.into();
|
||||||
self.buffer[3] = FELICA_CMD_POLLING;
|
self.buffer[3] = FELICA_CMD_POLLING;
|
||||||
@@ -79,7 +78,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
/// Send a raw FeliCa command to the currently in-listed card.
|
/// Send a raw FeliCa command to the currently in-listed card.
|
||||||
///
|
///
|
||||||
/// Returns the number of bytes written to `response`.
|
/// Returns the number of bytes written to `response`.
|
||||||
pub fn felica_send_command(
|
pub(crate) fn felica_send_command(
|
||||||
&mut self,
|
&mut self,
|
||||||
command: &[u8],
|
command: &[u8],
|
||||||
response: &mut [u8],
|
response: &mut [u8],
|
||||||
@@ -88,7 +87,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_COMMAND_INDATAEXCHANGE;
|
self.buffer[0] = pn532::INDATAEXCHANGE;
|
||||||
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)?;
|
||||||
@@ -124,12 +123,12 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
/// Send a FeliCa "Read Without Encryption" command.
|
/// Send a FeliCa "Read Without Encryption" command.
|
||||||
///
|
///
|
||||||
/// Note: the number of blocks is limited by the 64-byte response buffer.
|
/// Note: the number of blocks is limited by the 64-byte response buffer.
|
||||||
pub fn felica_read_without_encryption(
|
pub(crate) fn felica_read_without_encryption<const U: usize>(
|
||||||
&mut self,
|
&mut self,
|
||||||
card: &CardSession,
|
card: &CardSession,
|
||||||
service_code_list: &[impl AsServiceCode],
|
service_code_list: &[impl AsServiceCode],
|
||||||
block_list: &[impl AsBlock],
|
block_list: &[impl AsBlock; U],
|
||||||
block_data: &mut [[u8; 16]],
|
block_data: &mut [[u8; 16]; U],
|
||||||
) -> Result<(), Error<B::TransportError>> {
|
) -> Result<(), Error<B::TransportError>> {
|
||||||
const COMMAND_SIZE: usize =
|
const COMMAND_SIZE: usize =
|
||||||
1 // command code (0x06)
|
1 // command code (0x06)
|
||||||
@@ -148,10 +147,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
|
|
||||||
// validate
|
// validate
|
||||||
let num_service = service_code_list.len();
|
let num_service = service_code_list.len();
|
||||||
let num_block = block_list.len();
|
if num_service > FELICA_READ_MAX_SERVICE_NUM || U > FELICA_READ_MAX_BLOCK_NUM
|
||||||
if num_service > FELICA_READ_MAX_SERVICE_NUM
|
|
||||||
|| num_block > FELICA_READ_MAX_BLOCK_NUM
|
|
||||||
|| num_block > block_data.len()
|
|
||||||
{
|
{
|
||||||
return Err(Error::InvalidParam);
|
return Err(Error::InvalidParam);
|
||||||
}
|
}
|
||||||
@@ -165,7 +161,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
let sc: [u8; 2] = sc.as_service_code().to_le_bytes();
|
let sc: [u8; 2] = sc.as_service_code().to_le_bytes();
|
||||||
cmd.extend_from_slice(&sc).unwrap();
|
cmd.extend_from_slice(&sc).unwrap();
|
||||||
}
|
}
|
||||||
cmd.push(num_block as u8).unwrap();
|
cmd.push(U as u8).unwrap();
|
||||||
for bl in block_list {
|
for bl in block_list {
|
||||||
let bl: [u8; 2] = bl.as_block().to_be_bytes();
|
let bl: [u8; 2] = bl.as_block().to_be_bytes();
|
||||||
cmd.extend_from_slice(&bl).unwrap();
|
cmd.extend_from_slice(&bl).unwrap();
|
||||||
@@ -179,10 +175,10 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
let response_len = self.felica_send_command(
|
let response_len = self.felica_send_command(
|
||||||
&cmd,
|
&cmd,
|
||||||
&mut response,
|
&mut response,
|
||||||
card.pmm.get_read_timeout(num_block, Some(Duration::from_millis(50)))
|
card.pmm.get_read_timeout(U, Some(Duration::from_millis(50)))
|
||||||
)?;
|
)?;
|
||||||
crate::trace!("Read Response: {:02X}", response);
|
crate::trace!("Read Response: {:02X}", response);
|
||||||
if response_len != 12 + 16 * num_block {
|
if response_len != 12 + 16 * U {
|
||||||
return Err(Error::InvalidFrame);
|
return Err(Error::InvalidFrame);
|
||||||
}
|
}
|
||||||
if response[9] != 0 || response[10] != 0 {
|
if response[9] != 0 || response[10] != 0 {
|
||||||
@@ -190,7 +186,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut k = 12;
|
let mut k = 12;
|
||||||
for block in block_data.iter_mut().take(num_block) {
|
for block in block_data.iter_mut().take(U) {
|
||||||
block.copy_from_slice(&response[k..k + 16]);
|
block.copy_from_slice(&response[k..k + 16]);
|
||||||
k += 16;
|
k += 16;
|
||||||
}
|
}
|
||||||
@@ -198,12 +194,12 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Send a FeliCa "Write Without Encryption" command.
|
/// Send a FeliCa "Write Without Encryption" command.
|
||||||
pub fn felica_write_without_encryption(
|
pub(crate) fn felica_write_without_encryption<const U: usize>(
|
||||||
&mut self,
|
&mut self,
|
||||||
card: &CardSession,
|
card: &CardSession,
|
||||||
service_code_list: &[impl AsServiceCode],
|
service_code_list: &[impl AsServiceCode],
|
||||||
block_list: &[impl AsBlock],
|
block_list: &[impl AsBlock; U],
|
||||||
block_data: &[[u8; 16]],
|
block_data: &[[u8; 16]; U],
|
||||||
) -> Result<(), Error<B::TransportError>> {
|
) -> Result<(), Error<B::TransportError>> {
|
||||||
const COMMAND_SIZE: usize =
|
const COMMAND_SIZE: usize =
|
||||||
1 // command code
|
1 // command code
|
||||||
@@ -221,10 +217,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
|
|
||||||
// validate
|
// validate
|
||||||
let num_service = service_code_list.len();
|
let num_service = service_code_list.len();
|
||||||
let num_block = block_list.len();
|
if num_service > FELICA_WRITE_MAX_SERVICE_NUM || U > FELICA_WRITE_MAX_BLOCK_NUM
|
||||||
if num_service > FELICA_WRITE_MAX_SERVICE_NUM
|
|
||||||
|| num_block > FELICA_WRITE_MAX_BLOCK_NUM
|
|
||||||
|| num_block > block_data.len()
|
|
||||||
{
|
{
|
||||||
return Err(Error::InvalidParam);
|
return Err(Error::InvalidParam);
|
||||||
}
|
}
|
||||||
@@ -238,12 +231,12 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
let sc = sc.as_service_code().to_le_bytes();
|
let sc = sc.as_service_code().to_le_bytes();
|
||||||
cmd.extend_from_slice(&sc).unwrap();
|
cmd.extend_from_slice(&sc).unwrap();
|
||||||
}
|
}
|
||||||
cmd.push(num_block as u8).unwrap();
|
cmd.push(U as u8).unwrap();
|
||||||
for block in block_list {
|
for block in block_list {
|
||||||
let block = block.as_block().to_be_bytes();
|
let block = block.as_block().to_be_bytes();
|
||||||
cmd.extend_from_slice(&block).unwrap();
|
cmd.extend_from_slice(&block).unwrap();
|
||||||
}
|
}
|
||||||
for block in block_data.iter().take(num_block) {
|
for block in block_data.iter().take(U) {
|
||||||
cmd.extend_from_slice(block).unwrap();
|
cmd.extend_from_slice(block).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +245,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
|||||||
let response_len = self.felica_send_command(
|
let response_len = self.felica_send_command(
|
||||||
&cmd,
|
&cmd,
|
||||||
&mut response,
|
&mut response,
|
||||||
card.pmm.get_write_timeout(num_block, Some(Duration::from_millis(50)))
|
card.pmm.get_write_timeout(U, Some(Duration::from_millis(50)))
|
||||||
)?;
|
)?;
|
||||||
if response_len != RESPONSE_SIZE {
|
if response_len != RESPONSE_SIZE {
|
||||||
return Err(Error::InvalidFrame);
|
return Err(Error::InvalidFrame);
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#[cfg(feature = "felica")]
|
||||||
|
pub mod felica;
|
||||||
|
#[cfg(feature = "mifare-classic")]
|
||||||
|
pub mod mifare;
|
||||||
|
#[cfg(feature = "iso14443a")]
|
||||||
|
pub mod iso14443a;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::commands::{PN532_COMMAND_TGGETDATA, PN532_COMMAND_TGINITASTARGET, PN532_COMMAND_TGSETDATA};
|
use crate::commands::*;
|
||||||
use crate::error::StatusCode;
|
use crate::error::StatusCode;
|
||||||
use crate::{Error, Interface, Pn532, TargetInitStatus};
|
use crate::{Error, Interface, Pn532, TargetInitStatus};
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
@@ -24,7 +24,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_COMMAND_TGINITASTARGET, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0xFE,
|
pn532::TGINITASTARGET, 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 +34,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_COMMAND_TGGETDATA;
|
self.buffer[0] = pn532::TGGETDATA;
|
||||||
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 +57,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_COMMAND_TGSETDATA;
|
self.buffer[0] = pn532::TGSETDATA;
|
||||||
self.interface.write_command(&self.buffer[..1], header)?;
|
self.interface.write_command(&self.buffer[..1], header)?;
|
||||||
} else {
|
} else {
|
||||||
self.buffer[0] = PN532_COMMAND_TGSETDATA;
|
self.buffer[0] = pn532::TGSETDATA;
|
||||||
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)?;
|
||||||
+1
-8
@@ -1,4 +1,4 @@
|
|||||||
use crate::felica::types::AsBlock;
|
use crate::types::felica::AsBlock;
|
||||||
use crate::FELICA_READ_MAX_BLOCK_NUM;
|
use crate::FELICA_READ_MAX_BLOCK_NUM;
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||||
@@ -26,13 +26,6 @@ impl<const N: usize> MacInput<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_vec(&self) -> heapless::Vec<u8, 64> {
|
|
||||||
let mut data = heapless::Vec::new();
|
|
||||||
data.extend(self.block_list());
|
|
||||||
data.extend_from_slice(&self.block_data()).unwrap();
|
|
||||||
data
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn block_data(&self) -> heapless::Vec<u8, 64> {
|
pub fn block_data(&self) -> heapless::Vec<u8, 64> {
|
||||||
let mut data = heapless::Vec::<u8, 64>::new();
|
let mut data = heapless::Vec::<u8, 64>::new();
|
||||||
for block in self.block_data.iter().take(N - 1) {
|
for block in self.block_data.iter().take(N - 1) {
|
||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
use cbc::cipher::{Block, BlockCipherEncrypt};
|
use cbc::cipher::{Block, BlockCipherEncrypt};
|
||||||
use des::TdesEde2;
|
use des::TdesEde2;
|
||||||
use crate::felica::types::felica_lite_s::auth::RandomChallenge;
|
use crate::types::felica::felica_lite_s::auth::RandomChallenge;
|
||||||
|
|
||||||
#[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))]
|
||||||
+5
-3
@@ -1,10 +1,12 @@
|
|||||||
pub mod auth;
|
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
|
||||||
|
|
||||||
use bitfields::bitflag;
|
use bitfields::bitflag;
|
||||||
use super::AsBlock;
|
use crate::types::felica::polling::PollingResponse;
|
||||||
|
use super::{AsBlock, IDm, PMm};
|
||||||
use super::AsServiceCode;
|
use super::AsServiceCode;
|
||||||
|
|
||||||
/// Service Code
|
/// Service Code
|
||||||
@@ -62,11 +64,11 @@ pub enum Block {
|
|||||||
/// Card key version block.
|
/// Card key version block.
|
||||||
CKV = 0x8086,
|
CKV = 0x8086,
|
||||||
/// Card key block.
|
/// Card key block.
|
||||||
CK= 0x8087,
|
CK = 0x8087,
|
||||||
/// Memory configuration block.
|
/// Memory configuration block.
|
||||||
MemoryConfig = 0x8088,
|
MemoryConfig = 0x8088,
|
||||||
/// Write counter block.
|
/// Write counter block.
|
||||||
WriteCounter = 0x8090,
|
WCNT = 0x8090,
|
||||||
/// MAC_A block.
|
/// MAC_A block.
|
||||||
MACA = 0x8091
|
MACA = 0x8091
|
||||||
}
|
}
|
||||||
@@ -5,14 +5,13 @@ mod idm;
|
|||||||
pub mod felica_lite_s;
|
pub mod felica_lite_s;
|
||||||
pub mod ic_type;
|
pub mod ic_type;
|
||||||
|
|
||||||
use core::fmt::{Display, Formatter};
|
|
||||||
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::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};
|
||||||
use crate::felica::types::polling::PollingResponse;
|
|
||||||
|
|
||||||
pub trait AsServiceCode {
|
pub trait AsServiceCode {
|
||||||
fn as_service_code(&self) -> u16;
|
fn as_service_code(&self) -> u16;
|
||||||
@@ -38,32 +37,3 @@ impl AsServiceCode for u16 {
|
|||||||
val
|
val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
|
||||||
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
|
||||||
#[readonly::make]
|
|
||||||
pub struct CardSession {
|
|
||||||
pub idm: IDm,
|
|
||||||
pub pmm: PMm
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CardSession {
|
|
||||||
pub fn new(idm: IDm, pmm: PMm) -> Self {
|
|
||||||
Self { idm, pmm }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<PollingResponse> for CardSession {
|
|
||||||
fn from(value: PollingResponse) -> Self {
|
|
||||||
Self {
|
|
||||||
idm: value.idm,
|
|
||||||
pmm: value.pmm
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for CardSession {
|
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
|
||||||
write!(f, "IDm: {}, PMm: {}", self.idm, self.pmm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use core::fmt::Display;
|
use core::fmt::{Display, Formatter};
|
||||||
use bitfields::bitflag;
|
use bitfields::bitflag;
|
||||||
use super::{IDm, PMm};
|
use super::{IDm, PMm};
|
||||||
|
|
||||||
@@ -47,3 +47,32 @@ impl Display for PollingResponse {
|
|||||||
write!(f, "IDm: {}, PMm, {}, System Code: {}", self.idm, self.pmm, system_code)
|
write!(f, "IDm: {}, PMm, {}, System Code: {}", self.idm, self.pmm, system_code)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
|
||||||
|
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
|
||||||
|
#[readonly::make]
|
||||||
|
pub struct CardSession {
|
||||||
|
pub idm: IDm,
|
||||||
|
pub pmm: PMm
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CardSession {
|
||||||
|
pub fn new(idm: IDm, pmm: PMm) -> Self {
|
||||||
|
Self { idm, pmm }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PollingResponse> for CardSession {
|
||||||
|
fn from(value: PollingResponse) -> Self {
|
||||||
|
Self {
|
||||||
|
idm: value.idm,
|
||||||
|
pmm: value.pmm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for CardSession {
|
||||||
|
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
|
||||||
|
write!(f, "IDm: {}, PMm: {}", self.idm, self.pmm)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#[cfg(feature = "felica")]
|
||||||
|
pub mod felica;
|
||||||
|
|
||||||
|
/// Passive target baud rates supported by [`crate::Pn532::read_passive_target_id`].
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
#[repr(u8)]
|
||||||
|
pub enum BaudRate {
|
||||||
|
ISO14443A106kbps = 0x00,
|
||||||
|
Felica212kbps = 0x01,
|
||||||
|
Felica424kbps = 0x02,
|
||||||
|
ISO14443B106kbps = 0x03,
|
||||||
|
InnovisionJewel106kbps = 0x04,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<BaudRate> for u8 {
|
||||||
|
fn from(value: BaudRate) -> Self {
|
||||||
|
value as u8
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,9 +4,10 @@ use embassy_sync::once_lock::OnceLock;
|
|||||||
use embassy_time::{Delay, Timer};
|
use embassy_time::{Delay, Timer};
|
||||||
use esp_hal::gpio;
|
use esp_hal::gpio;
|
||||||
use esp_hal::rng::Trng;
|
use esp_hal::rng::Trng;
|
||||||
use pn532::felica::types::{CardSession, FelicaLiteSBlock, FelicaPollingRequestCode};
|
use pn532::types::felica::{CardSession, FelicaLiteSBlock, FelicaPollingRequestCode};
|
||||||
use pn532::{BaudRate, Pn532};
|
use pn532::{Pn532};
|
||||||
use pn532::felica::types::felica_lite_s::auth::CardKey;
|
use pn532::types::felica::felica_lite_s::auth::CardKey;
|
||||||
|
use pn532::types::BaudRate;
|
||||||
|
|
||||||
static CARD_KEY: OnceLock<CardKey> = OnceLock::new();
|
static CARD_KEY: OnceLock<CardKey> = OnceLock::new();
|
||||||
const CARD_KEY_STR: &str = env!("CARD_KEY");
|
const CARD_KEY_STR: &str = env!("CARD_KEY");
|
||||||
|
|||||||
Reference in New Issue
Block a user