Header

Examples
[RFID handling]

Table of contents:

pr_rfid - RFID handling example

Show how to read data from an RFID chip.

The needed gxsdldr.c loader file is included directly:

#include "prapi.h"
#include "gxsdldr.c"

The __lib__.h file contains some library functions used only in the sample programs, such as the lib_function_start and lib_function_end functions that implement the simple command line interface and measures the elapsed time between the two function calls.

#include "../__lib__.h"

The make_bac helper function, reading MRZ from the document and using it to make BAC:

/* The make_bac helper function, reading MRZ from the document and using it to make BAC */
int make_bac(gxHANDLE hpr, char* card)
{
    int j,l;
    gxVARIANT pdoc;
    int pages;
    char *mrz[3];

    /* Setting only infra light for capture */
    lib_function_start("\t- Setting infra light");
    if (pr_getlightmask(hpr,&pages,PR_LIGHT_INFRA,0) && pr_setpagelight(hpr,1,(gxu32*)&pages)) lib_function_end();
    else return lib_displ_err();

    /* Capturing images */
    lib_function_start("\t- Capturing images");
    if (pr_capture(hpr)) lib_function_end();
    else return lib_displ_err();

    /* Reading MRZ */
    lib_function_start("\t- Reading MRZ");
    if (pr_getmrz(hpr, 0, PR_LIGHT_INFRA, PR_IT_ORIGINAL, &pdoc)) lib_function_end();
    else return lib_displ_err();

    if (!pdoc) {printf("No MRZ data found!\n"); return -1;}

    for (j=0; j<3; j++) {
        mrz[j] = (char*) malloc(45);
        memset(mrz[j], 0 ,45);
        l = 45;
        pr_getfieldfromdoca(hpr, pdoc, PR_DF_MRZ1 + j, mrz[j], &l, 0, 0);
    }

    gx_disposevariant(&pdoc);

    /* Making BAC */
    lib_function_start("\t- Making BAC");
    if (pr_makebaca(hpr, card, (const char **)mrz, strlen(mrz[2]) ? 3 : 2)) {
        for (j=0; j<3; j++) free(mrz[j]);
        lib_function_end();
    } else {
        for (j=0; j<3; j++) free(mrz[j]);
        return lib_displ_err();
    }

    return 0;
}

The resolve_dg1 helper function, parsing EF_DG1 and displaying MRZ information:

/* The resolve_dg1 helper function, parsing EF_DG1 and displaying MRZ information */
int resolve_dg1(gxHANDLE hpr, void * data, int sdata)
{
    int error_code = 0;
    gxVARIANT pdoc;
    char text[256];
    int stext;

    lib_function_start("\t- Resolving DG1");
    if (pr_resolverfiddata(hpr, data, sdata, &pdoc)) {
        if (!pdoc) lib_error("No MRZ data found!");
        else {
            lib_function_end();
            lib_write_line("\t- MRZ data:");
            stext = sizeof(text);
            if (pr_getfieldfromdoca(hpr, pdoc, PR_DF_RFID_MRZ, text, &stext, NULL, 0)) {
                char s[45];
                gx_snprintf(s, 44, text);
                s[44] = 0;
                lib_write_line("\t\t %s", s);
                gx_snprintf(s, 44, text+44);
                s[44] = 0;
                lib_write_line("\t\t %s", s);
            } else {
                error_code = lib_displ_err();
            }
            if (pdoc) gx_disposevariant(&pdoc);
        }
    } else {
        error_code = lib_displ_err();
    }

    return error_code;
}

The resolve_dg2 helper function, parsing EF_DG2 and saving the face image:

/* The resolve_dg2 helper function, parsing EF_DG2 and saving the face image */
int resolve_dg2(gxHANDLE hpr, void * data, int sdata)
{
    int error_code = 0;
    gxVARIANT pdoc;
    gxIMAGE *img = NULL;

    lib_function_start("\t- Resolving");
    if (pr_resolverfiddata(hpr, data, sdata, &pdoc)) {
        if (!pdoc) lib_error("No image data found!");
        else {
            lib_function_end();
            lib_function_start("\t- Saving image");
            if (pr_getgximagefromdoc(hpr, pdoc, PR_DF_RFID_FACE, &img)) {
                if (gx_saveimagea(gx_direct(GX_CALL_GROUP_GX_IMAGE), img, "face.jpg", GX_JPEG)) lib_function_end();
                else error_code = lib_displ_err();
                gx_unrefimage(gx_direct(GX_CALL_GROUP_GX_IMAGE), img);
            } else {
                error_code = lib_displ_err();
            }
            if (pdoc) gx_disposevariant(&pdoc);
        }
    } else {
        error_code = lib_displ_err();
    }

    return error_code;
}

The main function:

