1#![deny(unsafe_code, missing_docs)]
61#![cfg_attr(not(feature = "std"), no_std)]
62
63pub mod comm;
64mod error;
65mod picc;
66mod register;
67mod tests;
68mod util;
69
70pub use error::Error;
71pub use picc::Type;
72pub use register::RxGain;
73
74use comm::Interface;
75use register::*;
76use util::Sealed;
77
78pub type MifareKey = [u8; 6];
80
81pub enum Uid {
83 Single(GenericUid<4>),
85 Double(GenericUid<7>),
87 Triple(GenericUid<10>),
89}
90
91impl Uid {
92 pub fn as_bytes(&self) -> &[u8] {
94 match self {
95 Uid::Single(u) => u.as_bytes(),
96 Uid::Double(u) => u.as_bytes(),
97 Uid::Triple(u) => u.as_bytes(),
98 }
99 }
100
101 pub fn get_type(&self) -> Type {
103 match self {
104 Uid::Single(u) => u.get_type(),
105 Uid::Double(u) => u.get_type(),
106 Uid::Triple(u) => u.get_type(),
107 }
108 }
109}
110
111pub struct GenericUid<const T: usize>
115where
116 [u8; T]: Sized,
117{
118 bytes: [u8; T],
120 sak: picc::Sak,
122}
123
124impl<const T: usize> GenericUid<T> {
125 pub fn new(bytes: [u8; T], sak_byte: u8) -> Self {
130 Self {
131 bytes,
132 sak: picc::Sak::from(sak_byte),
133 }
134 }
135
136 pub fn as_bytes(&self) -> &[u8] {
138 &self.bytes
139 }
140
141 pub fn is_compliant(&self) -> bool {
143 self.sak.is_compliant()
144 }
145
146 pub fn get_type(&self) -> Type {
148 self.sak.get_type()
149 }
150}
151
152pub struct AtqA {
154 bytes: [u8; 2],
155}
156
157pub trait State: Sealed {}
161
162pub enum Uninitialized {}
164pub enum Initialized {}
166
167impl State for Uninitialized {}
168impl State for Initialized {}
169impl Sealed for Uninitialized {}
170impl Sealed for Initialized {}
171
172pub struct Mfrc522<COMM: Interface, S: State> {
174 comm: COMM,
175 state: core::marker::PhantomData<S>,
176}
177
178impl<COMM: Interface> Mfrc522<COMM, Uninitialized> {
179 pub fn new(comm: COMM) -> Self {
181 Self {
182 comm,
183 state: core::marker::PhantomData,
184 }
185 }
186}
187
188impl<COMM: Interface, S: State> Mfrc522<COMM, S> {
189 pub fn release(self) -> COMM {
191 self.comm
192 }
193}
194
195impl<E, COMM: Interface<Error = E>> Mfrc522<COMM, Uninitialized> {
197 pub fn init(mut self) -> Result<Mfrc522<COMM, Initialized>, Error<E>> {
201 self.reset()?;
202 self.write(Register::TxModeReg, 0x00)?;
203 self.write(Register::RxModeReg, 0x00)?;
204 self.write(Register::ModWidthReg, 0x26)?;
206
207 self.write(Register::TModeReg, 0x80)?;
211 self.write(Register::TPrescalerReg, 0xA9)?;
215 self.write(Register::TReloadRegHigh, 0x03)?;
218 self.write(Register::TReloadRegLow, 0xE8)?;
219
220 self.write(Register::TxASKReg, FORCE_100_ASK)?;
222 self.write(Register::ModeReg, (0x3f & (!0b11)) | 0b01)?;
224 self.rmw(Register::TxControlReg, |b| b | 0b11)?;
226
227 Ok(Mfrc522 {
228 comm: self.comm,
229 state: core::marker::PhantomData,
230 })
231 }
232}
233
234impl<E, COMM: Interface<Error = E>> Mfrc522<COMM, Initialized> {
236 pub fn reqa(&mut self) -> Result<AtqA, Error<E>> {
238 let fifo_data = self.transceive(&[picc::Command::ReqA as u8], 7, 0)?;
240 if fifo_data.valid_bytes != 2 || fifo_data.valid_bits != 0 {
241 Err(Error::IncompleteFrame)
242 } else {
243 Ok(AtqA {
244 bytes: fifo_data.buffer,
245 })
246 }
247 }
248
249 pub fn wupa(&mut self) -> Result<AtqA, Error<E>> {
251 let fifo_data = self.transceive(&[picc::Command::WupA as u8], 7, 0)?;
253 if fifo_data.valid_bytes != 2 || fifo_data.valid_bits != 0 {
254 Err(Error::IncompleteFrame)
255 } else {
256 Ok(AtqA {
257 bytes: fifo_data.buffer,
258 })
259 }
260 }
261
262 pub fn hlta(&mut self) -> Result<(), Error<E>> {
264 let mut buffer: [u8; 4] = [picc::Command::HltA as u8, 0, 0, 0];
265 let crc = self.calculate_crc(&buffer[..2])?;
266 buffer[2..].copy_from_slice(&crc);
267
268 match self.transceive::<0>(&buffer, 0, 0) {
274 Err(Error::Timeout) => Ok(()),
275 Ok(_) => Err(Error::Nak),
276 Err(e) => Err(e),
277 }
278 }
279
280 pub fn select(&mut self, atqa: &AtqA) -> Result<Uid, Error<E>> {
283 if (atqa.bytes[0] & 0b00011111).count_ones() != 1 {
285 return Err(Error::Proprietary);
286 }
287
288 self.rmw(Register::CollReg, |b| b & !0x80)?;
290
291 let mut cascade_level: u8 = 0;
292 let mut uid_bytes: [u8; 10] = [0u8; 10];
293 let mut uid_idx: usize = 0;
294
295 let sak = 'cascade: loop {
296 let cmd = match cascade_level {
297 0 => picc::Command::SelCl1,
298 1 => picc::Command::SelCl2,
299 2 => picc::Command::SelCl3,
300 _ => unreachable!(),
301 };
302 let mut known_bits = 0;
303 let mut tx = [0u8; 9];
304 tx[0] = cmd as u8;
305
306 'anticollision: loop {
308 let tx_last_bits = known_bits % 8;
309 let tx_bytes = 2 + known_bits / 8;
310 let end = tx_bytes as usize + if tx_last_bits > 0 { 1 } else { 0 };
311 tx[1] = (tx_bytes << 4) + tx_last_bits;
312
313 match self.transceive::<5>(&tx[0..end], tx_last_bits, tx_last_bits) {
317 Ok(fifo_data) => {
318 fifo_data.copy_bits_to(&mut tx[2..=6], known_bits)?;
319 break 'anticollision;
320 }
321 Err(Error::Collision) => {
322 let coll_reg = self.read(Register::CollReg)?;
323 if coll_reg & (1 << 5) != 0 {
324 return Err(Error::Collision);
326 }
327 let mut coll_pos = coll_reg & 0x1F;
328 if coll_pos == 0 {
329 coll_pos = 32;
330 }
331 if coll_pos < known_bits {
332 return Err(Error::Collision);
334 }
335 let fifo_data = self.fifo_data::<5>()?;
336 fifo_data.copy_bits_to(&mut tx[2..=6], known_bits)?;
337 known_bits = coll_pos;
338
339 let count = known_bits % 8;
341 let check_bit = (known_bits - 1) % 8;
342 let index: usize =
343 1 + (known_bits / 8) as usize + if count != 0 { 1 } else { 0 };
344 tx[index] |= 1 << check_bit;
345 }
346 Err(e) => return Err(e),
347 }
348 }
349
350 tx[1] = 0x70; tx[6] = tx[2] ^ tx[3] ^ tx[4] ^ tx[5]; let crc = self.calculate_crc(&tx[..7])?;
355 tx[7..].copy_from_slice(&crc);
356
357 let rx = self.transceive::<3>(&tx[0..9], 0, 0)?;
358 if rx.valid_bytes != 3 || rx.valid_bits != 0 {
359 return Err(Error::IncompleteFrame);
360 }
361
362 let sak = picc::Sak::from(rx.buffer[0]);
363 let crc_a = &rx.buffer[1..];
364 let crc_verify = self.calculate_crc(&rx.buffer[..1])?;
365 if crc_a != crc_verify {
366 return Err(Error::Crc);
367 }
368
369 if !sak.is_complete() {
370 uid_bytes[uid_idx..uid_idx + 3].copy_from_slice(&tx[3..6]);
371 uid_idx += 3;
372 cascade_level += 1;
373 } else {
374 uid_bytes[uid_idx..uid_idx + 4].copy_from_slice(&tx[2..6]);
375 break 'cascade sak;
376 }
377 };
378
379 match cascade_level {
380 0 => Ok(Uid::Single(GenericUid {
381 bytes: uid_bytes[0..4].try_into().unwrap(),
382 sak,
383 })),
384 1 => Ok(Uid::Double(GenericUid {
385 bytes: uid_bytes[0..7].try_into().unwrap(),
386 sak,
387 })),
388 2 => Ok(Uid::Triple(GenericUid {
389 bytes: uid_bytes,
390 sak,
391 })),
392 _ => unreachable!(),
393 }
394 }
395
396 pub fn stop_crypto1(&mut self) -> Result<(), Error<E>> {
400 self.rmw(Register::Status2Reg, |b| b & !0x08)
401 }
402
403 pub fn mf_authenticate(
408 &mut self,
409 uid: &Uid,
410 block: u8,
411 key: &MifareKey,
412 ) -> Result<(), Error<E>> {
413 self.command(Command::Idle)?;
415 self.write(Register::ComIrqReg, 0x7f)?;
417 self.fifo_flush()?;
419 self.write(Register::BitFramingReg, 0)?;
421
422 let mut tx_buffer = [0u8; 12];
423 tx_buffer[0] = picc::Command::MfAuthKeyA as u8;
424 tx_buffer[1] = block;
425 tx_buffer[2..8].copy_from_slice(key);
426 match uid {
427 Uid::Single(u) => tx_buffer[8..12].copy_from_slice(&u.bytes[0..4]),
428 Uid::Double(u) => tx_buffer[8..12].copy_from_slice(&u.bytes[0..4]),
429 Uid::Triple(u) => tx_buffer[8..12].copy_from_slice(&u.bytes[0..4]),
430 };
431 self.write_many(Register::FIFODataReg, &tx_buffer)?;
433
434 self.command(Command::MFAuthent)?;
436
437 let mut irq;
438 loop {
439 irq = self.read(Register::ComIrqReg)?;
440
441 if irq & (ERR_IRQ | IDLE_IRQ) != 0 {
442 break;
443 } else if irq & TIMER_IRQ != 0 {
444 return Err(Error::Timeout);
445 }
446 }
447
448 self.check_error_register()?;
449 Ok(())
450 }
451
452 pub fn mf_read(&mut self, block: u8) -> Result<[u8; 16], Error<E>> {
456 let mut tx = [picc::Command::MfRead as u8, block, 0u8, 0u8];
457
458 let crc = self.calculate_crc(&tx[0..2])?;
459 tx[2..].copy_from_slice(&crc);
460
461 let rx = self.transceive::<18>(&tx, 0, 0)?.buffer;
462
463 let crc = self.calculate_crc(&rx[..16])?;
465 if crc != rx[16..] {
466 return Err(Error::Crc);
467 }
468 Ok(rx[..16].try_into().unwrap())
469 }
470
471 pub fn mf_write(&mut self, block: u8, data: [u8; 16]) -> Result<(), Error<E>> {
475 let mut cmd = [picc::Command::MfWrite as u8, block, 0, 0];
476 let crc = self.calculate_crc(&cmd[0..2])?;
477 cmd[2..].copy_from_slice(&crc);
478 let fifo_data = self.transceive::<1>(&cmd, 0, 0)?;
479 if fifo_data.valid_bytes != 1 || fifo_data.valid_bits != 4 {
480 return Err(Error::Nak);
481 }
482
483 let mut tx = [0u8; 18];
484 let crc = self.calculate_crc(&data)?;
485 tx[..16].copy_from_slice(&data);
486 tx[16..].copy_from_slice(&crc);
487 let fifo_data = self.transceive::<1>(&tx, 0, 0)?;
488 if fifo_data.valid_bytes != 1 || fifo_data.valid_bits != 4 {
489 return Err(Error::Nak);
490 }
491
492 Ok(())
493 }
494
495 pub fn version(&mut self) -> Result<u8, Error<E>> {
497 self.read(Register::VersionReg)
498 }
499
500 pub fn new_card_present(&mut self) -> Result<AtqA, Error<E>> {
502 self.write(Register::TxModeReg, 0x00)?;
503 self.write(Register::RxModeReg, 0x00)?;
504 self.write(Register::ModWidthReg, 0x26)?;
505
506 self.reqa()
507 }
508
509 pub fn set_antenna_gain(&mut self, gain: RxGain) -> Result<(), Error<E>> {
514 self.write(Register::RFCfgReg, gain.into())
515 }
516
517 pub fn transceive<const RX: usize>(
525 &mut self,
526 tx_buffer: &[u8],
528 tx_last_bits: u8,
530 rx_align_bits: u8,
532 ) -> Result<FifoData<RX>, Error<E>>
533 where
534 [u8; RX]: Sized,
535 {
536 self.command(Command::Idle)?;
538
539 self.write(Register::ComIrqReg, 0x7f)?;
541
542 self.fifo_flush()?;
544
545 self.write_many(Register::FIFODataReg, tx_buffer)?;
547
548 self.command(Command::Transceive)?;
550
551 self.write(
553 Register::BitFramingReg,
554 (1 << 7) | ((rx_align_bits & 0b0111) << 4) | (tx_last_bits & 0b0111),
555 )?;
556
557 loop {
560 let irq = self.read(Register::ComIrqReg)?;
561
562 if irq & (RX_IRQ | ERR_IRQ | IDLE_IRQ) != 0 {
563 break;
564 } else if irq & TIMER_IRQ != 0 {
565 return Err(Error::Timeout);
566 }
567 }
568
569 self.check_error_register()?;
570 self.fifo_data()
571 }
572}
573
574impl<E, COMM: Interface<Error = E>, S: State> Mfrc522<COMM, S> {
576 fn calculate_crc(&mut self, data: &[u8]) -> Result<[u8; 2], Error<E>> {
577 self.command(Command::Idle)?;
579
580 self.write(Register::DivIrqReg, 1 << 2)?;
582
583 self.fifo_flush()?;
585
586 self.write_many(Register::FIFODataReg, data)?;
588
589 self.command(Command::CalcCRC)?;
590
591 let mut irq;
593 for _ in 0..5000 {
594 irq = self.read(Register::DivIrqReg)?;
595
596 if irq & CRC_IRQ != 0 {
597 self.command(Command::Idle)?;
598 let crc = [
599 self.read(Register::CRCResultRegLow)?,
600 self.read(Register::CRCResultRegHigh)?,
601 ];
602
603 return Ok(crc);
604 }
605 }
606 Err(Error::Timeout)
607 }
608
609 fn check_error_register(&mut self) -> Result<(), Error<E>> {
610 let err = self.read(Register::ErrorReg)?;
611
612 if err & PROTOCOL_ERR != 0 {
613 Err(Error::Protocol)
614 } else if err & PARITY_ERR != 0 {
615 Err(Error::Parity)
616 } else if err & CRC_ERR != 0 {
617 Err(Error::Crc)
618 } else if err & COLL_ERR != 0 {
619 Err(Error::Collision)
620 } else if err & BUFFER_OVFL != 0 {
621 Err(Error::BufferOverflow)
622 } else if err & TEMP_ERR != 0 {
623 Err(Error::Overheating)
624 } else if err & WR_ERR != 0 {
625 Err(Error::Wr)
626 } else {
627 Ok(())
628 }
629 }
630
631 fn fifo_data<const RX: usize>(&mut self) -> Result<FifoData<RX>, Error<E>> {
633 let mut buffer = [0u8; RX];
634 let mut valid_bytes = 0;
635 let mut valid_bits = 0;
636
637 if RX > 0 {
638 valid_bytes = self.read(Register::FIFOLevelReg)? as usize;
639 if valid_bytes > RX {
640 return Err(Error::NoRoom);
641 }
642 if valid_bytes > 0 {
643 self.read_many(Register::FIFODataReg, &mut buffer[0..valid_bytes])?;
644 valid_bits = (self.read(Register::ControlReg)? & 0x07) as usize;
645 }
646 }
647
648 Ok(FifoData {
649 buffer,
650 valid_bytes,
651 valid_bits,
652 })
653 }
654
655 fn fifo_flush(&mut self) -> Result<(), Error<E>> {
657 self.write(Register::FIFOLevelReg, FLUSH_BUFFER)
658 }
659
660 fn command(&mut self, command: Command) -> Result<(), Error<E>> {
662 self.write(Register::CommandReg, command.into())
663 }
664
665 fn reset(&mut self) -> Result<(), Error<E>> {
667 self.command(Command::SoftReset)?;
668 while self.read(Register::CommandReg)? & POWER_DOWN != 0 {}
669 Ok(())
670 }
671}
672
673impl<E, COMM: Interface<Error = E>, S: State> Mfrc522<COMM, S> {
675 fn read(&mut self, reg: Register) -> Result<u8, Error<E>> {
676 self.comm.read(reg).map_err(Error::Comm)
677 }
678
679 fn read_many<'b>(&mut self, reg: Register, buffer: &'b mut [u8]) -> Result<&'b [u8], Error<E>> {
680 self.comm.read_many(reg, buffer).map_err(Error::Comm)
681 }
682
683 fn write(&mut self, reg: Register, val: u8) -> Result<(), Error<E>> {
684 self.comm.write(reg, val).map_err(Error::Comm)
685 }
686
687 fn write_many(&mut self, reg: Register, bytes: &[u8]) -> Result<(), Error<E>> {
688 self.comm.write_many(reg, bytes).map_err(Error::Comm)
689 }
690
691 fn rmw<F>(&mut self, reg: Register, f: F) -> Result<(), Error<E>>
692 where
693 F: FnOnce(u8) -> u8,
694 {
695 self.comm.rmw(reg, f).map_err(Error::Comm)
696 }
697}
698
699#[derive(Debug, PartialEq)]
701pub struct FifoData<const L: usize> {
702 pub buffer: [u8; L],
704 pub valid_bytes: usize,
706 pub valid_bits: usize,
708}
709
710impl<const L: usize> FifoData<L> {
711 fn copy_bits_to<E>(&self, dst: &mut [u8], dst_valid_bits: u8) -> Result<u8, Error<E>> {
715 if self.valid_bytes == 0 {
716 return Ok(dst_valid_bits);
718 }
719
720 let dst_valid_bytes = dst_valid_bits / 8;
721 let dst_valid_last_bits = dst_valid_bits % 8;
722 let mask: u8 = 0xFF << dst_valid_last_bits;
723 let mut idx = dst_valid_bytes as usize;
724 dst[idx] = (self.buffer[0] & mask) | (dst[idx] & !mask);
725 idx += 1;
726 let len = self.valid_bytes - 1;
727 if len + idx > dst.len() {
728 return Err(Error::NoRoom);
730 }
731 if len > 0 {
732 dst[idx..idx + len].copy_from_slice(&self.buffer[1..=len]);
733 }
734 Ok(dst_valid_bits + (len * 8) as u8 + self.valid_bits as u8)
735 }
736}