Sample code for 30+ languages & platforms
Zig

PC/SC Get Card UID

See more SCard Examples

Sends the APDU command to get a card's UID.

Chilkat Zig Downloads

Zig
const std = @import("std");
const chilkat = @import("chilkat");

pub fn main(init: std.process.Init) !void {
    const alloc = init.arena.allocator();

    var success: bool = false;

    // This example requires the Chilkat API to have been previously unlocked.
    // See Global Unlock Sample for sample code.

    const scard = try chilkat.SCard.init();
    defer scard.deinit();

    // First establish a context to the PC/SC Resource Manager
    success = if (scard.establishContext("user")) true else |_| false;
    if (!success) {
        std.debug.print("{s}\n", .{try scard.getLastErrorText(alloc)});
        return;
    }

    // Use your own smart card reader name here.
    success = scard.connect("ACS ACR122 0", "shared", "no_preference");
    if (!success) {
        std.debug.print("{s}\n", .{try scard.getLastErrorText(alloc)});
        return;
    }

    std.debug.print("Connected reader: {s}\n", .{try scard.getConnectedReader(alloc)});
    std.debug.print("Active protocol: {s}\n", .{try scard.getActiveProtocol(alloc)});
    std.debug.print("ATR: {s}\n", .{try scard.getCardAtr(alloc)});
    std.debug.print("Reader Status: {s}\n", .{try scard.getReaderStatus(alloc)});

    //  Send the APDU command 0xFF, 0xCA, 0x00, 0x00, 0x00
    const bd_recv = try chilkat.BinData.init();
    defer bd_recv.deinit();
    if (scard.transmitHex(try scard.getActiveProtocol(alloc), "FFCA000000", bd_recv, 32)) {
        std.debug.print("Received: {s}\n", .{try bd_recv.getEncoded(alloc, "hex")});

        // The UID is the returned data without the final 2 bytes.
        const num_bytes = bd_recv.getNumBytes();
        if (num_bytes > 2) {
            std.debug.print("UID: {s}\n", .{try bd_recv.getEncodedChunk(alloc, 0, num_bytes - 2, "hex")});
        }
    } else |_| {
        std.debug.print("{s}\n", .{try scard.getLastErrorText(alloc)});
    }

    // Disconnect from this reader.
    scard.disconnect("leave") catch {
        std.debug.print("{s}\n", .{try scard.getLastErrorText(alloc)});
    };

    // Applications should always release the context when finished.
    scard.releaseContext() catch {
        std.debug.print("{s}\n", .{try scard.getLastErrorText(alloc)});
    };
}