int main() {
    int i;
    char ** cardlist=0;
    int numcards=0;
    void * data=NULL;
    int sdata = 0, srfid_files = 4;
    unsigned int rfid_files = 0;
    char path[64], fn[32];
    gxVARIANT pdoc = NULL;

Opening the Passport Reader system:

    /* Opening the PR system */
    gxHANDLE hpr;       /* handle for the PR system */
    lib_function_start("Opening system files");
    if (gx_openmodulea(&hpr,"prapi","default")) lib_function_end();
    else {
        lib_displ_err();
        return 0;
    }

Connecting to the first device. If no device is connected then the pr_usedevicen() function returns false and the program ends:

    /* Connecting to the first device */
    lib_function_start("Connecting to the first device");
    if (pr_usedevicen(hpr,0,PR_UMODE_FULL_CONTROL)) {
        lib_function_end();
    } else {
        lib_displ_err();
        gx_closehandle(&hpr);
        return 0;
    }

The main loop begins:

    while(!lib_kbhit()) {

        lib_process_start("RFID");

Searching for RFID cards:

        /* Searching for RFID cards */
        lib_function_start("Searching for RFID cards ...");
        if (pr_getrfidcardlista(hpr, &cardlist, &numcards)) {
            lib_function_end();

Connecting to the first chip:

                    /* Connecting to the first chip */
                    lib_function_start("Connecting to the RFID chip");
                    if (pr_connectrfidcarda(hpr, cardlist[0])) lib_function_end();
                    else {
                        lib_displ_err();
                        continue;
                    }

                    lib_write_line("Serial no.: %s", cardlist[0]);

Reading EF_COM first to determine the available files on the chip. In case of BAC protected chip the reading process returns GX_EACCES, which means that the Basic Access Control procedure must be executed in order to access the chip.

                    /* Initializing chip reading */
                    lib_function_start("Initializing chip reading");
                    if (pr_getrfidfilea(hpr, cardlist[0], PR_RFID_EF_COM, &data, &sdata)) lib_function_end();
                    else {
                        lib_displ_err();
                        if (gx_geterrorcode() != GX_EACCES) continue;
                        if(make_bac(hpr, cardlist[0])) continue;
                        lib_function_start("Initializing chip reading");
                        if (pr_getrfidfilea(hpr, cardlist[0], PR_RFID_EF_COM, &data, &sdata)) lib_function_end();
                        else {lib_displ_err(); continue;}
                    }

Parsing the EF_COM and getting the information about the available files on the chip:

                    /* Getting available files */
                    lib_function_start("\t- Available files");
                    gx_snprintf(path, sizeof(path), "C,D=%i/L,V=%i/C,D=%i", PRV_FIELDLIST, PR_DF_RFID_FIELDS|PR_DFE_DOCUMENT_DESCRIPTOR, PRV_RFIDDIR);
                    if (
                        !pr_resolverfiddata(hpr, data, sdata, &pdoc) ||
                        !gx_convertvariantbypatha(pdoc, path, 0, GX_VARIANT_INT, &srfid_files, 0, &rfid_files, srfid_files)
                        ) {
                            lib_displ_err();
                            if (pdoc) gx_disposevariant(&pdoc);
                            if (data) {gx_globalfree(data); data = NULL; sdata = 0;}
                            continue;
                    }
                    if (pdoc) gx_disposevariant(&pdoc);
                    if (data) {gx_globalfree(data); data = NULL; sdata = 0;}

                    for (i=PR_RFID_EF_DG1; i<=PR_RFID_EF_DG16; i++)
                        if (((1<<i) & rfid_files)) lib_write("DG%i ", i);
                    lib_function_end();

Reading available files, saving and resolving them

                    /* Reading available files, saving and resolving them */
                    for (i=PR_RFID_EF_DG1; i<=PR_RFID_EF_DG2; i++) {
                        if (!((1<<i) & rfid_files)) continue;
                        gx_snprintf(fn, 32, "EF_DG%i.dat", i);
                        lib_function_start("Reading %s", fn);
                        if (pr_getrfidfilea(hpr, cardlist[0], i, &data, &sdata)) lib_function_end();
                        else {lib_displ_err(); continue;}
                        lib_function_start("\t- Saving %s", fn);
                        if (!lib_save(fn, data, sdata)) lib_error("File write error!");
                        else lib_function_end();
                        if (i == PR_RFID_EF_DG1) resolve_dg1(hpr, data, sdata);
                        if (i == PR_RFID_EF_DG2) resolve_dg2(hpr, data, sdata);
                        if (data) {gx_globalfree(data); data = NULL; sdata = 0;}
                    }

Disconnecting from the chip:

                    /* Disconnecting from the chip */
                    lib_function_start("Disconnecting from the RFID chip");
                    if (pr_disconnectrfidcarda(hpr, cardlist[0])) lib_function_end();
                    else lib_displ_err();

The main loop ends:

        lib_process_end();
        lib_wait_for_sec(3);
    }

Closing the device:

    /* Closing the device */
    lib_function_start("Closing the device");
    if (pr_closedevice(hpr)) {
        lib_function_end();
    } else {
        lib_displ_err();
    }

Closing the Passport Reader system:

    /* Closing the PR system */
    lib_function_start("Closing the PR system");
    if (gx_closehandle(&hpr)) {
        lib_function_end();
    } else {
        lib_displ_err();
    }

The sample program ends printing some statistic information:

    return lib_print_stat();
}

The complete source code:

#include "prapi.h"
#include "gxsdldr.c"

#include "../__lib__.h"

/* The make_bac helper function, reading MRZ from the document and using it to make BAC */
int make_bac(gxHANDLE hpr, char* card)
{
    int j,l;
    gxVARIANT pdoc;
    int pages;
    char *mrz[3];

    /* Setting only infra light for capture */
    lib_function_start("\t- Setting infra light");
    if (pr_getlightmask(hpr,&pages,PR_LIGHT_INFRA,0) && pr_setpagelight(hpr,1,(gxu32*)&pages)) lib_function_end();
    else return lib_displ_err();

    /* Capturing images */
    lib_function_start("\t- Capturing images");
    if (pr_capture(hpr)) lib_function_end();
    else return lib_displ_err();

    /* Reading MRZ */
    lib_function_start("\t- Reading MRZ");
    if (pr_getmrz(hpr, 0, PR_LIGHT_INFRA, PR_IT_ORIGINAL, &pdoc)) lib_function_end();
    else return lib_displ_err();

    if (!pdoc) {printf("No MRZ data found!\n"); return -1;}

    for (j=0; j<3; j++) {
        mrz[j] = (char*) malloc(45);
        memset(mrz[j], 0 ,45);
        l = 45;
        pr_getfieldfromdoca(hpr, pdoc, PR_DF_MRZ1 + j, mrz[j], &l, 0, 0);
    }

    gx_disposevariant(&pdoc);

    /* Making BAC */
    lib_function_start("\t- Making BAC");
    if (pr_makebaca(hpr, card, (const char **)mrz, strlen(mrz[2]) ? 3 : 2)) {
        for (j=0; j<3; j++) free(mrz[j]);
        lib_function_end();
    } else {
        for (j=0; j<3; j++) free(mrz[j]);
        return lib_displ_err();
    }

    return 0;
}

/* The resolve_dg1 helper function, parsing EF_DG1 and displaying MRZ information */
int resolve_dg1(gxHANDLE hpr, void * data, int sdata)
{
    int error_code = 0;
    gxVARIANT pdoc;
    char text[256];
    int stext;

    lib_function_start("\t- Resolving DG1");
    if (pr_resolverfiddata(hpr, data, sdata, &pdoc)) {
        if (!pdoc) lib_error("No MRZ data found!");
        else {
            lib_function_end();
            lib_write_line("\t- MRZ data:");
            stext = sizeof(text);
            if (pr_getfieldfromdoca(hpr, pdoc, PR_DF_RFID_MRZ, text, &stext, NULL, 0)) {
                char s[45];
                gx_snprintf(s, 44, text);
                s[44] = 0;
                lib_write_line("\t\t %s", s);
                gx_snprintf(s, 44, text+44);
                s[44] = 0;
                lib_write_line("\t\t %s", s);
            } else {
                error_code = lib_displ_err();
            }
            if (pdoc) gx_disposevariant(&pdoc);
        }
    } else {
        error_code = lib_displ_err();
    }

    return error_code;
}

/* The resolve_dg2 helper function, parsing EF_DG2 and saving the face image */
int resolve_dg2(gxHANDLE hpr, void * data, int sdata)
{
    int error_code = 0;
    gxVARIANT pdoc;
    gxIMAGE *img = NULL;

    lib_function_start("\t- Resolving");
    if (pr_resolverfiddata(hpr, data, sdata, &pdoc)) {
        if (!pdoc) lib_error("No image data found!");
        else {
            lib_function_end();
            lib_function_start("\t- Saving image");
            if (pr_getgximagefromdoc(hpr, pdoc, PR_DF_RFID_FACE, &img)) {
                if (gx_saveimagea(gx_direct(GX_CALL_GROUP_GX_IMAGE), img, "face.jpg", GX_JPEG)) lib_function_end();
                else error_code = lib_displ_err();
                gx_unrefimage(gx_direct(GX_CALL_GROUP_GX_IMAGE), img);
            } else {
                error_code = lib_displ_err();
            }
            if (pdoc) gx_disposevariant(&pdoc);
        }
    } else {
        error_code = lib_displ_err();
    }

    return error_code;
}

int main() {
    int i;
    char ** cardlist=0;
    int numcards=0;
    void * data=NULL;
    int sdata = 0, srfid_files = 4;
    unsigned int rfid_files = 0;
    char path[64], fn[32];
    gxVARIANT pdoc = NULL;

    /* Opening the PR system */
    gxHANDLE hpr;       /* handle for the PR system */
    lib_function_start("Opening system files");
    if (gx_openmodulea(&hpr,"prapi","default")) lib_function_end();
    else {
        lib_displ_err();
        return 0;
    }

    /* Connecting to the first device */
    lib_function_start("Connecting to the first device");
    if (pr_usedevicen(hpr,0,PR_UMODE_FULL_CONTROL)) {
        lib_function_end();
    } else {
        lib_displ_err();
        gx_closehandle(&hpr);
        return 0;
    }

    while(!lib_kbhit()) {

        lib_process_start("RFID");

        /* Searching for RFID cards */
        lib_function_start("Searching for RFID cards ...");
        if (pr_getrfidcardlista(hpr, &cardlist, &numcards)) {
            lib_function_end();

            if (numcards == 0) {
                lib_write_line("No card found");
            } else {
                lib_write_line("");

                do {
                    /* Connecting to the first chip */
                    lib_function_start("Connecting to the RFID chip");
                    if (pr_connectrfidcarda(hpr, cardlist[0])) lib_function_end();
                    else {
                        lib_displ_err();
                        continue;
                    }

                    lib_write_line("Serial no.: %s", cardlist[0]);

                    /* Initializing chip reading */
                    lib_function_start("Initializing chip reading");
                    if (pr_getrfidfilea(hpr, cardlist[0], PR_RFID_EF_COM, &data, &sdata)) lib_function_end();
                    else {
                        lib_displ_err();
                        if (gx_geterrorcode() != GX_EACCES) continue;
                        if(make_bac(hpr, cardlist[0])) continue;
                        lib_function_start("Initializing chip reading");
                        if (pr_getrfidfilea(hpr, cardlist[0], PR_RFID_EF_COM, &data, &sdata)) lib_function_end();
                        else {lib_displ_err(); continue;}
                    }

                    /* Getting available files */
                    lib_function_start("\t- Available files");
                    gx_snprintf(path, sizeof(path), "C,D=%i/L,V=%i/C,D=%i", PRV_FIELDLIST, PR_DF_RFID_FIELDS|PR_DFE_DOCUMENT_DESCRIPTOR, PRV_RFIDDIR);
                    if (
                        !pr_resolverfiddata(hpr, data, sdata, &pdoc) ||
                        !gx_convertvariantbypatha(pdoc, path, 0, GX_VARIANT_INT, &srfid_files, 0, &rfid_files, srfid_files)
                        ) {
                            lib_displ_err();
                            if (pdoc) gx_disposevariant(&pdoc);
                            if (data) {gx_globalfree(data); data = NULL; sdata = 0;}
                            continue;
                    }
                    if (pdoc) gx_disposevariant(&pdoc);
                    if (data) {gx_globalfree(data); data = NULL; sdata = 0;}

                    for (i=PR_RFID_EF_DG1; i<=PR_RFID_EF_DG16; i++)
                        if (((1<<i) & rfid_files)) lib_write("DG%i ", i);
                    lib_function_end();

                    /* Reading available files, saving and resolving them */
                    for (i=PR_RFID_EF_DG1; i<=PR_RFID_EF_DG2; i++) {
                        if (!((1<<i) & rfid_files)) continue;
                        gx_snprintf(fn, 32, "EF_DG%i.dat", i);
                        lib_function_start("Reading %s", fn);
                        if (pr_getrfidfilea(hpr, cardlist[0], i, &data, &sdata)) lib_function_end();
                        else {lib_displ_err(); continue;}
                        lib_function_start("\t- Saving %s", fn);
                        if (!lib_save(fn, data, sdata)) lib_error("File write error!");
                        else lib_function_end();
                        if (i == PR_RFID_EF_DG1) resolve_dg1(hpr, data, sdata);
                        if (i == PR_RFID_EF_DG2) resolve_dg2(hpr, data, sdata);
                        if (data) {gx_globalfree(data); data = NULL; sdata = 0;}
                    }

                    /* Disconnecting from the chip */
                    lib_function_start("Disconnecting from the RFID chip");
                    if (pr_disconnectrfidcarda(hpr, cardlist[0])) lib_function_end();
                    else lib_displ_err();

                } while(false);

            }
            if (cardlist) {gx_globalfree(cardlist); cardlist = NULL;}
        } else {
            lib_displ_err();
        }

        lib_process_end();
        lib_wait_for_sec(3);
    }

    /* Closing the device */
    lib_function_start("Closing the device");
    if (pr_closedevice(hpr)) {
        lib_function_end();
    } else {
        lib_displ_err();
    }

    /* Closing the PR system */
    lib_function_start("Closing the PR system");
    if (gx_closehandle(&hpr)) {
        lib_function_end();
    } else {
        lib_displ_err();
    }

    return lib_print_stat();
}

pr_rfid_adv - Advanced RFID handling example

Show how to read data from an RFID chip with advanced authentication features.

The needed gxsdldr.c loader file is included directly:

#include "prapi.h"
#include "gxsdldr.c"

The __lib__.h file contains some library functions used only in the sample programs, such as the lib_function_start and lib_function_end functions that implement the simple command line interface and measures the elapsed time between the two function calls.

#include "../__lib__.h"

The load_certificates helper function, loading the certificate files:

/* The load_certificates helper function, loading the certificate files */
int load_certificates(gxHANDLE hpr)
{
    int i,l;
    char *pk;
    char **list = NULL;

    /* Loading certificates */
    l = lib_filelist("../../../data/certs", "*.cer", &list);
    for (i=0; i<l; i++) {
        lib_function_start("Loading sample certificate: %s", list[i]);
        if (pr_loadcertfilea(hpr, list[i], NULL)) lib_function_end(); else lib_displ_err();
        free(list[i]);
    }

    /* Loading CV certificates */
    l = lib_filelist("../../../data/certs", "*.cvcert", &list);
    for (i=0; i<l; i++) {
        lib_function_start("Loading sample CV certificate: %s", list[i]);
        pk = (char*)malloc(strlen(list[i]) - strlen("cvcert") + strlen("pkcs8") + 1);
        if (pk) {
            gx_strncpy(pk, list[i], strlen(list[i]) - strlen("cvcert") + 1);
            gx_strncpy(pk + strlen(list[i]) - strlen("cvcert"), "pkcs8", strlen("pkcs8") + 1);
        }
        if (pr_loadcertfilea(hpr, list[i], lib_isfile(pk) ? pk: NULL)) lib_function_end(); else lib_displ_err();
        free(list[i]);
        if (pk) free(pk);
    }

    return 0;
}

The make_bac helper function, reading MRZ from the document and using it to make BAC:

/* The make_bac helper function, reading MRZ from the document and using it to make BAC */
int make_bac(gxHANDLE hpr, char* card)
{
    int j,l;
    gxVARIANT pdoc;
    int pages;
    char *mrz[3];

    /* Setting only infra light for capture */
    lib_function_start("\t- Setting infra light");
    if (pr_getlightmask(hpr,&pages,PR_LIGHT_INFRA,0) && pr_setpagelight(hpr,1,(gxu32*)&pages)) lib_function_end();
    else return lib_displ_err();

    /* Capturing images */
    lib_function_start("\t- Capturing images");
    if (pr_capture(hpr)) lib_function_end();
    else return lib_displ_err();

    /* Reading MRZ */
    lib_function_start("\t- Reading MRZ");
    if (pr_getmrz(hpr, 0, PR_LIGHT_INFRA, PR_IT_ORIGINAL, &pdoc)) lib_function_end();
    else return lib_displ_err();

    if (!pdoc) {printf("No MRZ data found!\n"); return -1;}

    for (j=0; j<3; j++) {
        mrz[j] = (char*) malloc(45);
        memset(mrz[j], 0 ,45);
        l = 45;
        pr_getfieldfromdoca(hpr, pdoc, PR_DF_MRZ1 + j, mrz[j], &l, 0, 0);
    }

    gx_disposevariant(&pdoc);

    /* Making BAC */
    lib_function_start("\t- Making BAC");
    if (pr_makebaca(hpr, card, (const char **)mrz, strlen(mrz[2]) ? 3 : 2)) {
        for (j=0; j<3; j++) free(mrz[j]);
        lib_function_end();
    } else {
        for (j=0; j<3; j++) free(mrz[j]);
        return lib_displ_err();
    }

    return 0;
}

The resolve_dg1 helper function, parsing EF_DG1 and displaying MRZ information:

/* The resolve_dg1 helper function, parsing EF_DG1 and displaying MRZ information */
int resolve_dg1(gxHANDLE hpr, void * data, int sdata)
{
    int error_code = 0;
    gxVARIANT pdoc;
    char text[256];
    int stext;

    lib_function_start("\t- Resolving DG1");
    if (pr_resolverfiddata(hpr, data, sdata, &pdoc)) {
        if (!pdoc) lib_error("No MRZ data found!");
        else {
            lib_function_end();
            lib_write_line("\t- MRZ data:");
            stext = sizeof(text);
            if (pr_getfieldfromdoca(hpr, pdoc, PR_DF_RFID_MRZ, text, &stext, NULL, 0)) {
                char s[45];
                gx_snprintf(s, 44, text);
                s[44] = 0;
                lib_write_line("\t\t %s", s);
                gx_snprintf(s, 44, text+44);
                s[44] = 0;
                lib_write_line("\t\t %s", s);
            } else {
                error_code = lib_displ_err();
            }
            if (pdoc) gx_disposevariant(&pdoc);
        }
    } else {
        error_code = lib_displ_err();
    }

    return error_code;
}

The resolve_dg2 helper function, parsing EF_DG2 and saving the face image:

/* The resolve_dg2 helper function, parsing EF_DG2 and saving the face image */
int resolve_dg2(gxHANDLE hpr, void * data, int sdata)
{
    int error_code = 0;
    gxVARIANT pdoc;
    gxIMAGE *img = NULL;

    lib_function_start("\t- Resolving");
    if (pr_resolverfiddata(hpr, data, sdata, &pdoc)) {
        if (!pdoc) lib_error("No image data found!");
        else {
            lib_function_end();
            lib_function_start("\t- Saving image");
            if (pr_getgximagefromdoc(hpr, pdoc, PR_DF_RFID_FACE, &img)) {
                if (gx_saveimagea(gx_direct(GX_CALL_GROUP_GX_IMAGE), img, "face.jpg", GX_JPEG)) lib_function_end();
                else error_code = lib_displ_err();
                gx_unrefimage(gx_direct(GX_CALL_GROUP_GX_IMAGE), img);
            } else {
                error_code = lib_displ_err();
            }
            if (pdoc) gx_disposevariant(&pdoc);
        }
    } else {
        error_code = lib_displ_err();
    }

    return error_code;
}

The main function:

int main() {
    int i;
    char ** cardlist=0;
    int numcards=0;
    void * data=NULL;
    int sdata = 0, srfid_files = 4;
    unsigned int rfid_files = 0;
    char path[64], fn[32];
    gxVARIANT pdoc = NULL;

Opening the Passport Reader system:

    /* Opening the PR system */
    gxHANDLE hpr;       /* handle for the PR system */
    lib_function_start("Opening system files");
    if (gx_openmodulea(&hpr,"prapi","default")) lib_function_end();
    else {
        lib_displ_err();
        return 0;
    }

Connecting to the first device. If no device is connected then the pr_usedevicen() function returns false and the program ends:

    /* Connecting to the first device */
    lib_function_start("Connecting to the first device");
    if (pr_usedevicen(hpr,0,PR_UMODE_FULL_CONTROL)) {
        lib_function_end();
    } else {
        lib_displ_err();
        gx_closehandle(&hpr);
        return 0;
    }

Loading the certificates for authentication:

    /* Loading certificates */
    lib_write_line("Loading certificates");
    load_certificates(hpr);

The main loop begins:

    while(!lib_kbhit()) {

        lib_process_start("RFID");

Searching for RFID cards:

        /* Searching for RFID cards */
        lib_function_start("Searching for RFID cards ...");
        if (pr_getrfidcardlista(hpr, &cardlist, &numcards)) {
            lib_function_end();

Connecting to the first chip:

                    /* Connecting to the first chip */
                    lib_function_start("Connecting to the RFID chip");
                    if (pr_connectrfidcarda(hpr, cardlist[0])) lib_function_end();
                    else {
                        lib_displ_err();
                        continue;
                    }

                    lib_write_line("Serial no.: %s", cardlist[0]);

Reading EF_COM first to determine the available files on the chip. In case of BAC protected chip the reading process returns GX_EACCES, which means that the Basic Access Control procedure must be executed in order to access the chip.

                    /* Initializing chip reading */
                    lib_function_start("Initializing chip reading");
                    if (pr_getrfidfilea(hpr, cardlist[0], PR_RFID_EF_COM, &data, &sdata)) lib_function_end();
                    else {
                        lib_displ_err();
                        if (gx_geterrorcode() != GX_EACCES) continue;
                        if(make_bac(hpr, cardlist[0])) continue;
                        lib_function_start("Initializing chip reading");
                        if (pr_getrfidfilea(hpr, cardlist[0], PR_RFID_EF_COM, &data, &sdata)) lib_function_end();
                        else {lib_displ_err(); continue;}
                    }

Parsing the EF_COM and getting the information about the available files on the chip:

                    /* Getting available files */
                    lib_function_start("\t- Available files");
                    gx_snprintf(path, sizeof(path), "C,D=%i/L,V=%i/C,D=%i", PRV_FIELDLIST, PR_DF_RFID_FIELDS|PR_DFE_DOCUMENT_DESCRIPTOR, PRV_RFIDDIR);
                    if (
                        !pr_resolverfiddata(hpr, data, sdata, &pdoc) ||
                        !gx_convertvariantbypatha(pdoc, path, 0, GX_VARIANT_INT, &srfid_files, 0, &rfid_files, srfid_files)
                        ) {
                            lib_displ_err();
                            if (pdoc) gx_disposevariant(&pdoc);
                            if (data) {gx_globalfree(data); data = NULL; sdata = 0;}
                            continue;
                    }
                    if (pdoc) gx_disposevariant(&pdoc);
                    if (data) {gx_globalfree(data); data = NULL; sdata = 0;}

                    for (i=PR_RFID_EF_DG1; i<=PR_RFID_EF_DG16; i++)
                        if (((1<<i) & rfid_files)) lib_write("DG%i ", i);
                    lib_function_end();

Making Passive Authentication to check the integrity of the chip data:

                    /* Making Passive Authentication */
                    lib_function_start("\t- Making Passive Authentication");
                    if (pr_makepassiveautha(hpr, cardlist[0])) lib_function_end();
                    else lib_displ_err();

Making Active Authentication if EF_DG15 exists:

                    /* Making Active Authentication */
                    if ((1 << PR_RFID_EF_DG15) & rfid_files) {
                        lib_function_start("\t- Making Active Authentication");
                        if (pr_makeactiveautha(hpr, cardlist[0])) lib_function_end();
                        else lib_displ_err();
                    }

Reading available files, saving and resolving them

                    /* Reading available files, saving and resolving them */
                    for (i=PR_RFID_EF_DG1; i<=PR_RFID_EF_DG16; i++) {
                        if (i == PR_RFID_EF_DG3 || i == PR_RFID_EF_DG4) continue;
                        if (!((1<<i) & rfid_files)) continue;
                        gx_snprintf(fn, 32, "EF_DG%i.dat", i);
                        lib_function_start("Reading %s", fn);
                        if (pr_getrfidfilea(hpr, cardlist[0], i, &data, &sdata)) lib_function_end();
                        else {lib_displ_err(); continue;}
                        lib_function_start("\t- Saving %s", fn);
                        if (!lib_save(fn, data, sdata)) lib_error("File write error!");
                        else lib_function_end();
                        if (i == PR_RFID_EF_DG1) resolve_dg1(hpr, data, sdata);
                        if (i == PR_RFID_EF_DG2) resolve_dg2(hpr, data, sdata);
                        if (data) {gx_globalfree(data); data = NULL; sdata = 0;}
                    }

Disconnecting from the chip:

                    /* Disconnecting from the chip */
                    lib_function_start("Disconnecting from the RFID chip");
                    if (pr_disconnectrfidcarda(hpr, cardlist[0])) lib_function_end();
                    else lib_displ_err();

The main loop ends:

        lib_process_end();
        lib_wait_for_sec(3);
    }

Closing the device:

    /* Closing the device */
    lib_function_start("Closing the device");
    if (pr_closedevice(hpr)) {
        lib_function_end();
    } else {
        lib_displ_err();
    }

Closing the Passport Reader system:

    /* Closing the PR system */
    lib_function_start("Closing the PR system");
    if (gx_closehandle(&hpr)) {
        lib_function_end();
    } else {
        lib_displ_err();
    }

The sample program ends printing some statistic information:

    return lib_print_stat();
}

The complete source code:

#include "prapi.h"
#include "gxsdldr.c"

#include "../__lib__.h"

/* The load_certificates helper function, loading the certificate files */
int load_certificates(gxHANDLE hpr)
{
    int i,l;
    char *pk;
    char **list = NULL;

    /* Loading certificates */
    l = lib_filelist("../../../data/certs", "*.cer", &list);
    for (i=0; i<l; i++) {
        lib_function_start("Loading sample certificate: %s", list[i]);
        if (pr_loadcertfilea(hpr, list[i], NULL)) lib_function_end(); else lib_displ_err();
        free(list[i]);
    }

    /* Loading CV certificates */
    l = lib_filelist("../../../data/certs", "*.cvcert", &list);
    for (i=0; i<l; i++) {
        lib_function_start("Loading sample CV certificate: %s", list[i]);
        pk = (char*)malloc(strlen(list[i]) - strlen("cvcert") + strlen("pkcs8") + 1);
        if (pk) {
            gx_strncpy(pk, list[i], strlen(list[i]) - strlen("cvcert") + 1);
            gx_strncpy(pk + strlen(list[i]) - strlen("cvcert"), "pkcs8", strlen("pkcs8") + 1);
        }
        if (pr_loadcertfilea(hpr, list[i], lib_isfile(pk) ? pk: NULL)) lib_function_end(); else lib_displ_err();
        free(list[i]);
        if (pk) free(pk);
    }

    return 0;
}

/* The make_bac helper function, reading MRZ from the document and using it to make BAC */
int make_bac(gxHANDLE hpr, char* card)
{
    int j,l;
    gxVARIANT pdoc;
    int pages;
    char *mrz[3];

    /* Setting only infra light for capture */
    lib_function_start("\t- Setting infra light");
    if (pr_getlightmask(hpr,&pages,PR_LIGHT_INFRA,0) && pr_setpagelight(hpr,1,(gxu32*)&pages)) lib_function_end();
    else return lib_displ_err();

    /* Capturing images */
    lib_function_start("\t- Capturing images");
    if (pr_capture(hpr)) lib_function_end();
    else return lib_displ_err();

    /* Reading MRZ */
    lib_function_start("\t- Reading MRZ");
    if (pr_getmrz(hpr, 0, PR_LIGHT_INFRA, PR_IT_ORIGINAL, &pdoc)) lib_function_end();
    else return lib_displ_err();

    if (!pdoc) {printf("No MRZ data found!\n"); return -1;}

    for (j=0; j<3; j++) {
        mrz[j] = (char*) malloc(45);
        memset(mrz[j], 0 ,45);
        l = 45;
        pr_getfieldfromdoca(hpr, pdoc, PR_DF_MRZ1 + j, mrz[j], &l, 0, 0);
    }

    gx_disposevariant(&pdoc);

    /* Making BAC */
    lib_function_start("\t- Making BAC");
    if (pr_makebaca(hpr, card, (const char **)mrz, strlen(mrz[2]) ? 3 : 2)) {
        for (j=0; j<3; j++) free(mrz[j]);
        lib_function_end();
    } else {
        for (j=0; j<3; j++) free(mrz[j]);
        return lib_displ_err();
    }

    return 0;
}

/* The resolve_dg1 helper function, parsing EF_DG1 and displaying MRZ information */
int resolve_dg1(gxHANDLE hpr, void * data, int sdata)
{
    int error_code = 0;
    gxVARIANT pdoc;
    char text[256];
    int stext;

    lib_function_start("\t- Resolving DG1");
    if (pr_resolverfiddata(hpr, data, sdata, &pdoc)) {
        if (!pdoc) lib_error("No MRZ data found!");
        else {
            lib_function_end();
            lib_write_line("\t- MRZ data:");
            stext = sizeof(text);
            if (pr_getfieldfromdoca(hpr, pdoc, PR_DF_RFID_MRZ, text, &stext, NULL, 0)) {
                char s[45];
                gx_snprintf(s, 44, text);
                s[44] = 0;
                lib_write_line("\t\t %s", s);
                gx_snprintf(s, 44, text+44);
                s[44] = 0;
                lib_write_line("\t\t %s", s);
            } else {
                error_code = lib_displ_err();
            }
            if (pdoc) gx_disposevariant(&pdoc);
        }
    } else {
        error_code = lib_displ_err();
    }

    return error_code;
}

/* The resolve_dg2 helper function, parsing EF_DG2 and saving the face image */
int resolve_dg2(gxHANDLE hpr, void * data, int sdata)
{
    int error_code = 0;
    gxVARIANT pdoc;
    gxIMAGE *img = NULL;

    lib_function_start("\t- Resolving");
    if (pr_resolverfiddata(hpr, data, sdata, &pdoc)) {
        if (!pdoc) lib_error("No image data found!");
        else {
            lib_function_end();
            lib_function_start("\t- Saving image");
            if (pr_getgximagefromdoc(hpr, pdoc, PR_DF_RFID_FACE, &img)) {
                if (gx_saveimagea(gx_direct(GX_CALL_GROUP_GX_IMAGE), img, "face.jpg", GX_JPEG)) lib_function_end();
                else error_code = lib_displ_err();
                gx_unrefimage(gx_direct(GX_CALL_GROUP_GX_IMAGE), img);
            } else {
                error_code = lib_displ_err();
            }
            if (pdoc) gx_disposevariant(&pdoc);
        }
    } else {
        error_code = lib_displ_err();
    }

    return error_code;
}

int main() {
    int i;
    char ** cardlist=0;
    int numcards=0;
    void * data=NULL;
    int sdata = 0, srfid_files = 4;
    unsigned int rfid_files = 0;
    char path[64], fn[32];
    gxVARIANT pdoc = NULL;

    /* Opening the PR system */
    gxHANDLE hpr;       /* handle for the PR system */
    lib_function_start("Opening system files");
    if (gx_openmodulea(&hpr,"prapi","default")) lib_function_end();
    else {
        lib_displ_err();
        return 0;
    }

    /* Connecting to the first device */
    lib_function_start("Connecting to the first device");
    if (pr_usedevicen(hpr,0,PR_UMODE_FULL_CONTROL)) {
        lib_function_end();
    } else {
        lib_displ_err();
        gx_closehandle(&hpr);
        return 0;
    }

    /* Loading certificates */
    lib_write_line("Loading certificates");
    load_certificates(hpr);

    while(!lib_kbhit()) {

        lib_process_start("RFID");

        /* Searching for RFID cards */
        lib_function_start("Searching for RFID cards ...");
        if (pr_getrfidcardlista(hpr, &cardlist, &numcards)) {
            lib_function_end();

            if (numcards == 0) {
                lib_write_line("No card found");
            } else {
                lib_write_line("");

                do {
                    /* Connecting to the first chip */
                    lib_function_start("Connecting to the RFID chip");
                    if (pr_connectrfidcarda(hpr, cardlist[0])) lib_function_end();
                    else {
                        lib_displ_err();
                        continue;
                    }

                    lib_write_line("Serial no.: %s", cardlist[0]);

                    /* Initializing chip reading */
                    lib_function_start("Initializing chip reading");
                    if (pr_getrfidfilea(hpr, cardlist[0], PR_RFID_EF_COM, &data, &sdata)) lib_function_end();
                    else {
                        lib_displ_err();
                        if (gx_geterrorcode() != GX_EACCES) continue;
                        if(make_bac(hpr, cardlist[0])) continue;
                        lib_function_start("Initializing chip reading");
                        if (pr_getrfidfilea(hpr, cardlist[0], PR_RFID_EF_COM, &data, &sdata)) lib_function_end();
                        else {lib_displ_err(); continue;}
                    }

                    /* Getting available files */
                    lib_function_start("\t- Available files");
                    gx_snprintf(path, sizeof(path), "C,D=%i/L,V=%i/C,D=%i", PRV_FIELDLIST, PR_DF_RFID_FIELDS|PR_DFE_DOCUMENT_DESCRIPTOR, PRV_RFIDDIR);
                    if (
                        !pr_resolverfiddata(hpr, data, sdata, &pdoc) ||
                        !gx_convertvariantbypatha(pdoc, path, 0, GX_VARIANT_INT, &srfid_files, 0, &rfid_files, srfid_files)
                        ) {
                            lib_displ_err();
                            if (pdoc) gx_disposevariant(&pdoc);
                            if (data) {gx_globalfree(data); data = NULL; sdata = 0;}
                            continue;
                    }
                    if (pdoc) gx_disposevariant(&pdoc);
                    if (data) {gx_globalfree(data); data = NULL; sdata = 0;}

                    for (i=PR_RFID_EF_DG1; i<=PR_RFID_EF_DG16; i++)
                        if (((1<<i) & rfid_files)) lib_write("DG%i ", i);
                    lib_function_end();

                    /* Making Passive Authentication */
                    lib_function_start("\t- Making Passive Authentication");
                    if (pr_makepassiveautha(hpr, cardlist[0])) lib_function_end();
                    else lib_displ_err();

                    /* Making Active Authentication */
                    if ((1 << PR_RFID_EF_DG15) & rfid_files) {
                        lib_function_start("\t- Making Active Authentication");
                        if (pr_makeactiveautha(hpr, cardlist[0])) lib_function_end();
                        else lib_displ_err();
                    }

                    /* Reading available files, saving and resolving them */
                    for (i=PR_RFID_EF_DG1; i<=PR_RFID_EF_DG16; i++) {
                        if (i == PR_RFID_EF_DG3 || i == PR_RFID_EF_DG4) continue;
                        if (!((1<<i) & rfid_files)) continue;
                        gx_snprintf(fn, 32, "EF_DG%i.dat", i);
                        lib_function_start("Reading %s", fn);
                        if (pr_getrfidfilea(hpr, cardlist[0], i, &data, &sdata)) lib_function_end();
                        else {lib_displ_err(); continue;}
                        lib_function_start("\t- Saving %s", fn);
                        if (!lib_save(fn, data, sdata)) lib_error("File write error!");
                        else lib_function_end();
                        if (i == PR_RFID_EF_DG1) resolve_dg1(hpr, data, sdata);
                        if (i == PR_RFID_EF_DG2) resolve_dg2(hpr, data, sdata);
                        if (data) {gx_globalfree(data); data = NULL; sdata = 0;}
                    }

                    /* Disconnecting from the chip */
                    lib_function_start("Disconnecting from the RFID chip");
                    if (pr_disconnectrfidcarda(hpr, cardlist[0])) lib_function_end();
                    else lib_displ_err();

                } while(false);

            }
            if (cardlist) {gx_globalfree(cardlist); cardlist = NULL;}
        } else {
            lib_displ_err();
        }

        lib_process_end();
        lib_wait_for_sec(3);
    }

    /* Closing the device */
    lib_function_start("Closing the device");
    if (pr_closedevice(hpr)) {
        lib_function_end();
    } else {
        lib_displ_err();
    }

    /* Closing the PR system */
    lib_function_start("Closing the PR system");
    if (gx_closehandle(&hpr)) {
        lib_function_end();
    } else {
        lib_displ_err();
    }

    return lib_print_stat();
}

pr_rfid_eac - EAC RFID handling example

Show how to read data from an EAC RFID chip.

The needed gxsdldr.c loader file is included directly:

The __lib__.h file contains some library functions used only in the sample programs, such as the lib_function_start and lib_function_end functions that implement the simple command line interface and measures the elapsed time between the two function calls.

The load_certificates helper function, loading the certificate files:

The make_bac helper function, reading MRZ from the document and using it to make BAC:

The resolve_dg1 helper function, parsing EF_DG1 and displaying MRZ information:

The resolve_dg2 helper function, parsing EF_DG2 and saving the face image:

The main function:

Opening the Passport Reader system:

Connecting to the first device. If no device is connected then the pr_usedevicen() function returns false and the program ends:

Loading the certificates for authentication:

The main loop begins:

Searching for RFID cards:

Connecting to the first chip:

Reading EF_COM first to determine the available files on the chip. In case of BAC protected chip the reading process returns GX_EACCES, which means that the Basic Access Control procedure must be executed in order to access the chip.

Parsing the EF_COM and getting the information about the available files on the chip:

Making Chip Authentication if EF_DG14 exists:

Making Passive Authentication to check the integrity of the chip data:

Making Active Authentication if EF_DG15 exists:

Making Terminal Authentication if EF_DG14 exists:

Reading available files, checking the hash, saving and resolving them:

Disconnecting from the chip:

The main loop ends:

Closing the device:

Closing the Passport Reader system:

The sample program ends printing some statistic information:

The complete source code:


Generated  for Passport Reader
(c) ADAPTIVE RECOGNITION