connect/
connect.rs

1use pcsc::*;
2
3fn main() {
4    // Get a context.
5    let ctx = Context::establish(Scope::User).expect("failed to establish context");
6
7    // List connected readers.
8    let mut readers_buf = [0; 2048];
9    let readers = ctx
10        .list_readers(&mut readers_buf)
11        .expect("failed to list readers")
12        .collect::<Vec<_>>();
13    println!("Readers: {:?}", readers);
14
15    if readers.is_empty() {
16        return;
17    }
18
19    {
20        // Try to connect to a card in the first reader.
21        let mut card = ctx
22            .connect(readers[0], ShareMode::Shared, Protocols::ANY)
23            .expect("failed to connect to card");
24
25        {
26            // Start an exclusive transaction (not required -- can work on card directly).
27            let tx = card.transaction().expect("failed to begin card transaction");
28
29            // Get the card status.
30            let (names_len, _atr_len) = tx.status2_len().expect("failed to get the status length");
31            let mut names_buf = vec![0; names_len];
32            let mut atr_buf = [0; MAX_ATR_SIZE];
33            let status = tx
34                .status2(&mut names_buf, &mut atr_buf)
35                .expect("failed to get card status");
36            println!("Status from status: {:?}", status.status());
37            println!(
38                "Reader names from status: {:?}",
39                status.reader_names().collect::<Vec<_>>()
40            );
41            if let Some(protocol) = status.protocol2() {
42                println!("Protocol from status: {:?}", protocol);
43            } else {
44                println!("Protocol from status: directly connected");
45            }
46            println!("ATR from status: {:?}", status.atr());
47
48            // Send some harmless APDU to the card.
49            if let Some(_) = status.protocol2() {
50                let apdu = b"\x00\xa4\x04\x00\x08\x31\x54\x49\x43\x2e\x49\x43\x41";
51                let mut rapdu_buf = [0; MAX_BUFFER_SIZE];
52                let rapdu = tx
53                    .transmit(apdu, &mut rapdu_buf)
54                    .expect("failed to transmit APDU to card");
55                println!("RAPDU: {:?}", rapdu);
56            }
57
58            // Get the card's ATR.
59            let mut atr_buf = [0; MAX_ATR_SIZE];
60            let atr = tx
61                .get_attribute(Attribute::AtrString, &mut atr_buf)
62                .expect("failed to get ATR attribute");
63            println!("ATR from attribute: {:?}", atr);
64
65            // Get some attribute.
66            let mut ifd_version_buf = [0; 4];
67            let ifd_version = tx
68                .get_attribute(Attribute::VendorIfdVersion, &mut ifd_version_buf)
69                .expect("failed to get vendor IFD version attribute");
70            println!("Vendor IFD version: {:?}", ifd_version);
71
72            // Get some other attribute.
73            // This time we allocate a buffer of the needed length.
74            let vendor_name_len = tx
75                .get_attribute_len(Attribute::VendorName)
76                .expect("failed to get the vendor name attribute length");
77            let mut vendor_name_buf = vec![0; vendor_name_len];
78            let vendor_name = tx
79                .get_attribute(Attribute::VendorName, &mut vendor_name_buf)
80                .expect("failed to get vendor name attribute");
81            println!("Vendor name: {}", std::str::from_utf8(vendor_name).unwrap());
82
83            // Can either end explicity, which allows error handling,
84            // and setting the disposition method, or leave it to drop, which
85            // swallows any error and hardcodes LeaveCard.
86            tx.end(Disposition::LeaveCard)
87                .map_err(|(_, err)| err)
88                .expect("failed to end transaction");
89        }
90
91        // Can either disconnect explicity, which allows error handling,
92        // and setting the disposition method, or leave it to drop, which
93        // swallows any error and hardcodes ResetCard.
94        card.disconnect(Disposition::ResetCard)
95            .map_err(|(_, err)| err)
96            .expect("failed to disconnect from card");
97    }
98
99    // Can either release explicity, which allows error handling,
100    // or leave it to drop, which swallows any error.
101    // The function fails if there are any live clones.
102    ctx.release()
103        .map_err(|(_, err)| err)
104        .expect("failed to release context");
105}