Smart Card Manager C++

Namespaces

 dpySCM
 Deepsy SCM namespace that includes the different enums, structs or method signatures that should be used.
 

Classes

class  SCM
 Allows to interact with a platform manager. More...
 

Detailed Description

Smart Card Manager API related documentation

A quick overview of basic Smart Card Manager API capabilities and examples is given.
If you find Smart Card Manager API useful and would like to know more details, please check out further sections. of the Smart Card Manager API documentation or contact the Deepsy platform team.

Functionalities

  • Get devices: Asynchronous operation for getting connected devices.
  • Get readers: Asynchronous operation for getting readers connected to a device.
  • Add keys: Asynchronous operation for adding keys to a specific device.These keys can be loaded from json file or C++ structure.
  • Get keys: Asynchronous operation for getting keys from specific device.
  • Remove keys: Asynchronous operation for removing keys from specific device.
  • Card operation: Asynchronous operation for any operation to any smart card type.
  • New card events: Subscribe to new card events, available or removed smart cards.
  • Read: Synchronous operation for reading blocks or pages of Mifare Classic or Ultralight smart cards.
  • Write: Synchronous operation for writing blocks or pages of Mifare Classic or Ultralight smart cards.
  • APDU Exchange: Synchronous operation for exchanging APDUs to smart cards.
  • Get media profiles: Asynchronous operation used to retrieve the available media profiles for a specific device.
  • Add media profiles: Asynchronous operation used to add a media profile for a specific device.These media profiles can be loaded from json file or C++ structure.
  • Play media profiles: Asynchronous operation playing media profiles in device.
  • Get/Set PCI Data Security Standard reboot time
  • PCI reboot events: Subscribe to PCI reboot events.
  • Get Ultralight counter: Asynchronous and synchronous operation for getting the ultralight counter.
  • Increment Ultralight counter: Asynchronous and synchronous operation for incrementing the ultralight counter.
  • Pass through operation: Asynchronous/Synchronous operation used to send commands directly to the device via pass-through .
  • Upgrade status: Every upgrade status change.
  • Request charge for EMV: Request a EMV transaction.
  • Confirm a EMV transaction: Confirm the last EMV transaction.
  • Set payment application status: Set payment app status.
  • Get payment application information: Get the current payment application information.
  • Get payment application configuration: Get the current payment application configuration.
  • Get every transaction EMV result: Get every EMV transaction result.
  • Reboot a device, The reboot can be SOFT (only application) or HARD (complete device).
  • Force connection: when device has lost internet connection, payment gateway connection can be force.

