File: connect.rs

package info (click to toggle)
rust-pcsc 2.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 184 kB
  • sloc: makefile: 4
file content (105 lines) | stat: -rw-r--r-- 4,353 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use pcsc::*;

fn main() {
    // Get a context.
    let ctx = Context::establish(Scope::User).expect("failed to establish context");

    // List connected readers.
    let mut readers_buf = [0; 2048];
    let readers = ctx
        .list_readers(&mut readers_buf)
        .expect("failed to list readers")
        .collect::<Vec<_>>();
    println!("Readers: {:?}", readers);

    if readers.is_empty() {
        return;
    }

    {
        // Try to connect to a card in the first reader.
        let mut card = ctx
            .connect(readers[0], ShareMode::Shared, Protocols::ANY)
            .expect("failed to connect to card");

        {
            // Start an exclusive transaction (not required -- can work on card directly).
            let tx = card.transaction().expect("failed to begin card transaction");

            // Get the card status.
            let (names_len, _atr_len) = tx.status2_len().expect("failed to get the status length");
            let mut names_buf = vec![0; names_len];
            let mut atr_buf = [0; MAX_ATR_SIZE];
            let status = tx
                .status2(&mut names_buf, &mut atr_buf)
                .expect("failed to get card status");
            println!("Status from status: {:?}", status.status());
            println!(
                "Reader names from status: {:?}",
                status.reader_names().collect::<Vec<_>>()
            );
            if let Some(protocol) = status.protocol2() {
                println!("Protocol from status: {:?}", protocol);
            } else {
                println!("Protocol from status: directly connected");
            }
            println!("ATR from status: {:?}", status.atr());

            // Send some harmless APDU to the card.
            if let Some(_) = status.protocol2() {
                let apdu = b"\x00\xa4\x04\x00\x08\x31\x54\x49\x43\x2e\x49\x43\x41";
                let mut rapdu_buf = [0; MAX_BUFFER_SIZE];
                let rapdu = tx
                    .transmit(apdu, &mut rapdu_buf)
                    .expect("failed to transmit APDU to card");
                println!("RAPDU: {:?}", rapdu);
            }

            // Get the card's ATR.
            let mut atr_buf = [0; MAX_ATR_SIZE];
            let atr = tx
                .get_attribute(Attribute::AtrString, &mut atr_buf)
                .expect("failed to get ATR attribute");
            println!("ATR from attribute: {:?}", atr);

            // Get some attribute.
            let mut ifd_version_buf = [0; 4];
            let ifd_version = tx
                .get_attribute(Attribute::VendorIfdVersion, &mut ifd_version_buf)
                .expect("failed to get vendor IFD version attribute");
            println!("Vendor IFD version: {:?}", ifd_version);

            // Get some other attribute.
            // This time we allocate a buffer of the needed length.
            let vendor_name_len = tx
                .get_attribute_len(Attribute::VendorName)
                .expect("failed to get the vendor name attribute length");
            let mut vendor_name_buf = vec![0; vendor_name_len];
            let vendor_name = tx
                .get_attribute(Attribute::VendorName, &mut vendor_name_buf)
                .expect("failed to get vendor name attribute");
            println!("Vendor name: {}", std::str::from_utf8(vendor_name).unwrap());

            // Can either end explicity, which allows error handling,
            // and setting the disposition method, or leave it to drop, which
            // swallows any error and hardcodes LeaveCard.
            tx.end(Disposition::LeaveCard)
                .map_err(|(_, err)| err)
                .expect("failed to end transaction");
        }

        // Can either disconnect explicity, which allows error handling,
        // and setting the disposition method, or leave it to drop, which
        // swallows any error and hardcodes ResetCard.
        card.disconnect(Disposition::ResetCard)
            .map_err(|(_, err)| err)
            .expect("failed to disconnect from card");
    }

    // Can either release explicity, which allows error handling,
    // or leave it to drop, which swallows any error.
    // The function fails if there are any live clones.
    ctx.release()
        .map_err(|(_, err)| err)
        .expect("failed to release context");
}