Finish pn532 crate
This commit is contained in:
@@ -4,10 +4,10 @@ use embassy_sync::once_lock::OnceLock;
|
||||
use embassy_time::{Delay, Timer};
|
||||
use esp_hal::gpio;
|
||||
use esp_hal::rng::Trng;
|
||||
use pn532::types::felica::{CardSession, FelicaLiteSBlock, FelicaPollingRequestCode};
|
||||
use pn532::{Pn532};
|
||||
use pn532::types::felica::felica_lite_s::auth::CardKey;
|
||||
use pn532::types::BaudRate;
|
||||
use pn532::types::felica::felica_lite_s::auth::{CardKey, CardKeyVersion};
|
||||
use pn532::types::felica::felica_lite_s::config::{MemoryConfig, RFParameter};
|
||||
use pn532::types::felica::{CardSession, FelicaLiteSBlock};
|
||||
use pn532::Pn532;
|
||||
|
||||
static CARD_KEY: OnceLock<CardKey> = OnceLock::new();
|
||||
const CARD_KEY_STR: &str = env!("CARD_KEY");
|
||||
@@ -16,24 +16,30 @@ fn get_card_key() -> &'static CardKey {
|
||||
CARD_KEY.get_or_init(|| {
|
||||
let mut buffer = [0u8; 16];
|
||||
hex::decode_to_slice(CARD_KEY_STR, &mut buffer).unwrap();
|
||||
CardKey(buffer)
|
||||
CardKey::from(buffer)
|
||||
})
|
||||
}
|
||||
|
||||
pub struct CardReader<'a> {
|
||||
driver: Pn532<gpio::Output<'a>, gpio::Input<'a>, Delay, pn532::I2cInterface<SharedI2c<'a>, Delay, gpio::Output<'a>, gpio::Input<'a>>>
|
||||
driver: Pn532<
|
||||
gpio::Output<'a>,
|
||||
gpio::Input<'a>,
|
||||
Delay,
|
||||
pn532::I2cInterface<SharedI2c<'a>, Delay, gpio::Output<'a>, gpio::Input<'a>>,
|
||||
>,
|
||||
}
|
||||
|
||||
impl<'a> CardReader<'a> {
|
||||
pub fn new(i2c: SharedI2c<'a>, irq: gpio::Input<'a>, reset: gpio::Output<'a>) -> Self {
|
||||
Self {
|
||||
driver: Pn532::new(pn532::I2cInterface::with_reset_irq(i2c, Delay, reset, irq))
|
||||
driver: Pn532::new(pn532::I2cInterface::with_reset_irq(i2c, Delay, reset, irq)),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn init(&mut self) -> Result<(), crate::error::Error> {
|
||||
self.driver.begin()?;
|
||||
self.driver.sam_config()?;
|
||||
self.driver.set_passive_activation_retries(5)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@@ -42,16 +48,29 @@ impl<'a> CardReader<'a> {
|
||||
pub async fn start_card_reader(
|
||||
mut card_reader: CardReader<'static>,
|
||||
_publisher: LoraPublisher<'static>,
|
||||
mut trng: Trng
|
||||
mut trng: Trng,
|
||||
) -> () {
|
||||
loop {
|
||||
match _start_card_reader(&mut card_reader, &_publisher, &mut trng).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
defmt::error!("Error while reading card: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn _start_card_reader(
|
||||
card_reader: &mut CardReader<'static>,
|
||||
_publisher: &LoraPublisher<'static>,
|
||||
trng: &mut Trng,
|
||||
) -> Result<(), crate::error::Error> {
|
||||
let card_key = get_card_key();
|
||||
defmt::trace!("card_key: {}", card_key);
|
||||
|
||||
let driver = &mut card_reader.driver;
|
||||
loop {
|
||||
Timer::after_millis(50).await;
|
||||
let Some(response) = (match card_reader.driver.felica_polling(
|
||||
Default::default()
|
||||
) {
|
||||
Timer::after_millis(10).await;
|
||||
let Some(response) = (match driver.felica_polling(Default::default()) {
|
||||
Ok(v) => v,
|
||||
Err(e) => {
|
||||
defmt::error!("card_reader driver error: {}", e);
|
||||
@@ -62,8 +81,9 @@ pub async fn start_card_reader(
|
||||
continue;
|
||||
};
|
||||
defmt::info!("Polling card: {}", Debug2Format(&response));
|
||||
defmt::debug!("IDm: {}", response.idm.into_bytes());
|
||||
let card = CardSession::from(response);
|
||||
|
||||
|
||||
// if let Err(e) = card_reader.driver.felica_write_without_encryption(
|
||||
// &response.idm, &response.pmm,
|
||||
// &[FelicaLiteSServiceCode::Write],
|
||||
@@ -73,32 +93,64 @@ pub async fn start_card_reader(
|
||||
// defmt::error!("card_reader write ck error: {}", e);
|
||||
// continue;
|
||||
// }
|
||||
let id = driver.get_id(&card)?;
|
||||
defmt::debug!("ID: {}", id);
|
||||
|
||||
if let Some(card_id) = option_env!("CARD_ID") {
|
||||
let mut id = [0u8; 6];
|
||||
hex::decode_to_slice(card_id,&mut id)?;
|
||||
driver.set_id(&card, id, None)?;
|
||||
}
|
||||
|
||||
let mut mc = driver.get_mc(&card)?;
|
||||
defmt::info!("Config: {}", mc);
|
||||
mc.access.set_system_block(0x00);
|
||||
mc.ndef = 0x00;
|
||||
mc.rf = RFParameter::from(0xFF);
|
||||
mc.access.set_is_ck_ckv_rewritable(true);
|
||||
|
||||
let mut read_auth = mc.auth.scratch_pad_read();
|
||||
read_auth.set_pad0(true);
|
||||
mc.auth.set_scratch_pad_read(read_auth);
|
||||
|
||||
let mut write_auth = mc.auth.scratch_pad_write();
|
||||
write_auth.set_pad0(true);
|
||||
mc.auth.set_scratch_pad_write(write_auth);
|
||||
|
||||
let mut mac_auth = mc.auth.scratch_pad_mac_write();
|
||||
mac_auth.set_pad0(true);
|
||||
mc.auth.set_scratch_pad_mac_write(mac_auth);
|
||||
|
||||
let auth_result = card_reader.driver.try_authenticate(
|
||||
&mut trng, &card, card_key
|
||||
);
|
||||
let session = match auth_result {
|
||||
let block: [u8; 16] = mc.into();
|
||||
defmt::debug!("1st insurance Config: {}", block);
|
||||
driver.set_mc(&card, mc)?;
|
||||
|
||||
let session = match driver.try_authenticate(trng, &card, card_key) {
|
||||
Ok(Some(sk)) => sk,
|
||||
Ok(None) => {
|
||||
defmt::warn!("card key is invalid");
|
||||
continue;
|
||||
},
|
||||
}
|
||||
Err(e) => {
|
||||
defmt::error!("card_reader auth error: {}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let read_result = card_reader.driver.read_with_mac(&card, &session, FelicaLiteSBlock::PAD0);
|
||||
let _read_data = match read_result {
|
||||
|
||||
driver.set_ck_with_mac(&card, &session, &card_key)?;
|
||||
driver.set_ckv_with_mac(&card, &session, &CardKeyVersion::new(1))?;
|
||||
driver.get_ckv(&card)?;
|
||||
|
||||
let _read_data = match driver.read_with_mac(&card, &session, FelicaLiteSBlock::PAD0) {
|
||||
Ok(d) => d,
|
||||
Err(e) => {
|
||||
defmt::error!("card_reader read with mac error: {}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
match card_reader.driver.release() {
|
||||
Ok(_) => {},
|
||||
|
||||
match driver.release() {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
defmt::error!("card_reader release error: {}", e);
|
||||
continue;
|
||||
@@ -107,9 +159,9 @@ pub async fn start_card_reader(
|
||||
|
||||
// InRelease switches the RF field off when no target remains
|
||||
// (UM0701-02 §7.3.11), so re-enable it before the next poll.
|
||||
if let Err(e) = card_reader.driver.set_rf_field(0x00, 0x01) {
|
||||
if let Err(e) = driver.set_rf_field(0x00, 0x01) {
|
||||
defmt::error!("card_reader RF field error: {}", e);
|
||||
}
|
||||
Timer::after_millis(200).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user