Examples

  • Getting available devices

    #include <dpy/scmApi.h>
    #include <iostream>
    void print_device_list(boost::system::error_code& ec, const dpySCM::Device& rDevice)
    {
    if (ec.value() == 0) {
    std::cout << "\rSmart Card Manager device list: " << std::endl;
    for (std::vector<std::string>::size_type i = 0; i != rDevice.device.size(); i++) {
    std::cout << "\r- " << rDevice.device[i] << std::endl;
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    int main(int argc, char *argv[])
    {
    SCM scm;
    scm.asyncGetDevices(print_device_list);
    }

  • Obtaining readers from device

    #include <dpy/scmApi.h>
    #include <iostream>
    #include <boost/thread.hpp>
    static bool get_readers = false;
    static bool reset_sam = false;
    void print_readers_list(boost::system::error_code& ec, const dpySCM::DeviceReaderList& deviceReaderList)
    {
    if (ec.value() == 0) {
    std::cout << "\rSmart Card Manager '" << deviceReaderList.deviceId << "' reader list:" << std::endl;
    for (std::vector<std::string>::size_type i = 0; i != deviceReaderList.readers.size(); i++) {
    std::cout << "\r- " << deviceReaderList.readers[i].deviceid << ", ";
    std::cout << deviceReaderList.readers[i].socket << ", ";
    std::cout << deviceReaderList.readers[i].samuid << std::endl;
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    get_readers = true;
    }
    void result_sync_handler(boost::system::error_code ec)
    {
    if (ec) {
    std::cout << "\rError : " << ec.message() << std::endl;
    } else {
    std::cout << "\rSynchronous operation performed successfully" << std::endl;
    }
    reset_sam = true;
    }
    auto main(int argc, char *argv[]) -> int
    {
    SCM scm;
    scm.asyncGetReaders("Ux410",print_readers_list);
    while ( !get_readers ) {
    boost::this_thread::sleep_for(boost::chrono::seconds(2));
    }
    scm.asyncResetSamSlot("Ux410", (dpySCM::SamSlot)1, result_sync_handler);
    while ( !reset_sam ) {
    boost::this_thread::sleep_for(boost::chrono::seconds(2));
    }
    reset_sam = false;
    scm.asyncResetSamSlot("Ux410", (dpySCM::SamSlot)2, result_sync_handler);
    while ( !reset_sam ) {
    boost::this_thread::sleep_for(boost::chrono::seconds(2));
    }
    return 0;
    }

  • Read smart card example
    Complete example for reading the blocks/pages 4 and 5 for a Mifare Classic or an Ultralight. It tries to set the keys if they have not been done before. It have been set a default keys 0x'FF'

    #include <dpy/scmApi.h>
    #include <iostream>
    static SCM scm;
    dpySCM::DeviceKeys set_keys(std::string deviceid)
    {
    std::cout << "\rSetting keys to: " << deviceid << std::endl;
    keygroup.deviceId = deviceid;
    dpySCM::KeyGroup keygroup1;
    keygroup1.priority = 0;
    dpySCM::Key keys_g1;
    keys_g1.index = 0;
    keys_g1.keys = "FFFFFFFFFFFF";
    keygroup1.key.push_back(keys_g1);
    keys_g1.index = 1;
    keygroup1.key.push_back(keys_g1);
    keys_g1.index = 2;
    keygroup1.key.push_back(keys_g1);
    keys_g1.index = 3;
    keygroup1.key.push_back(keys_g1);
    keygroup.keys.push_back(keygroup1);
    return keygroup;
    }
    void print_readers_list(boost::system::error_code& ec, const dpySCM::DeviceReaderList& deviceReaderList)
    {
    if (ec.value() == 0) {
    std::cout << "\rSmart Card Manager '" << deviceReaderList.deviceId << "' reader list:" << std::endl;
    for (std::vector<std::string>::size_type i = 0; i != deviceReaderList.readers.size(); i++) {
    std::cout << "\r- " << deviceReaderList.readers[i].deviceid << ", ";
    std::cout << deviceReaderList.readers[i].socket << ", ";
    std::cout << deviceReaderList.readers[i].samuid << std::endl;
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    void confirmation_handler_function(boost::system::error_code& ec)
    {
    if (ec.value() == 0) {
    std::cout << "\rSmart Card Manager sets key successfully'" << std::endl;
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    void print_keys(boost::system::error_code& ec, dpySCM::DeviceKeys deviceKeys)
    {
    if (ec.value() == 0) {
    if (deviceKeys.keys.size() > 0) {
    std::cout << "\rSmart Card Manager gets key successfully for: '" << deviceKeys.deviceId << std::endl;
    std::vector<dpySCM::KeyGroup>::iterator it;
    for (it = deviceKeys.keys.begin(); it != deviceKeys.keys.end(); ++it) {
    std::cout << "\rKeys with priority: " << it->priority << std::endl;
    std::vector<dpySCM::Key>::iterator it2;
    for (it2 = it->key.begin(); it2 != it->key.end(); ++it2) {
    std::cout << "\rKey index: " << it2->index << " value: " << it2->keys << std::endl;
    }
    }
    } else {
    std::cout << "\rThere are no keys in " << deviceKeys.deviceId << " device" << std::endl;
    /* ADD KEYS FOR THIS DEVICE CONNECTED */
    scm.asyncAddKeys(set_keys(deviceKeys.deviceId), confirmation_handler_function);
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    void print_device_list(boost::system::error_code& ec, const dpySCM::Device& rDevice)
    {
    if (ec.value() == 0) {
    std::cout << "\rSmart Card Manager device list: " << std::endl;
    for (std::vector<std::string>::size_type i = 0; i != rDevice.device.size(); i++) {
    /* GET THE KEYS FOR THIS DEVICE */
    scm.asyncGetKeys(rDevice.device[i], print_keys);
    /* GET READERS FOR THIS DEVICE */
    std::cout << "\r- " << rDevice.device[i] << std::endl;
    scm.asyncGetReaders(rDevice.device[i], print_readers_list);
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    void print_transaction(boost::system::error_code& ec, dpySCM::TransactionDevice TransactionDevice)
    {
    if (ec.value() == 0) {
    std::cout << "\rSmart Card Manager device: " << TransactionDevice.deviceId << std::endl;
    std::vector<dpySCM::CardOperation>::iterator it;
    for (it = TransactionDevice.operation.begin(); it != TransactionDevice.operation.end(); ++it) {
    std::cout << "\rUID: " << it->uid << "\rIndex: " << it->index << std::endl;
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    void new_card_event(boost::system::error_code& ec, const std::string& deviceId, dpySCM::CardEvent cardEvent)
    {
    if (ec.value() == 0) {
    if (cardEvent.event == dpySCM::REMOVED) {
    std::cout << "\rThe card: " << cardEvent.cardinfo.uid << " was removed" << std::endl;
    } else if (cardEvent.event == dpySCM::ADDED && cardEvent.cardinfo.collision == false) {
    std::cout << "\rNew card available: " << cardEvent.cardinfo.uid << " in the reader: " << cardEvent.cardinfo.readerName << " of device: " << deviceId << std::endl;
    /* -------------------- Synchronous request ---------------------------------- */
    std::list<dpySCM::Data> dataList;
    data.index = 4;
    dataList.push_back(data);
    data.index = 5;
    dataList.push_back(data);
    ec = scm.read(deviceId, cardEvent.cardinfo.uid, dataList);
    if (ec.value() == 0) {
    std::list<dpySCM::Data>::iterator it;
    for (it = dataList.begin(); it != dataList.end(); ++it) {
    std::cout << "\rSuccessful read: " << cardEvent.cardinfo.uid << std::endl;
    std::cout << "\rThe index: " << it->index << " has the value: " << it->buffer << std::endl;
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    /* ----------------------------------------------------------------------------- */
    /* -------------------- Asynchronous request -----------------------------------
    dpySCM::TransactionDevice operationDevice;
    operationDevice.deviceId = deviceId;
    dpySCM::CardOperation operation;
    operation.uid = cardEvent.cardinfo.uid;
    operation.operationType = dpySCM::READ;
    operation.index = 4;
    operation.priority = 0;
    operationDevice.operation.push_back(operation);
    scm.asyncCardOperation(operationDevice, print_transaction);
    ------------------------------------------------------------------------------- */
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    int main(int argc, char *argv[])
    {
    scm.asyncGetDevices(print_device_list);
    scm.newCardEvent_S(new_card_event);
    while (1){
    }
    }

  • APDU exchange with SAM
    Complete example for exchanging APDUs, in this case using a SAM card. Before sending any command, the program ask for SAMs connected, afterwards, if is given the example for synchronous and asynchronous operations.

    #include <dpy/scmApi.h>
    #include <iostream>
    volatile bool waiting = true;
    static SCM scm;
    void print_transaction(boost::system::error_code& ec, dpySCM::TransactionDevice TransactionDevice)
    {
    if (ec.value() == 0) {
    std::cout << "\rSmart Card Manager device: " << TransactionDevice.deviceId << std::endl;
    std::vector<dpySCM::CardOperation>::iterator it;
    for (it = TransactionDevice.operation.begin(); it != TransactionDevice.operation.end(); ++it) {
    dpySCM::ApduRxData apduRxData = it->rxData;
    std::cout << "\rUID: " << it->uid << "\tSW1: " << apduRxData.sw1 << "\tSW2: " << apduRxData.sw2 <<"\tResult: " << apduRxData.rxData << std::endl;
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    void print_readers_list(boost::system::error_code& ec, const dpySCM::DeviceReaderList& deviceReaderList)
    {
    if (ec.value() == 0) {
    std::cout << "\rSmart Card Manager '" << deviceReaderList.deviceId << "' reader list:" << std::endl;
    std::list<dpySCM::ApduTxData> apduTx;
    dpySCM::ApduTxData apduTxData;
    apduTxData.class_instruction = 0x90;
    apduTxData.instruction = 0x10;
    apduTxData.param1 = 0x00;
    apduTxData.param2 = 0x00;
    apduTxData.expectedResponseLen = 0x14;
    apduTx.push_back(apduTxData);
    for (std::vector<std::string>::size_type i = 0; i != deviceReaderList.readers.size(); i++) {
    std::cout << "\r- " << deviceReaderList.readers[i].deviceid << ", ";
    std::cout << deviceReaderList.readers[i].socket << ", ";
    std::cout << deviceReaderList.readers[i].samuid << std::endl;
    if ((deviceReaderList.readers[i].deviceid.find("SAMREADER") != std::string::npos) && (deviceReaderList.readers[i].samuid != "NA")) {
    /* -------------------------------------------- Synchronous request -----------------------------------------------------------
    std::list<dpySCM::ApduRxData> apduRx;
    error = scm.apduExchange(deviceReaderList.deviceId, deviceReaderList.readers[i].samuid, apduTx, apduRx);
    if (error.value() == 0) {
    std::list<dpySCM::ApduRxData>::iterator it;
    for (it = apduRx.begin(); it != apduRx.end(); it++) {
    char32_t SW1 = it->sw1;
    char32_t SW2 = it->sw2;
    std::string rxRawData = it->rxData;
    std::cout << "\rSW1: " << SW1 << "\tSW2: " << SW2 << "\tResult: " << rxRawData << std::endl;
    }
    } else {
    std::cout << "\rError while exchanging the APDU. Error: [" << error.value() << "] "<< ec.message() << std::endl;
    }
    ------------------------------------------------------------------------------------------------------------------------------- */
    /* -------------------------------------------- Asynchronous request ------------------------------------------------------------- */
    dpySCM::TransactionDevice operationDevice;
    operationDevice.deviceId = deviceReaderList.deviceId;
    operation.uid = deviceReaderList.readers[i].samuid;
    operation.priority = 0;
    operation.txData = apduTxData;
    operationDevice.operation.push_back(operation);
    scm.asyncCardOperation(operationDevice, print_transaction);
    /* ---------------------------------------------------------------------------------------------------------------------------------- */
    } else {
    std::cout << "\rThere is not a SAM reader" << std::endl;
    }
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    //waiting = false;
    }
    void print_device_list(boost::system::error_code& ec, const dpySCM::Device& rDevice)
    {
    if (ec.value() == 0) {
    std::cout << "\rSmart Card Manager device list: " << std::endl;
    for (std::vector<std::string>::size_type i = 0; i != rDevice.device.size(); i++) {
    /* GET READERS FOR THIS DEVICE */
    std::cout << "\r- " << rDevice.device[i] << std::endl;
    scm.asyncGetReaders(rDevice.device[i], print_readers_list);
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    int main(int argc, char *argv[])
    {
    scm.asyncGetDevices(print_device_list);
    while (waiting){
    }
    }

  • Play profile example

    #include <dpy/scmApi.h>
    #include <iostream>
    void result_sync_handler(boost::system::error_code ec)
    {
    if (ec) {
    std::cout << "\rError : " << ec.message() << std::endl;
    } else {
    std::cout << "\rSynchronous operation performed successfully" << std::endl;
    }
    }
    int main(int argc, char *argv[])
    {
    SCM scm;
    scm.asyncPlayProfile("verifone", "Default_OK", result_sync_handler);
    }

  • Pass-through example
    Example for sending commands synchronously via pass-through whenever a new card is added.

    #include <dpy/scmApi.h>
    #include <iostream>
    volatile bool waiting = true;
    static SCM scm;
    void card_event_handler(boost::system::error_code &ec, const std::string &deviceId, dpySCM::CardEvent cardEvent)
    {
    if (ec.value() == 0) {
    //Send a pass through command to the card that has been detected
    if (cardEvent.event == dpySCM::Event::ADDED) {
    std::cout << "Card with UID " << cardEvent.cardinfo.uid << " has been detected at device with id " << deviceId << ", reader " << cardEvent.cardinfo.readerName << std::endl;
    //Create the command or commands that want to be sent
    dpySCM::Command cmd_one;
    cmd_one.inRawData = "A50101000000";
    dpySCM::Command cmd_two;
    cmd_two.inRawData = "3901";
    //Fill the PassThrough structure containing the query
    dpySCM::PassThrough passThroughCmd;
    passThroughCmd.uid = cardEvent.cardinfo.uid;
    passThroughCmd.readerId = cardEvent.cardinfo.readerName;
    passThroughCmd.commands.push_back(cmd_one);
    passThroughCmd.commands.push_back(cmd_two);
    //Make a synchronous passThrough query
    std::cout << "Sending command [" << cmd_one.inRawData << "] and command [" << cmd_two.inRawData << "]" << std::endl;
    boost::system::error_code error_code = scm.passThrough(deviceId, passThroughCmd);
    if (error_code.value() == 0) {
    std::cout << "Pass through query was successful" << std::endl;
    int i = 1;
    for(auto &command: passThroughCmd.commands){
    std::cout << "\tCommand [" << i << "] " << std::endl;
    if (command.errorCode == 0) {
    std::cout << "\t\tPass through command was processed correctly. Command response: " << std::endl;
    std::cout << "\t\tBuffer is [" << command.outRawData << "]" << std::endl;
    } else {
    std::cout << "\t\tPass through command could not be processed, error " << command.errorCode << std::endl;
    }
    i++;
    std::cout << "\t\t-------------- " << std::endl;
    }
    } else {
    std::cout << "Pass through command error " << ec.message() << std::endl;
    }
    } else {
    std::cout << "Card with UID " << cardEvent.cardinfo.uid << " has been removed from device " << deviceId << std::endl;
    }
    } else {
    std::cout << "Error " << ec.message() << std::endl;
    }
    }
    int main(int argc, char *argv[])
    {
    //Listen to card events
    scm.newCardEvent_S(card_event_handler);
    std::cout << "Waiting for card events ... " << std::endl;
    while (waiting) {
    }
    }

  • Observer Pattern Example
    Demonstrating how to use the observer pattern to subscribe to Smart Card events.

    #include <dpyError.h>
    #include <dpy/scmApi.h>
    #include <iostream>
    #include <boost/bind.hpp>
    #include <boost/bind/placeholders.hpp>
    #include <boost/thread.hpp>
    #include <type_traits>
    #include <variant>
    #include <mutex>
    #include <condition_variable>
    {
    private:
    SCM scm;
    public:
    App() = default;
    ~App() = default;
    void start()
    {
    scm.subscribeReaderEvent(this);
    scm.subscribeDeviceListEvent(this);
    scm.subscribeDeviceEvent(this);
    }
    void finish()
    {
    scm.unsubscribeReaderEvent(this);
    scm.unsubscribeDeviceListEvent(this);
    scm.unsubscribeDeviceEvent(this);
    }
    void newSmartCard(boost::system::error_code& ec, const std::string& deviceId, dpySCM::CardEvent cardEvent) override
    {
    if (ec.value() == 0) {
    if (cardEvent.event == dpySCM::ADDED) {
    std::cout << "\rNew card available: " << cardEvent.cardinfo.uid
    << " Collision: " << cardEvent.cardinfo.collision
    << " Card Type: " << cardEvent.cardinfo.cardtype
    << " ATQA: " << cardEvent.cardinfo.atqa
    << " SAK: " << cardEvent.cardinfo.sak
    << " ATS: " << cardEvent.cardinfo.ats
    << " in the reader: " << cardEvent.cardinfo.readerName << " of device: " << deviceId << std::endl;
    } else {
    std::cout << "Card removed: " << cardEvent.cardinfo.uid << std::endl;
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    void chargeResult(boost::system::error_code& ec, dpySCM::DeviceChargeResult deviceChargeResult) override
    {
    std::cout << "\rNew charge result" << std::endl;
    }
    void deviceListEvent(boost::system::error_code& ec, const std::string& deviceId, dpySCM::Event deviceEvent) override
    {
    std::cout << "\r Device list notification" << std::endl;
    }
    void notifyPciReboot(boost::system::error_code& ec, dpySCM::DevicePciRebootTime& devicePciRebootTime) override
    {
    std::cout << "\r PCI Notification" << std::endl;
    }
    void newUpgradeStatus(boost::system::error_code& ec, dpySCM::DeviceUpgradeStatus& deviceUpgradeStatus) override
    {
    std::cout << "\r Upgrade status notification" << std::endl;
    }
    };
    auto main(int argc, char *argv[]) -> int
    {
    App app;
    app.start();
    std::cout << "\r Subscribe to events" << std::endl;
    boost::this_thread::sleep_for(boost::chrono::seconds(30));
    std::cout << "\r Unsubscribe to events" << std::endl;
    boost::this_thread::sleep_for(boost::chrono::seconds(30));
    std::cout << "\r Finish program" << std::endl;
    return [](){return 0;}();
    }

  • Manual Authentication Example
    Demonstrating how to authenticate, read and write using the manual mode

    #include <dpy/scmApi.h>
    #include <iostream>
    #include <boost/thread/thread.hpp>
    static SCM scm;
    static std::list<dpySCM::Data> readDataList;
    static std::list<dpySCM::Data> writeDataList;
    static std::list<dpySCM::Data> authDataList;
    void dataInitialization()
    {
    /*********** AUTHENTICATION ********************/
    authDataList.clear();
    dpySCM::Data authData;
    // Sector 4
    authData.index = 4;
    authData.buffer = "FFFFFFFFFFFF";
    authDataList.push_back(authData);
    /*********** READING ********************/
    readDataList.clear();
    dpySCM::Data readData;
    // Sector 4
    readData.index = 16;
    readDataList.push_back(readData);
    readData.index = 17;
    readDataList.push_back(readData);
    readData.index = 18;
    readDataList.push_back(readData);
    /*********** WRITING ********************/
    writeDataList.clear();
    dpySCM::Data writeData;
    // Sector 4
    writeData.index = 16;
    writeData.buffer = "0A0A000000000000000000000E0E0B0B";
    writeDataList.push_back(writeData);
    writeData.index = 18;
    writeData.buffer = "0A0A000000000000000000000E0E0B0A";
    writeDataList.push_back(writeData);
    }
    void new_card_event(boost::system::error_code& ec, const std::string& deviceId, dpySCM::CardEvent cardEvent)
    {
    dataInitialization();
    if (ec.value() == 0) {
    if (cardEvent.event == dpySCM::REMOVED) {
    std::cout << "\n\n\rThe card: " << cardEvent.cardinfo.uid << " was removed" << std::endl;
    } else if (cardEvent.event == dpySCM::ADDED && cardEvent.cardinfo.collision == false) {
    std::cout << "\rNew card available: " << cardEvent.cardinfo.uid << " in the reader: " << cardEvent.cardinfo.readerName << " of device: " << deviceId << std::endl;
    /* -------------------- Synchronous request ---------------------------------- */
    ec = scm.auth(deviceId, cardEvent.cardinfo.uid, authDataList);
    if (ec.value() == 0)
    {
    std::cout << "\nSuccessful Authentication." << std::endl;
    ec = scm.read(deviceId, cardEvent.cardinfo.uid, readDataList);
    if (ec.value() == 0) {
    std::cout << "\nSuccessful first read." << std::endl;
    std::list<dpySCM::Data>::iterator it;
    for (it = readDataList.begin(); it != readDataList.end(); ++it) {
    std::cout << "\rSuccessful read: " << cardEvent.cardinfo.uid << std::endl;
    std::cout << "\rThe index: " << it->index << " has the value: " << it->buffer << std::endl;
    }
    ec = scm.write(deviceId, cardEvent.cardinfo.uid, writeDataList);
    if (ec.value() == 0) {
    std::cout << "\nSuccessful write." << std::endl;
    std::list<dpySCM::Data>::iterator it;
    for (it = writeDataList.begin(); it != writeDataList.end(); ++it) {
    std::cout << "\rSuccessful write: " << cardEvent.cardinfo.uid << std::endl;
    std::cout << "\rThe index: " << it->index << " has the value: " << it->buffer << std::endl;
    }
    ec = scm.read(deviceId, cardEvent.cardinfo.uid, readDataList);
    if (ec.value() == 0) {
    std::cout << "\nSuccessful second read." << std::endl;
    std::list<dpySCM::Data>::iterator it;
    for (it = readDataList.begin(); it != readDataList.end(); ++it) {
    std::cout << "\rSuccessful read: " << cardEvent.cardinfo.uid << std::endl;
    std::cout << "\rThe index: " << it->index << " has the value: " << it->buffer << std::endl;
    }
    } else {
    std::cout << "\rError second reading: " << ec.message() << std::endl;
    }
    } else {
    std::cout << "\rError Writing: " << ec.message() << std::endl;
    }
    } else {
    std::cout << "\rError first reading: " << ec.message() << std::endl;
    }
    }
    else
    {
    std::cout << "\rAuthentication error: " << ec.message() << std::endl;
    }
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    int main()
    {
    std::cout << "==== ==== ==== Manual Authentication Example: ==== ==== ====" << std::endl;
    std::cout << "Subscribing to new card events...\n" << std::endl;
    scm.newCardEvent_S(new_card_event);
    while (1) {
    boost::this_thread::sleep_for(boost::chrono::milliseconds(100));
    }
    }

  • Ultra Light Counter Operations Example
    Demonstrating how to read and increment a counter on a MF Ultra Light Card.

    #include <dpy/scmApi.h>
    #include <iostream>
    static SCM scm;
    void new_card_event(boost::system::error_code& ec, const std::string& deviceId, dpySCM::CardEvent cardEvent)
    {
    if (ec.value() == 0) {
    if (cardEvent.event == dpySCM::REMOVED) {
    std::cout << "\n\n\rThe card: " << cardEvent.cardinfo.uid << " was removed" << std::endl;
    } else if (cardEvent.event == dpySCM::ADDED && cardEvent.cardinfo.collision == false ) {
    std::cout << "\rNew card available: " << cardEvent.cardinfo.uid << " in the reader: " << cardEvent.cardinfo.readerName << " of device: " << deviceId << std::endl;
    _counter.uid = cardEvent.cardinfo.uid;
    _counter.counter = 2;
    ec = scm.getULCounter(deviceId, _counter);
    if (ec.value() != 0)
    {
    std::cout << "\nError Getting Ultralight: " << ec.message() << std::endl;
    return;
    }
    std::cout << "\nCounter [" << std::to_string(_counter.counter) << "] value: " << std::to_string(_counter.value) << std::endl;
    _counter2.uid = cardEvent.cardinfo.uid;
    _counter2.counter = 2;
    _counter2.value = 2;
    ec = scm.incrementULCounter(deviceId, _counter2);
    if (ec.value() != 0)
    {
    std::cout << "\nError Increment Ultralight Counter [" << std::to_string(_counter2.counter) << "] in " << std::to_string(_counter2.value) <<". Error: " << ec.message() << std::endl;
    } else {
    std::cout << "\nCorrect Increment Ultralight Counter [" << std::to_string(_counter2.counter) << "] in " << std::to_string(_counter2.value) << std::endl;
    }
    _counter3.uid = cardEvent.cardinfo.uid;
    _counter3.counter = 2;
    ec = scm.getULCounter(deviceId, _counter3);
    if (ec.value() != 0)
    {
    std::cout << "\nError Getting Ultralight Counter: [" << std::to_string(_counter2.counter) << "]. Error: " << ec.message() << std::endl;
    return;
    }
    std::cout << "\nCounter [" << std::to_string(_counter3.counter) << "] value: " << std::to_string(_counter3.value) << std::endl;
    }
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    }
    int main()
    {
    std::cout << "==== ==== ==== Ultra Light Counter Operations Example ==== ==== ====" << std::endl;
    std::cout << "Subscribing to new card events...\n" << std::endl;
    scm.newCardEvent_S(new_card_event);
    while (1) {
    }
    return 0;
    }

  • Restore and Transfer Block Example
    Demonstrating how to restore and transfer blocks in a MF Classic Card.

    #include <dpy/scmApi.h>
    #include <iostream>
    volatile bool waiting = true;
    static SCM scm;
    void read_block(boost::system::error_code& ec, std::string deviceId, std::string uid, std::list<dpySCM::DataBlock> content)
    {
    std::list<dpySCM::Data> data_list;
    for (auto db : content) {
    data.index = db.index;
    data.priority = db.priority;
    data_list.push_back(data);
    }
    ec = scm.read(deviceId, uid, data_list);
    for (auto const &data : data_list) {
    if (ec.value() != 0) {
    std::cout << "\rError on read block" << std::endl;
    } else {
    std::cout << "\rValue readed: " << data.buffer << std::endl;
    }
    }
    }
    void write_block(boost::system::error_code& ec, std::string deviceId, std::string uid, std::list<dpySCM::Data> data_list)
    {
    ec = scm.write(deviceId, uid, data_list);
    for (auto const &data : data_list) {
    if (ec.value() != 0) {
    std::cout << "\rError on write block" << std::endl;
    } else {
    std::cout << "\rValue written: " << data.buffer << std::endl;
    }
    }
    }
    boost::system::error_code ensure_correct_block_format(const std::string& _deviceId, const std::string& _uid)
    {
    boost::system::error_code ec;
    std::list<dpySCM::Data> data_list;
    data.index = 16;
    data.priority = 3;
    data.buffer = "FF00000000FFFFFFFF00000010EF10EF"; //Value 255 - block 16
    /*
    // ===== ===== ===== ===== ===== ===== Useful information about a block format ===== ===== ===== ===== ===== =====
    // Source: https://stackoverflow.com/questions/72431616/android-nfc-mifare-classic-restore-and-transfer-not-working
    //
    // Byte number: | 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 | 13 | 14 | 15 |
    // Description: | value | ~value | value | adr | ~adr | adr | ~adr |
    //
    // Value in Little Endian
    //
    // Used in this example
    // (1) Value 255 - block 16
    // Byte number: | 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 | 13 | 14 | 15 |
    // Description: | 255 | ~255 | 255 | 16 | ~16 | 16 | ~16 |
    // Hex value: | FF 00 00 00 | 00 FF FF FF | FF 00 00 00 | 10 | EF | 10 | EF |
    // (2) Value 204 - block 16
    // Byte number: | 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 | 13 | 14 | 15 |
    // Description: | 204 | ~204 | 204 | 16 | ~16 | 16 | ~16 |
    // Hex value: | CC 00 00 00 | 33 FF FF FF | CC 00 00 00 | 10 | EF | 10 | EF |
    */
    data_list.push_back(data);
    write_block(ec, _deviceId, _uid, data_list);
    return ec;
    }
    void new_card_event(boost::system::error_code& ec, const std::string& deviceId, dpySCM::CardEvent cardEvent)
    {
    if (ec.value() == 0) {
    if (cardEvent.event == dpySCM::REMOVED) {
    std::cout << "\rThe card: " << cardEvent.cardinfo.uid << " was removed" << std::endl;
    } else if (cardEvent.event == dpySCM::ADDED && cardEvent.cardinfo.collision == false) {
    std::cout << "\n\rNew card available: " << cardEvent.cardinfo.uid << " in the reader: " << cardEvent.cardinfo.readerName << " of device: " << deviceId << std::endl;
    ec = ensure_correct_block_format(deviceId, cardEvent.cardinfo.uid);
    if (ec.value() != 0) {
    std::cout << "\rError while formatting block. Error: [" << ec.value() << "] "<< ec.message() << std::endl;
    return;
    }
    std::cout << "\r(1) Block formatted correctly!" << std::endl;
    std::cout << "(2) Reading block first time. Original value:" << std::endl;
    std::list<dpySCM::DataBlock> contents;
    db.index = 16;
    db.priority = 3;
    contents.push_back(db);
    read_block(ec, deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() != 0) {
    return;
    }
    std::cout << "(3) Saving block contain..." << std::endl;
    ec = scm.restoreBlock(deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() == 0) {
    std::cout << "\rBlock " << db.index << " restored" << std::endl;
    } else {
    std::cout << "\rError while executing restoreBlock. Error: [" << ec.value() << "] "<< ec.message() << std::endl;
    return;
    }
    std::cout << "(4) Overwriting block contain..." << std::endl;
    std::list<dpySCM::Data> data_list;
    data.index = 16;
    data.priority = 3;
    data.buffer = "CC00000033FFFFFFCC00000010EF10EF"; // Value 204 - Block 16
    data_list.push_back(data);
    write_block(ec, deviceId, cardEvent.cardinfo.uid, data_list);
    if (ec.value() != 0) {
    return;
    }
    std::cout << "(5) Transfering saved block contain..." << std::endl;
    ec = scm.transferBlock(deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() == 0) {
    std::cout << "\rBlock " << db.index << " transferred" << std::endl;
    } else {
    std::cout << "\rError while executing transfer block. Error: [" << ec.value() << "] "<< ec.message() << std::endl;
    return;
    }
    std::cout << "(6) Reading block again. Expected original value:" << std::endl;
    read_block(ec, deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() != 0) {
    return;
    }
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    waiting = false;
    }
    int main()
    {
    std::cout << "==== ==== ==== Restore and Transfer Block Example ==== ==== ====" << std::endl;
    std::cout << "PRECONDITIONS: The correct keys must be saved on the Smart Card Device" << std::endl;
    std::cout << "\rPlace the card in the reader...\n\n" << std::endl;
    scm.newCardEvent_S(new_card_event);
    while (waiting){
    }
    return 0;
    }

  • Increment, Decrement and Transfer Block Example
    Demonstrating how to increment, decrement and transfer blocks in a MF Classic Card

    #include <dpy/scmApi.h>
    #include <iostream>
    volatile bool waiting = true;
    static SCM scm;
    void read_block(boost::system::error_code& ec, std::string deviceId, std::string uid, std::list<dpySCM::DataBlock> content)
    {
    std::list<dpySCM::Data> data_list;
    for (auto db : content) {
    data.index = db.index;
    data.priority = db.priority;
    data_list.push_back(data);
    }
    ec = scm.read(deviceId, uid, data_list);
    for (auto const &data : data_list) {
    if (ec.value() != 0) {
    std::cout << "\rError on read block" << std::endl;
    } else {
    std::cout << "\rValue readed: " << data.buffer << std::endl;
    }
    }
    }
    void write_block(boost::system::error_code& ec, std::string deviceId, std::string uid, std::list<dpySCM::DataBlock> content)
    {
    std::list<dpySCM::Data> data_list;
    for (auto db : content) {
    data.index = db.index;
    data.priority = db.priority;
    data.buffer = db.value;
    data_list.push_back(data);
    }
    ec = scm.write(deviceId, uid, data_list);
    for (auto const &data : data_list) {
    if (ec.value() != 0) {
    std::cout << "\rError on write block" << std::endl;
    } else {
    std::cout << "\rValue written: " << data.buffer << std::endl;
    }
    }
    }
    void new_card_event(boost::system::error_code& ec, const std::string& deviceId, dpySCM::CardEvent cardEvent)
    {
    if (ec.value() == 0) {
    if (cardEvent.event == dpySCM::REMOVED) {
    std::cout << "\rThe card: " << cardEvent.cardinfo.uid << " was removed" << std::endl;
    } else if (cardEvent.event == dpySCM::ADDED && cardEvent.cardinfo.collision == false) {
    std::cout << "\rNew card available: " << cardEvent.cardinfo.uid << " in the reader: " << cardEvent.cardinfo.readerName << " of device: " << deviceId << std::endl;
    std::list<dpySCM::DataBlock> contents;
    db.index = 16;
    db.priority = 3;
    db.value = 5;
    contents.push_back(db);
    std::cout << "(1) Original value: " << std::endl;
    read_block(ec, deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() != 0) {
    return;
    }
    ec = scm.incrementBlock(deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() == 0) {
    std::cout << "\rBlock " << db.index << " incremented by " << db.value << std::endl;
    } else {
    std::cout << "\rError while executing increment block. Error: [" << ec.value() << "] "<< ec.message() << std::endl;
    return;
    }
    std::cout << "(2) Value updated: " << std::endl;
    read_block(ec, deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() != 0) {
    return;
    }
    contents.clear();
    db.index = 16;
    db.priority = 3;
    db.value = 2;
    contents.push_back(db);
    ec = scm.decrementOnlyBlock(deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() == 0) {
    std::cout << "\rBlock " << db.index << " decremented only by " << db.value << std::endl;
    } else {
    std::cout << "\rError while executing decrement only block. Error: [" << ec.value() << "] "<< ec.message() << std::endl;
    return;
    }
    std::cout << "(3) Value updated in buffer, same value readed in step 2: " << std::endl;
    read_block(ec, deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() != 0) {
    return;
    }
    ec = scm.transferBlock(deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() == 0) {
    std::cout << "\rBlock " << db.index << " transferred" << std::endl;
    } else {
    std::cout << "\rError while executing transfer block. Error: [" << ec.value() << "] "<< ec.message() << std::endl;
    return;
    }
    std::cout << "(4) Value updated: " << std::endl;
    read_block(ec, deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() != 0) {
    return;
    }
    contents.clear();
    db.index = 16;
    db.priority = 3;
    db.value = 2;
    contents.push_back(db);
    ec = scm.decrementBlock(deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() == 0) {
    std::cout << "\rBlock " << db.index << " decremented by " << db.value << std::endl;
    } else {
    std::cout << "\rError while executing increment block. Error: [" << ec.value() << "] "<< ec.message() << std::endl;
    return;
    }
    std::cout << "(5) Value updated: " << std::endl;
    read_block(ec, deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() != 0) {
    return;
    }
    contents.clear();
    db.index = 16;
    db.priority = 3;
    db.value = 4;
    contents.push_back(db);
    ec = scm.incrementOnlyBlock(deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() == 0) {
    std::cout << "\rBlock " << db.index << " incremented only by " << db.value << std::endl;
    } else {
    std::cout << "\rError while executing decrement only block. Error: [" << ec.value() << "] "<< ec.message() << std::endl;
    return;
    }
    std::cout << "(6) Value updated in buffer, same value readed in step 5: " << std::endl;
    read_block(ec, deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() != 0) {
    return;
    }
    ec = scm.transferBlock(deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() == 0) {
    std::cout << "\rBlock " << db.index << " transferred" << std::endl;
    } else {
    std::cout << "\rError while executing transfer block. Error: [" << ec.value() << "] "<< ec.message() << std::endl;
    return;
    }
    std::cout << "(7) Value updated: " << std::endl;
    read_block(ec, deviceId, cardEvent.cardinfo.uid, contents);
    if (ec.value() != 0) {
    return;
    }
    }
    } else {
    std::cout << "\rError : " << ec.message() << std::endl;
    }
    waiting = false;
    }
    int main()
    {
    std::cout << "==== ==== ==== Increment and Transfer Block Example ==== ==== ====" << std::endl;
    std::cout << "PRECONDITIONS: " << std::endl;
    std::cout << "\t 1 - The correct keys must be saved on the Smart Card Device" << std::endl;
    std::cout << "\t 2 - Block 16 must be in the correct format to block operations" << std::endl;
    std::cout << "\rPlace the card in the reader...\n\n" << std::endl;
    scm.newCardEvent_S(new_card_event);
    while (waiting){
    }
    return 0;
    }