use bitfield instead of strum
This commit is contained in:
+1
-2
@@ -3,7 +3,6 @@ name = "pn532"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
description = "A no_std, embedded-hal driver for the NXP PN532 NFC controller (I2C interface)"
|
||||
license = "BSD-3-Clause"
|
||||
keywords = ["nfc", "pn532", "embedded-hal", "no-std", "i2c"]
|
||||
categories = ["embedded", "no-std", "hardware-support"]
|
||||
|
||||
@@ -20,9 +19,9 @@ defmt = { version = "~1.1", optional = true }
|
||||
hex = { version = "~0.4", default-features = false }
|
||||
des = { version = "~0.9", default-features = false }
|
||||
cbc = { version = "~0.2", default-features = false, features = ["block-padding"] }
|
||||
strum = { version = "0.28.0", default-features = false, features = ["derive", "strum_macros"] }
|
||||
heapless = "~0.9"
|
||||
thiserror = { version = "~2", default-features = false }
|
||||
bitfields = "3.1.0"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
+1
-1
@@ -199,7 +199,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
/// return error if current buffer contains an error code
|
||||
pub(crate) fn validate_buffer(&self, len: usize) -> Result<(), Error<B::TransportError>> {
|
||||
if len == 0 || (self.buffer[0] & 0x3F) != 0 {
|
||||
Err(Error::Status(StatusCode::from_repr(self.buffer[0] & 0x3F).unwrap()))
|
||||
Err(Error::Status(StatusCode::from_bits(self.buffer[0] & 0x3F)))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
+5
-3
@@ -1,6 +1,6 @@
|
||||
use core::fmt::Debug;
|
||||
use bitfields::bitflag;
|
||||
use defmt::Debug2Format;
|
||||
use strum::FromRepr;
|
||||
|
||||
/// Driver-level error type, generic over the transport (I2C) error.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, thiserror::Error)]
|
||||
@@ -40,9 +40,11 @@ impl<E: Debug> defmt::Format for Error<E> {
|
||||
}
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(FromRepr, Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[bitflag(u8)]
|
||||
pub enum StatusCode {
|
||||
#[base]
|
||||
Unknown = 0x00,
|
||||
TimeOut = 0x01,
|
||||
CRC = 0x02,
|
||||
Parity = 0x03,
|
||||
|
||||
@@ -124,7 +124,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
let mut j = 0;
|
||||
cmd[j] = FELICA_CMD_REQUEST_SERVICE;
|
||||
j += 1;
|
||||
cmd[j..j + 8].copy_from_slice(&card.to_bytes());
|
||||
cmd[j..j + 8].copy_from_slice(&card.into_be_bytes());
|
||||
j += 8;
|
||||
cmd[j] = num_node as u8;
|
||||
j += 1;
|
||||
@@ -153,7 +153,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
pub fn felica_request_response(&mut self, card: &PollingResponse) -> Result<u8, Error<B::TransportError>> {
|
||||
let mut cmd = [0u8; 9];
|
||||
cmd[0] = FELICA_CMD_REQUEST_RESPONSE;
|
||||
cmd[1..9].copy_from_slice(&card.idm.to_bytes());
|
||||
cmd[1..9].copy_from_slice(&card.idm.into_be_bytes());
|
||||
|
||||
let mut response = [0u8; 10];
|
||||
let response_len = self.felica_send_command(&cmd, &mut response, Duration::from_millis(200))?;
|
||||
@@ -202,7 +202,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.extend_from_slice(&card.to_bytes()).unwrap();
|
||||
cmd.extend_from_slice(&card.into_be_bytes()).unwrap();
|
||||
cmd.push(num_service as u8).unwrap();
|
||||
for sc in service_code_list {
|
||||
let sc: [u8; 2] = sc.as_service_code().to_le_bytes();
|
||||
@@ -228,7 +228,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
return Err(Error::InvalidFrame);
|
||||
}
|
||||
if response[9] != 0 || response[10] != 0 {
|
||||
return Err(Error::Status(StatusCode::from_repr(response[9]).unwrap()));
|
||||
return Err(Error::Status(StatusCode::from_bits(response[9])));
|
||||
}
|
||||
|
||||
let mut k = 12;
|
||||
@@ -275,7 +275,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.extend_from_slice(&card.to_bytes()).unwrap();
|
||||
cmd.extend_from_slice(&card.into_be_bytes()).unwrap();
|
||||
cmd.push(num_service as u8).unwrap();
|
||||
for sc in service_code_list {
|
||||
let sc = sc.as_service_code().to_le_bytes();
|
||||
@@ -301,7 +301,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
return Err(Error::InvalidFrame);
|
||||
}
|
||||
if response[9] != 0 || response[10] != 0 {
|
||||
return Err(Error::Status(StatusCode::from_repr(response[9]).unwrap()));
|
||||
return Err(Error::Status(StatusCode::from_bits(response[9])));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -316,7 +316,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
) -> Result<usize, Error<B::TransportError>> {
|
||||
let mut cmd = [0u8; 9];
|
||||
cmd[0] = FELICA_CMD_REQUEST_SYSTEM_CODE;
|
||||
cmd[1..9].copy_from_slice(&card.to_bytes());
|
||||
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))?;
|
||||
|
||||
@@ -1,30 +1,8 @@
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
use bitfields::bitfield;
|
||||
|
||||
#[bitfield([u8; 8])]
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct IDm {
|
||||
pub manufacturer: u8,
|
||||
pub card_id: [u8; 7]
|
||||
}
|
||||
|
||||
impl IDm {
|
||||
/// The raw 8 bytes in wire order (manufacturer, ic_type, card_id).
|
||||
pub fn to_bytes(&self) -> [u8; 8] {
|
||||
let mut data = [0u8; 8];
|
||||
data[0] = self.manufacturer;
|
||||
data[1..].copy_from_slice(&self.card_id);
|
||||
data
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 8]> for IDm {
|
||||
fn from(value: [u8; 8]) -> Self {
|
||||
Self {
|
||||
manufacturer: value[0],
|
||||
card_id: value[1..].try_into().unwrap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<[u8; 8]> for IDm {
|
||||
fn into(self) -> [u8; 8] {
|
||||
self.to_bytes()
|
||||
}
|
||||
}
|
||||
@@ -2,20 +2,21 @@ mod polling;
|
||||
mod pmm;
|
||||
mod idm;
|
||||
|
||||
use bitfields::bitflag;
|
||||
pub use idm::*;
|
||||
pub use pmm::*;
|
||||
pub use polling::*;
|
||||
|
||||
use strum::FromRepr;
|
||||
|
||||
pub trait AsServiceCode {
|
||||
fn as_service_code(&self) -> u16;
|
||||
fn from_service_code(val: u16) -> Self;
|
||||
}
|
||||
|
||||
#[derive(FromRepr, Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(u16)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[bitflag(u16)]
|
||||
pub enum ServiceCode {
|
||||
#[base]
|
||||
Unknown = 0,
|
||||
/// FeliCa Lite read service code (read without key).
|
||||
Read = 0x000B,
|
||||
/// FeliCa Lite write service code (write without key).
|
||||
@@ -28,7 +29,7 @@ impl AsServiceCode for ServiceCode {
|
||||
}
|
||||
|
||||
fn from_service_code(val: u16) -> Self {
|
||||
Self::from_repr(val).unwrap()
|
||||
Self::from_bits(val)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,9 +48,11 @@ pub trait AsBlock {
|
||||
}
|
||||
|
||||
/// FeliCa Lite system block numbers.
|
||||
#[derive(FromRepr, Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[repr(u16)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[bitflag(u16)]
|
||||
pub enum Block {
|
||||
#[base]
|
||||
Unknown = 0,
|
||||
/// Random challenge block.
|
||||
RC = 0x8080,
|
||||
/// MAC block.
|
||||
@@ -81,3 +84,38 @@ impl AsBlock for u16 {
|
||||
*self | 0x8000
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// https://www.sony.co.jp/en/Products/felica/business/tech-support/list.html
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
#[bitflag(u8)]
|
||||
pub enum CardICType {
|
||||
#[base]
|
||||
Unknown = 0x00,
|
||||
S140 = 0x50,
|
||||
SA40_2P = 0x51,
|
||||
SA41_2C = 0x52,
|
||||
SA21_2 = 0x46,
|
||||
SA20_2 = 0x45,
|
||||
SA20_1 = 0x44,
|
||||
SA01_2 = 0x35,
|
||||
SA00_1 = 0x32,
|
||||
S962 = 0x20,
|
||||
S960 = 0x0D,
|
||||
S953 = 0x09,
|
||||
S952 = 0x08,
|
||||
S915 = 0x01,
|
||||
S982 = 0xF1,
|
||||
S978F = 0xF0,
|
||||
S967LiteS = 0xF2,
|
||||
S967Plug = 0xE1,
|
||||
S967NFC = 0xFF,
|
||||
S926 = 0xE0
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum MobileICType {
|
||||
V3(u8), // 0x14~0x1F
|
||||
V2(u8), // 0x10~0x13
|
||||
V1(u8) // 0x06~0x07
|
||||
}
|
||||
@@ -1,42 +1,28 @@
|
||||
use core::time::Duration;
|
||||
use bitfields::bitfield;
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[bitfield([u8; 8])]
|
||||
#[derive(PartialEq, Eq)]
|
||||
pub struct PMm {
|
||||
pub rom_type: u8,
|
||||
pub ic_type: u8,
|
||||
_f1: u8,
|
||||
_f2: u8,
|
||||
_f3: u8,
|
||||
pub read_timeout: u8,
|
||||
pub write_timeout: u8,
|
||||
}
|
||||
|
||||
impl From<[u8; 8]> for PMm {
|
||||
fn from(value: [u8; 8]) -> Self {
|
||||
Self {
|
||||
rom_type: value[0],
|
||||
ic_type: value[1],
|
||||
read_timeout: value[5],
|
||||
write_timeout: value[6],
|
||||
}
|
||||
}
|
||||
_f4: u8,
|
||||
}
|
||||
|
||||
impl PMm {
|
||||
pub fn to_bytes(&self) -> [u8; 8] {
|
||||
let mut data = [0u8; 8];
|
||||
data[0] = self.rom_type;
|
||||
data[1] = self.ic_type;
|
||||
data[5] = self.read_timeout;
|
||||
data[6] = self.write_timeout;
|
||||
data
|
||||
}
|
||||
|
||||
/// Maximum response time for a Read command over `block_len` blocks:
|
||||
pub fn get_read_timeout(&self, block_len: usize, margin: Option<Duration>) -> Duration {
|
||||
Self::response_time(self.read_timeout, block_len) + margin.unwrap_or(Duration::default())
|
||||
Self::response_time(self.read_timeout(), block_len) + margin.unwrap_or(Duration::default())
|
||||
}
|
||||
|
||||
/// Maximum response time for a Write command over `block_len` blocks.
|
||||
pub fn get_write_timeout(&self, block_len: usize, margin: Option<Duration>) -> Duration {
|
||||
Self::response_time(self.write_timeout, block_len) + margin.unwrap_or(Duration::default())
|
||||
Self::response_time(self.write_timeout(), block_len) + margin.unwrap_or(Duration::default())
|
||||
}
|
||||
|
||||
/// `T x [(B+1)*n + (A+1)] x 4^E`, with `T = 256*16/fc ~= 302.06 us`.
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
use bitfields::bitflag;
|
||||
use super::{IDm, PMm};
|
||||
use strum::FromRepr;
|
||||
|
||||
#[derive(FromRepr, Copy, Clone, Debug, PartialEq, Eq, Default)]
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, PartialEq, Eq, Default)]
|
||||
#[bitflag(u8)]
|
||||
pub enum PollingRequestCode {
|
||||
NoRequest,
|
||||
NoRequest = 0x00,
|
||||
#[default]
|
||||
SystemCode,
|
||||
CommunicationPerformance
|
||||
SystemCode = 0x01,
|
||||
CommunicationPerformance = 0x02
|
||||
}
|
||||
|
||||
#[derive(FromRepr, Copy, Clone, Debug, PartialEq, Eq, Default)]
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, PartialEq, Eq, Default)]
|
||||
#[bitflag(u8)]
|
||||
pub enum PollingTimeSlot {
|
||||
#[default]
|
||||
_1 = 0x00,
|
||||
|
||||
+2
-2
@@ -42,7 +42,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
return Ok(0);
|
||||
}
|
||||
if self.buffer[0] != 0 {
|
||||
return Err(Error::Status(StatusCode::from_repr(self.buffer[0]).unwrap()));
|
||||
return Err(Error::Status(StatusCode::from_bits(self.buffer[0])));
|
||||
}
|
||||
let data_len = len - 1;
|
||||
let copy_len = data_len.min(buf.len());
|
||||
@@ -68,7 +68,7 @@ impl<B: Interface, const N: usize> Pn532<B, N> {
|
||||
|
||||
let len = self.read_timeout(Duration::from_millis(3000))?;
|
||||
if len == 0 || self.buffer[0] != 0 {
|
||||
return Err(Error::Status(StatusCode::from_repr(self.buffer[0]).unwrap()));
|
||||
return Err(Error::Status(StatusCode::from_bits(self.buffer[0])));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user