@@ -9,19 +9,82 @@ SPDX-License-Identifier: GPL-3.0-or-later
99
1010Rust library to manipulate ISO/IEC 14443 data.
1111
12- ## Fontionalities
12+ ## Functionalities
1313
1414- [x] Type-A
1515 - [x] iso14443-3: REQA/WUPA/ATQA/ANTICOLLISION/SELECT/SAK/HLTA
16- - [x] CRC_A checks
16+ - [x] iso14443-3: CRC_A checks (hardware-accelerated or software)
17+ - [x] iso14443-3: PCD activation with anticollision cascade (4/7/10-byte UIDs)
1718 - [x] iso14443-4: RATS/ATS/PPS
1819 - [x] iso14443-4: PCB (Protocol Control Byte)
1920 - [x] iso14443-4: Block format (I-block, R-block, S-block)
20- - [x] iso14443-4: Block chaining
21- - [x] iso14443-4: Protocol state machine
21+ - [x] iso14443-4: PCD transport layer (APDU exchange, chaining, WTX, error recovery, DESELECT)
22+ - [x] iso14443-4: Generic block protocol handler (reusable for PCD and PICC)
2223- [ ] Type-B
2324
24- ## Example Usage
25+ ## Usage
26+
27+ ``` rust
28+ use iso14443 :: type_a :: {
29+ activation :: {activate, ActivationError },
30+ pcd :: {Pcd , PcdError },
31+ vec :: FrameVec ,
32+ Cid , Frame , Fsdi , PcdTransceiver ,
33+ };
34+
35+ /// Dummy PCD transceiver — replace with your real hardware driver
36+ /// (e.g. SPI to an NXP PN532 or ST25R3916).
37+ struct MyTransceiver ;
38+
39+ #[derive(Debug )]
40+ struct MyError ;
41+
42+ impl PcdTransceiver for MyTransceiver {
43+ type Error = MyError ;
44+
45+ fn transceive (& mut self , _frame : & Frame ) -> Result <FrameVec , MyError > {
46+ // Send frame bytes over SPI/I2C/UART, return the PICC response.
47+ todo! (" implement for your hardware" )
48+ }
49+
50+ fn enable_hw_crc (& mut self ) -> Result <(), MyError > {
51+ // Enable hardware CRC if the chip supports it.
52+ // Return Err to fall back to software CRC.
53+ Err (MyError )
54+ }
55+ }
56+
57+ fn talk_to_card (t : & mut MyTransceiver ) -> Result <(), Box <dyn std :: error :: Error >> {
58+ // ISO14443-3A: detect tag, resolve UID
59+ let activation = activate (t ). map_err (| e | format! (" {e:?}" ))? ;
60+ println! (" UID: {:02x?}" , activation . uid. as_slice ());
61+
62+ // Only proceed to ISO14443-4 if the tag supports it
63+ if ! activation . sak. iso14443_4_compliant {
64+ println! (" Tag does not support ISO14443-4" );
65+ return Ok (());
66+ }
67+
68+ // ISO14443-4: RATS/ATS negotiation, open a session
69+ let cid = Cid :: new (0 ). unwrap ();
70+ let (mut pcd , ats ) = Pcd :: connect (t , Fsdi :: Fsd256 , cid )
71+ . map_err (| e | format! (" {e:?}" ))? ;
72+ println! (" ATS: {ats:?}" );
73+
74+ // Exchange an APDU (e.g. SELECT application)
75+ let select_apdu = [0x00 , 0xA4 , 0x04 , 0x00 , 0x07 ,
76+ 0xD2 , 0x76 , 0x00 , 0x00 , 0x85 , 0x01 , 0x01 , 0x00 ];
77+ let response = pcd . exchange (& select_apdu )
78+ . map_err (| e | format! (" {e:?}" ))? ;
79+ println! (" Response: {:02x?}" , response . as_slice ());
80+
81+ // Clean up
82+ pcd . deselect (). map_err (| e | format! (" {e:?}" ))? ;
83+ Ok (())
84+ }
85+ ```
86+
87+ ## CLI Parser
2588
2689An example is provided to parse raw data from the ISO14443 protocol:
2790
0 commit comments