#include <stdio.h>
#include <string.h>
#include "demo_common.h"

extern IDT_COMMON_PROCESS COMMON;
extern IDT_PROCESS idtech_process;
extern IDT_DEMO_LIB_DISPLAY_MENU idtech_display_menu_from_lib;

void
_NEO2_display_device_menu();
// void _NEO2_display_device_type_menu();
// extern void getDUKPT(int type);

#if defined(WIN32) || defined(__MACH__)
EXPORT_SYMBOLS int isDeviceTransaction = 0;
#else
SHARED_SYMBOLS int isDeviceTransaction;
#endif

void
WorldPayCallback(char * message, int returnCode, int emvCode) {
    printf("WORLDPAY RESPONSE>>>>>>>\n");
    printf("Return Code = %d\n", returnCode);
    printf("EMV Code = %d\n", emvCode);
    printf("Message = \n%s\n", message);
    //	 _NEO2_display_device_menu();
    if (idtech_display_menu_from_lib.pDisplay_Menu_current) {
        idtech_display_menu_from_lib.pDisplay_Menu_current();
        printf("Please Input your Selection. (0 - exit current menu)\n");
    }
}

void
_NEO2_process_device() {
    int choice;
    int r = 0;
    char str1[256] = { 0 };
    int len        = 512;

    emv_setAutoAuthenticateTransaction(1);
    emv_setAutoCompleteTransaction(1);
    do {
        _NEO2_display_device_menu();
        choice = COMMON.inputSelection();

        if (device_getL100PassThroughMode() == 1) {
            switch (choice) {
                case 1: {
                    printf(">>1. Get Firmware Version\n");
                    fflush(stdout);
                    r = device_getFirmwareVersion(str1);
                    if (r != RETURN_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getResponseCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Get Firmware Version Failed! ErrorCode: 0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        char str2[200] = { 0 };
                        sprintf(str2, "Firmware version: %s\n", str1);
                        printf(str2);
                    }
                    fflush(stdout);
                }
                break;
                case 2: {
                    printf(">>2. Reboot Device\n");
                    fflush(stdout);
                    r = device_rebootDevice();
                    if (r != RETURN_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getResponseCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Do device_rebootDevice(), failed! ErrorCode:0x%02x ,Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Reboot Device Success!");
                    }
                    fflush(stdout);
                }
                break;
                case 3: {
                    printf(">>3. Send Command\n");
                    fflush(stdout);
                    BYTE bbyte[5] = { 0x00 };
                    int cmdlen;
                    BYTE cmdData[_DATA_BUF_LEN] = { 0x00 };
                    int cmdDataLen;
                    bbyte[0] = 0x78;
                    bbyte[1] = 0x31;
                    cmdlen   = 2;
                    BYTE rbbyte[512] = { 0 };
                    memset(rbbyte, 0, 512);
                    len = 512;

                    r = device_SendDataCommand(bbyte, cmdlen, NULL, 0, rbbyte, &len);
                    if (r != RETURN_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getResponseCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Do device_SendDataCommand(), failed! ErrorCode:0x%02x ,Info: %s ----- \n", r,
                            strErr);
                    } else {
                        char str3[1024] = { 0 };
                        memset(str3, 0, 1024);
                        COMMON.convertBytesIntoHexStr(rbbyte, len, 0, str3);
                        printf("response code : %s\n", str3);
                    }
                    fflush(stdout);
                }
                break;
                case 4:
                    printf(">>4. Get Key Status\n");
                    fflush(stdout);
                    {
                        int newFormat    = 0;
                        BYTE status[100] = { 0 };
                        int statusLen    = 100;
                        int rt = device_getKeyStatus(&newFormat, status, &statusLen);
                        if (0 == newFormat && rt == RETURN_CODE_DO_SUCCESS && statusLen > 0) {
                            printf("Get Key Status succeeded:\r\n");
                            if (status[0] == 0x01) {
                                printf("\tPIN DUKPT Key Loaded\r\n");
                            } else if (status[0] == 0xFF) {
                                printf("\tPIN DUKPT Key STOP\r\n");
                            } else {
                                printf("\tPIN DUKPT Key NOT Loaded\r\n");
                            }
                            if (status[1] == 0x01) {
                                printf("\tPIN Master Key Loaded\r\n");
                            } else {
                                printf("\tPIN Master Key NOT Loaded\r\n");
                            }
                            if (status[2] == 0x01) {
                                printf("\tStandard PIN Session Key Loaded\r\n");
                            } else {
                                printf("\tStandardPIN Session Key NOT Loaded\r\n");
                            }
                            if (status[3] == 0x01) {
                                printf("\tDesjardins PIN Session Key Loaded\r\n");
                            } else {
                                printf("\tDesjardins PIN Session Key NOT Loaded\r\n");
                            }
                            if (status[4] == 0x01) {
                                printf("\tMSR DUKPT Key Loaded\r\n");
                            } else if (status[4] == 0xFF) {
                                printf("\tMSR DUKPT Key STOP\r\n");
                            } else {
                                printf("\tMSR DUKPT Key NOT Loaded\r\n");
                            }
                            if (status[5] == 0x01) {
                                printf("ICC DUKPT Key Loaded\r\n");
                            } else if (status[5] == 0xFF) {
                                printf("\tICC DUKPT Key STOP\r\n");
                            } else {
                                printf("\tICC DUKPT Key NOT Loaded\r\n");
                            }
                            if (status[6] == 0x01) {
                                printf("\tAdmin Key Loaded\r\n");
                            } else if (status[6] == 0xFF) {
                                printf("\tAdmin Key STOP\r\n");
                            } else {
                                printf("\tAdmin Key NOT Loaded\r\n");
                            }
                            if (status[7] == 0x01) {
                                printf("\tData DUKPT Key Loaded\r\n");
                            } else if (status[7] == 0xFF) {
                                printf("\tData DUKPT Key STOP\r\n");
                            } else {
                                printf("\tData DUKPT Key NOT Loaded\r\n");
                            }
                            if (status[8] == 0x01) {
                                printf("\tMAC DUKPT Key Loaded\r\n");
                            } else if (status[8] == 0xFF) {
                                printf("\tMAC DUKPT Key STOP\r\n");
                            } else {
                                printf("\tMAC DUKPT Key NOT Loaded\r\n");
                            }
                        } else {
                            char strErr[200] = { 0 };
                            memset(strErr, 0, 200);
                            device_getResponseCodeString(r, strErr);
                            printf(
                                ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n	----- Do device_getKeyStatus(), failed! ErrorCode:0x%02x ,Info: %s ----- \n", r,
                                strErr);
                        }
                        fflush(stdout);
                    }
                    break;
                case 5: {
                    printf(">>5. Set Date/Time\n");
                    int r = device_setDateTime();
                    if (r == RETURN_CODE_DO_SUCCESS) {
                        printf("Set Date Time Successful.\r\n");
                    } else {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getResponseCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Do device_setDateTime(), failed! ErrorCode:0x%02x ,Info: %s ----- \n", r,
                            strErr);
                    }
                }
                break;
                case 6: {
                    printf(">>6. Get Date/Time\n");
                    fflush(stdout);
                    BYTE dateTime[6] = { 0 };

                    r = device_getDateTime(dateTime);
                    if (r != RETURN_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getResponseCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Do device_SendDataCommand(), failed! ErrorCode:0x%02x ,Info: %s ----- \n", r,
                            strErr);
                    } else {
                        char str3[50] = { 0 };
                        memset(str3, 0, 50);
                        COMMON.convertBytesIntoHexStr(dateTime, 6, 0, str3);
                        printf("response code : %s\n", str3);
                    }
                    fflush(stdout);
                }
                break;
                case 7:
                    printf(">>7. Disable L100 Passthrough\n");
                    fflush(stdout);
                    r = device_enableL100PassThrough(0);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- L100 Pass Through On Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("L100 Pass Through On Succeeded\n");
                    }
                    fflush(stdout);
                    break;
                case 0:
                    printf(">>0.Back To Main Menu\n");
                    fflush(stdout);
                    break;
            }
        } else {
            switch (choice) {
                case 1: {
                    BYTE data[]      = { 0x01 };
                    BYTE rbbyte[512] = { 0 };
                    len = 512;
                    device_SendDataCommandNEO(0x61, 0x33, data, 1, rbbyte, &len); // set Cancel button on

                    printf(">>1. Start Transaction\n");
                    fflush(stdout);

                    r = device_startTransaction(1.00, 0.00, 0, 30, NULL, 0); // default

                    //				BYTE data[] = {0xff, 0xee, 0x08, 0x0a, 0xdf, 0xef, 0x1a, 0x01, 0x0a, 0xdf, 0xed, 0x28, 0x01, 0x00, 0xff, 0xee, 0x0e, 0x00};
                    //				r = device_startTransaction(1.00, 0.00, 0, 30, data, 18);

                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS && r != IDG_P2_STATUS_CODE_REQUEST_ONLINE_AUTHORIZATION &&
                      r != IDG_P2_STATUS_CODE_OK_AND_HAVE_NEXT_COMMAND) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Start Transaction Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Start Transaction Succeeded\n");
                        if (r == IDG_P2_STATUS_CODE_OK_AND_HAVE_NEXT_COMMAND) {
                            printf("Please Use Card...\n");
                            isDeviceTransaction = 1;
                        }
                    }
                    fflush(stdout);
                }
                break;
                case 2:
                    printf(">>2. Cancel Transaction\n");
                    fflush(stdout);
                    r = device_cancelTransaction(); // default

                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Cancel Transaction Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Cancel Transaction successfully\n");
                    }
                    fflush(stdout);
                    break;
                case 3: {
                    printf(">>3. Get Transaction Results\n");
                    fflush(stdout);
                    IDTMSRData cardData;
                    resetMSRData(&cardData);
                    r = device_getTransactionResults(&cardData);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Get Transaction Result Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        COMMON.printMSRData(&cardData);
                    }
                    fflush(stdout);
                }
                break;
                case 4: {
                    printf(">>4. Get Firmware Version\n");
                    fflush(stdout);
                    r = device_getFirmwareVersion(str1);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Get Firmware Version Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        char str2[256] = { 0 };
                        sprintf(str2, "Firmware version: %s\n", str1);
                        printf(str2);
                        if (strstr(str1, "VP6800") != NULL || strstr(str1, "VP8810") != NULL) {
                            memset(str1, 0, 256);
                            memset(str2, 0, 256);
                            len = 256;
                            r   = device_SendDataCommandNEO(0x29, 0x80, NULL, 0, (BYTE *) str1, &len);
                            if (r == IDG_P2_STATUS_CODE_DO_SUCCESS) {
                                sprintf(str2, "RT1050 Firmware version: %s\n", str1);
                                printf(str2);
                            }
                        }
                    }
                    fflush(stdout);
                }
                break;
                case 5: {
                    printf(">>5. Send Command: 0x29, 0x00\n");
                    fflush(stdout);
                    BYTE rbbyte[512] = { 0 };
                    memset(rbbyte, 0, 512);
                    len = 512;
                    r = device_SendDataCommandNEO(0x29, 0x00, NULL, 0, rbbyte, &len); // default

                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Do device_SendDataCommand(), failed! ErrorCode:0x%02x ,Info: %s ----- \n", r,
                            strErr);
                    } else {
                        char str3[1024] = { 0 };
                        memset(str3, 0, 1024);
                        COMMON.convertBytesIntoHexStr(rbbyte, len, 0, str3);
                        printf("response code : %s\n", str3);
                    }
                    fflush(stdout);

                    //					printf(">>5. Get Camera Parameters\n");
                    //					fflush(stdout);
                    //					BYTE isAutoFocus;
                    //					BYTE focalLength;
                    //					r = device_getCameraParameters(&isAutoFocus, &focalLength);
                    //
                    //					if ( r != IDG_P2_STATUS_CODE_DO_SUCCESS ) {
                    //						char strErr[200] = {0};
                    //						memset(strErr,0,200);
                    //						device_getIDGStatusCodeString(r, strErr);
                    //						printf(">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Do device_getCameraParameters(), failed! ErrorCode:0x%02x ,Info: %s ----- \n",r,strErr);
                    //					}
                    //					else{
                    //						printf("isAutoFocus %d\n", isAutoFocus);
                    //						printf("focalLength %02X\n", focalLength);
                    //					}
                    //					fflush(stdout);
                }
                break;
                case 6: {
                    printf(">>6. Get Serial Number\n");
                    fflush(stdout);
                    r = config_getSerialNumber(str1);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Get Serial Number Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        char str2[200] = { 0 };
                        sprintf(str2, "Serial Number: %s\n", str1);
                        printf(str2);
                    }
                    fflush(stdout);

                    //				printf(">>6. Set Camera Parameters\n");
                    //				fflush(stdout);
                    //				BYTE isAutoFocus = 0;
                    //				BYTE focalLength = 258;
                    //
                    //				printf("focalLength %d, focalLength 0x%X\n", focalLength, focalLength);
                    //				r = device_setCameraParameters(isAutoFocus, focalLength);
                    //
                    //				if ( r != IDG_P2_STATUS_CODE_DO_SUCCESS ) {
                    //					char strErr[200] = {0};
                    //					memset(strErr,0,200);
                    //					device_getIDGStatusCodeString(r, strErr);
                    //					printf(">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Do device_getCameraParameters(), failed! ErrorCode:0x%02x ,Info: %s ----- \n",r,strErr);
                    //				}
                    //				else{
                    //					printf("Set Camera Parameters Succeeded\n");
                    //				}
                    //				fflush(stdout);
                }
                break;
                case 7: {
                    printf(">>7. Ping Device\n");
                    fflush(stdout);
                    r = device_pingDevice();
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Ping Device Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Ping Device Succeeded\n");
                    }
                    fflush(stdout);
                }
                break;
                case 8:
                    printf(">>8. Interface Control\n");
                    fflush(stdout);
                    BYTE values[4] = { 0xFF, 0x04, 0xFF, 0x01 };
                    r = device_controlUserInterface(values);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Interface Control Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Interface Control Succeeded\n");
                    }
                    fflush(stdout);
                    break;
                case 9:
                    printf(">>9. Pass Through On\n");
                    fflush(stdout);
                    r = device_enablePassThrough(1);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Pass Through On Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Pass Through On Succeeded\n");
                    }
                    fflush(stdout);
                    break;
                case 10:
                    printf(">>10. Pass Through Off\n");
                    fflush(stdout);
                    r = device_enablePassThrough(0);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Pass Through Off Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Pass Through Off Succeeded\n");
                    }
                    fflush(stdout);
                    break;
                case 11:
                    printf(">>11. Set Burst On\n");
                    fflush(stdout);
                    r = device_setBurstMode(1);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Set Burst On Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Set Burst On Succeeded\n");
                    }
                    fflush(stdout);
                    break;
                case 12:
                    printf(">>12. Set Burst Off\n");
                    fflush(stdout);
                    r = device_setBurstMode(0);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Set Burst Off Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Set Burst Off Succeeded\n");
                    }
                    fflush(stdout);
                    break;

                case 13:
                    printf(">>13. Set Auto Poll On\n");
                    fflush(stdout);
                    r = device_setPollMode(0);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Set Auto Poll On Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Set Auto Poll On Succeeded\n");
                    }
                    fflush(stdout);
                    break;
                case 14:
                    printf(">>14. Poll On Demand\n");
                    fflush(stdout);
                    r = device_setPollMode(1);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Poll On Demand Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Set Poll On Demand Succeeded\n");
                    }
                    fflush(stdout);
                    break;
                case 15:
                    printf(">>15. Set Merchant Record\n");
                    fflush(stdout);
                    r = device_setMerchantRecord(1, 1, "pass.com.firstdata.money2020", null);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Set Merchant Record Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Set Merchant Record Succeeded\n");
                    }
                    fflush(stdout);
                    break;
                case 16:
                    printf(">>16. Get Merchant Record\n");
                    fflush(stdout);
                    BYTE record[0x63];
                    memset(record, 0, 0x63);
                    r = device_getMerchantRecord(1, record);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Get Merchant Record Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Get Merchant Record Succeeded\n");
                        int i;
                        printf("Record:\n");
                        for (i = 0; i < 0x63; i++) {
                            printf("%02X", record[i]);
                        }
                        printf("\n");
                    }
                    fflush(stdout);
                    break;
                case 17:
                    printf(">>17. Enable L100 Passthrough\n");
                    fflush(stdout);
                    r = device_enableL100PassThrough(1);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- L100 Pass Through On Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("L100 Pass Through On Succeeded\n");
                        //					isL100Passthrough = 1;
                    }
                    fflush(stdout);
                    break;
                case 18: {
                    printf(">>18. Transfer File\n");
                    printf("Please enter the source file name:\n");
                    fflush(stdout);
                    char in_file_name[128];
                    fgets(in_file_name, 128, stdin);
                    int i;
                    for (i = 0; i < 128; i++) {
                        if (in_file_name[i] == '\n' || in_file_name[i] == '\r') {
                            in_file_name[i] = '\0';
                            break;
                        }
                    }

                    printf("Please enter the destination file name:\n");
                    fflush(stdout);
                    char file_name[128];
                    fgets(file_name, 128, stdin);
                    for (i = 0; i < 128; i++) {
                        if (file_name[i] == '\n' || file_name[i] == '\r') {
                            file_name[i] = '\0';
                            break;
                        }
                    }

                    // Read in the file
                    int fileDataLen;

                    FILE * fp;
                    if (NULL == (fp = fopen(in_file_name, "rb"))) {
                        printf("Could not open file %s\n", in_file_name);
                        fflush(stdout);
                        break;
                    }

                    fseek(fp, 0, SEEK_END);
                    fileDataLen = ftell(fp);
                    if (fileDataLen <= 0) {
                        printf("File is empty\n");
                        fflush(stdout);
                        break;
                    }

                    BYTE fileData[fileDataLen];
                    fseek(fp, 0, SEEK_SET);
                    fread(fileData, fileDataLen, 1, fp);
                    fclose(fp);

                    r = device_transferFile(file_name, strlen(file_name), fileData, fileDataLen);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Transfer File Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Transfer File Succeeded\n");
                    }
                    fflush(stdout);
                }
                break;
                case 19: {
                    printf(">>19. Query File\n");
                    fflush(stdout);
                    printf("Please enter the directory name (maximum 31 characters):\n");
                    fflush(stdout);
                    char dir_name[32];
                    fgets(dir_name, 32, stdin);
                    int i;
                    for (i = 0; i < 31; i++) {
                        if (dir_name[i] == '\n' || dir_name[i] == '\r') {
                            dir_name[i] = '\0';
                            break;
                        }
                    }
                    dir_name[31] = '\0';
                    int dir_name_len = strlen(dir_name);

                    printf("Please enter the file name (maximum 31 characters):\n");
                    fflush(stdout);
                    char file_name[32];
                    fgets(file_name, 32, stdin);
                    for (i = 0; i < 31; i++) {
                        if (file_name[i] == '\n' || file_name[i] == '\r') {
                            file_name[i] = '\0';
                            break;
                        }
                    }
                    file_name[31] = '\0';
                    int file_name_len = strlen(file_name);
                    BYTE timeStamp[6] = { 0 };
                    int timeStampLen  = 6;
                    char fileSize[50] = { 0 };
                    int fileSizeLen   = 50;
                    int isExist       = 0;
                    r = device_queryFile(dir_name, dir_name_len, file_name, file_name_len, &isExist, timeStamp,
                        &timeStampLen, fileSize, &fileSizeLen);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Query File Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Query File Succeeded\n");
                        printf("File Exist: %s\n", (isExist == 1) ? "TRUE" : "FALSE");
                        if (isExist == 1) {
                            if (timeStampLen == 6) {
                                printf("Timestamp: 20%02X/%02X/%02X %02X:%02X:%02X\n", timeStamp[0], timeStamp[1],
                                  timeStamp[2], timeStamp[3], timeStamp[4], timeStamp[5]);
                            }
                            printf("File Size: %s\n", fileSize);
                        }
                    }
                    fflush(stdout);
                }
                break;
                case 20: {
                    printf(">>20. Delete File\n");

                    printf("Please enter the file name:\n");
                    fflush(stdout);
                    char file_name[128];
                    fgets(file_name, 128, stdin);
                    int i;
                    for (i = 0; i < 128; i++) {
                        if (file_name[i] == '\n' || file_name[i] == '\r') {
                            file_name[i] = '\0';
                            break;
                        }
                    }

                    r = device_deleteFile(file_name, strlen(file_name));
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Delete File Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Delete File Succeeded\n");
                    }
                    fflush(stdout);
                }
                break;
                case 21: {
                    printf(">>21. List Directory\n");
                    fflush(stdout);
                    char ssDirectory[_CMD_BUF_LEN * 8];
                    int ssDirectoryLen = _CMD_BUF_LEN * 8;
                    memset(ssDirectory, 0, _CMD_BUF_LEN * 8);
                    r = device_listDirectory(NULL, 0, 1, 0, ssDirectory, &ssDirectoryLen); // default

                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- List Directory Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("List Directory Succeeded\n");
                        int i;
                        for (i = 0; i < ssDirectoryLen; i++) {
                            if (ssDirectory[i] == ',') {
                                printf("\n");
                            } else {
                                printf("%c", ssDirectory[i]);
                            }
                        }
                        printf("\n");
                    }
                    fflush(stdout);
                }
                break;
                case 22: {
                    printf(">>22. Start Scanning QR Code\n");
                    fflush(stdout);
                    r = device_startQRCodeScan(30);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS && r != IDG_P2_STATUS_CODE_OK_AND_HAVE_NEXT_COMMAND) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Start Scanning QR Code Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Start Scanning QR Code Succeeded\n");
                        printf("Please Scan the QR Code...\n");
                    }
                    fflush(stdout);
                }
                break;
                case 23: {
                    printf(">>23. Stop Scanning QR Code\n");
                    fflush(stdout);
                    r = device_stopQRCodeScan();
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Stop Scanning QR Code Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Stop Scanning QR Code Succeeded\n");
                    }
                    fflush(stdout);
                }
                break;
                case 24: {
                    printf(">>24. Start Taking Photo\n");
                    fflush(stdout);
                    r = device_startTakingPhoto(30);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS && r != IDG_P2_STATUS_CODE_OK_AND_HAVE_NEXT_COMMAND) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Start Taking Photo Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Start Taking Photo Succeeded\n");
                        printf("Please press the button to take a picture...\n");
                    }
                    fflush(stdout);
                }
                break;
                case 25: {
                    printf(">>25. Stop Taking Photo\n");
                    fflush(stdout);
                    r = device_stopTakingPhoto();
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Stop Taking Photo Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Stop Taking Photo Succeeded\n");
                    }
                    fflush(stdout);
                }
                break;
                case 26: {
                    printf(">>26. Start Remote Key Injection\n");
                    char option[10] = { 0 };
                    while (option[0] != '0' && option[0] != '1') {
                        printf("Please enter 0 for Demo unit or 1 for Production unit:\n");
                        fflush(stdout);
                        fgets(option, 10, stdin);
                    }
                    int opt = 0;
                    if (option[0] == '1') {
                        opt = 1;
                    }
                    r = device_startRKI(NULL, opt);

                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Remote Key Injection Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Start Remote Key Injection, please wait...\n");
                    }
                    fflush(stdout);
                }
                break;
                case 27:
                    printf(">>27.WorldPay Transaction\n");

                    WorldPayData data;
                    strcpy(data.accountID, "1188346\0");
                    strcpy(data.accountToken,
                      "E1EB3EFB049DFB599F1CB454E1CFC4FD14BF90BCE74456AE9E9490D7D609B466C81A3801\0");
                    strcpy(data.acceptorID, "364798674\0");
                    data.transactionType = TRANSACTION_TYPE_SALE;
                    // data.transactionType = TRANSACTION_TYPE_PRE_AUTH;
                    // data.transactionType = TRANSACTION_TYPE_COMPLETION;
                    // data.transactionType = TRANSACTION_TYPE_VOID;
                    // data.transactionType = TRANSACTION_TYPE_RETURN;
                    strcpy(data.amount, "22.00\0");                 // specify transaction Amount
                    data.timeout = 30;                              // Timeout for transaction
                    data.isTest  = 1;                               // if test transaction, set to TRUE.  If live transactions, set to FALSE
                    data.msrOnly = 0;                               // for EMV + MSR, set to FALSE.  If MSR swipe only, set to TRUE
                    strcpy(data.transactionID, "3830\0");           // required if COMPLETION, VOID, RETURN.  Otherwise, leave blank
                    strcpy(data.referenceNumber, "112233445566\0"); // required value. Set a reference number
                    strcpy(data.terminalID, "12345\0");             // required value.  Set a terminal identifer
                    strcpy(data.ticketNumber, "54321\0");           // required value. Set a ticket number
                    data.duplicateCheck    = 0;                     // set to TRUE if you want to check for duplicate transactions
                    data.duplicateOverride = 1;                     // set to TRUE if you want to allow duplicate charges to same card

                    int requestMode = 1; // 0 = Return Gateway Response
                                         // 1 = Return Request + Gateway Response
                                         // 2 = Return Request Only

//                    r = pingWorldPay(data.isTest, 10);
//                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
//                        char strErr[200] = { 0 };
//                        memset(strErr, 0, 200);
//                        device_getIDGStatusCodeString(r, strErr);
//                        printf(
//                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Ping WP Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
//                            strErr);
//                    } else {
//                        printf("Ping WP Succeeded\n");
//                    }

                    r = executeTransaction(&data, WorldPayCallback, requestMode);
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        char strErr[200] = { 0 };
                        memset(strErr, 0, 200);
                        device_getIDGStatusCodeString(r, strErr);
                        printf(
                            ">>>>>>>>>>>>FAIL<<<<<<<<<<<<< \n   ----- Execute WP Transaction Failed! ErrorCode:0x%02x, Info: %s ----- \n", r,
                            strErr);
                    } else {
                        printf("Execute Transaction Succeeded\n");
                    }
                    fflush(stdout);
                    break;
                case 28: {
                     printf(">>28. Cancel WorldPay Transaction\n");
                     r = cancelWorldPay();
                     if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                         printf("  Do cancelWorldPay(), failed! Error Code: %04X\n", r);
                     } else {
                         printf("Cancel WorldPay Transaction Succeeded\n");
                     }
                     fflush(stdout);
                    }
                    break;
                case 29: {
                    printf(">>29. Update Firmware\n");
                    char firmware_file_name[50];
                    BYTE *firmwareBinData = NULL;
                    printf("Please enter the firmware file name (Ex. VP5300_v1.00.021.0XXX.S_Test.fm):\n");
                    fflush(stdout);
                    fgets(firmware_file_name, 50, stdin);
                    int i;
                    for (i = 0; i < 50; i++) {
                        if (firmware_file_name[i] == '\n' || firmware_file_name[i] == '\r') {
                            firmware_file_name[i] = '\0';
                            break;
                        }
                    }
                    printf("Firmware File Name: %s\n", firmware_file_name);
                    FILE * fp;
                    if (strstr(firmware_file_name, ".txt") != NULL) {
                        if (NULL == (fp = fopen(firmware_file_name, "r"))) {
                            printf("Could not open file %s\n", firmware_file_name);
                            fflush(stdout);
                            break;
                        }
                        fflush(stdout);

                        char firmwareData[_FIRMWARE_BUF_LEN];
                        memset(firmwareData, 0, _FIRMWARE_BUF_LEN);
                        int fw_lines = 0;
                        int idx      = 0;
                        char * line  = firmware_file_name;
                        char temp[_FIRMWARE_CMD_LEN];
                        while (!feof(fp) && strcmp(line, "END>")) {
                            if (idx >= _FIRMWARE_BUF_LEN) {
                                break;
                            }
                            memset(temp, 0, _FIRMWARE_CMD_LEN);
                            fgets(temp, _FIRMWARE_CMD_LEN, fp);
                            for (i = (_FIRMWARE_CMD_LEN) -1; i >= 0; i--) {
                                if (temp[i] == '\n' || temp[i] == '\r') {
                                    temp[i] = '\0';
                                    break;
                                }
                            }
                            line = temp;
                            strcpy(&(firmwareData[idx]), temp);
                            fw_lines++;
                            idx += strlen(temp) + 1;
                        }
                        fclose(fp);
                        if (idx >= _FIRMWARE_BUF_LEN) {
                            printf("Not enough buffer\n");
                            fflush(stdout);
                            break;
                        }
                        printf("\033[1;31mUpdating firmware, please do not unplug the reader or exit this demo...\033[0m\n");
                        fflush(stdout);
                        r = device_updateFirmware(firmwareData, idx, firmware_file_name, 0, NULL, 0);
                    } else {
                        if (NULL == (fp = fopen(firmware_file_name, "rb"))) {
                            printf("Could not open file %s\n", firmware_file_name);
                            fflush(stdout);
                            break;
                        }

                        int fw_size = 0;

                        fseek(fp, 0, SEEK_END);
                        fw_size = ftell(fp);

//                        BYTE firmwareData[fw_size];
                        firmwareBinData = (BYTE *)malloc(fw_size);
                        if (firmwareBinData == NULL) {
                            printf("Can not allocate memory for firmware Update\n");
                            break;
                        }

                        memset(firmwareBinData, 0, fw_size);

                        fseek(fp, 0, SEEK_SET);
                        fread(firmwareBinData, fw_size, 1, fp);
                        fclose(fp);

                        printf("Firmware file size: %d\n", fw_size);
                        printf(
                            "\033[1;31mUpdating firmware, please do not unplug the reader or close this program...\033[0m\n");
                        fflush(stdout);
                        r = device_updateFirmware(firmwareBinData, fw_size, firmware_file_name, 0, NULL, 0);
                    }
                    if (r != IDG_P2_STATUS_CODE_DO_SUCCESS) {
                        if (r == IDG_P2_STATUS_CODE_FW_INIT_SUCCESS) {
                            printf(
                                "\033[1;31mInitialize Firmware Update succeeded.\nFor USB, please exit the demo, unplug and replug the reader, relaunch the demo, select the reader FW_UPDATE, and do Update Firmware again.\nFor RS232, please do firmware update again.\033[0m\n");
                        } else {
                            printf("\033[1;31mFirmware Update failed!\033[0m\n");
                            printf("Error code: 0x%04X\n", r);
                        }
                    } else {
                        printf(
                            "\033[1;31mFirmware Update succeeded.  Please exit the demo, unplug and replug the reader.\033[0m\n");
                    }
                    if (firmwareBinData != NULL) {
                        free(firmwareBinData);
                        firmwareBinData = NULL;
                    }
                    fflush(stdout);
                }
                break;
                case 30: {
                    printf(">>30. Update Firmware with zip file\n");
                    char firmware_zipfile_name[50];
                    printf("Please enter the firmware zip file name (Ex. package_VP6300 FW v1.01.003.0432.T.zip):\n");
                    fflush(stdout);
                    fgets(firmware_zipfile_name, 50, stdin);
                    int i;
                    for (i = 0; i < 50; i++) {
                        if (firmware_zipfile_name[i] == '\n' || firmware_zipfile_name[i] == '\r') {
                            firmware_zipfile_name[i] = '\0';
                            break;
                        }
                    }
                    r = device_updateFirmwareWithZipFile(firmware_zipfile_name, strlen(firmware_zipfile_name));
                    if (r != RETURN_CODE_DO_SUCCESS) {
                        printf("Firmware Update failed!\n");
                        printf("Error code: 0x%04X\n", r);
                    } else {
                        printf(
                            "Firmware Update succeeded.\n");
                    }
                    fflush(stdout);
                }
                break;
                case 31: {
                    printf(">>31. Set Config by JSON file\n");
                    char json_file_name[50];
                    printf("Please enter the config json file name (Ex. VP6800Config.json):\n");
                    fflush(stdout);
                    fgets(json_file_name, 50, stdin);
                    int i;
                    for (i = 0; i < 50; i++) {
                        if (json_file_name[i] == '\n' || json_file_name[i] == '\r') {
                            json_file_name[i] = '\0';
                            break;
                        }
                    }
                    r = config_setConfigByJsonFile(json_file_name, strlen(json_file_name));
                    if (r != RETURN_CODE_DO_SUCCESS) {
                        printf("Set Config by JSON file failed!\n");
                        printf("Error code: 0x%04X\n", r);
                    } else {
                        printf("Set Config by JSON file succeeded.\n");
                    }
                    fflush(stdout);
                }
                break;
                case 0:
                    printf(">>0.Back To Main Menu\n");
                    fflush(stdout);
                    break;
            }
        }
    } while (choice != 0);
    // #ifdef WIN32
    if (choice == 0) {
//        idtech_process.pProcess_function_list();
        return;
    }
    // #endif
} /* _NEO2_process_device */

void
_NEO2_display_device_menu() {
    idtech_display_menu_from_lib.pDisplay_Menu_current = _NEO2_display_device_menu;

    if (device_getL100PassThroughMode() == 1) {
        printf("\t\t************* Device Options [L100]*************\n");
        printf("\t\t0.  Back To Main Menu\n");
        printf("\t\t1.  Get Firmware Version\n");
        printf("\t\t2.  Reboot Device\n");
        printf("\t\t3.  Send Command\n");
        printf("\t\t4.  Get Key Status\n");
        printf("\t\t5.  Set Date/Time\n");
        printf("\t\t6.  Get Date/Time\n");
        printf("\t\t7.  Disable L100 Passthrough\n");
        printf("\t\t************************************************\n");
    } else {
        printf("\t\t********** Device Options [NEO]*****************\n");
        printf("\t\t0.  Back To Main Menu\n");
        printf("\t\t1.  Start Transaction\n");
        printf("\t\t2.  Cancel Transaction\n");
        printf("\t\t3.  Get Transaction Results\n");
        printf("\t\t4.  Get Firmware Version\n");
        printf("\t\t5.  Send Data Command\n");
        printf("\t\t6.  Get Serial Number\n");
        printf("\t\t7.  Ping Device\n");
        printf("\t\t8.  Interface Control\n");
        printf("\t\t9.  Enable Passthrough\n");
        printf("\t\t10. Disable Passthrough\n");
        printf("\t\t11. Burst Mode ON\n");
        printf("\t\t12. Burst Mode OFF\n");
        printf("\t\t13. Auto Poll\n");
        printf("\t\t14. Poll On Demand\n");
        printf("\t\t15. Set Merchant Record\n");
        printf("\t\t16. Get Merchant Record\n");
        printf("\t\t17. Enable L100 Passthrough\n");
        printf("\t\t18. Transfer File\n");
        printf("\t\t19. Query File (Only for VP6800)\n");
        printf("\t\t20. Delete File\n");
        printf("\t\t21. List Directory\n");
        printf("\t\t22. Start Scanning QR Code (Only for VP6800)\n");
        printf("\t\t23. Stop Scanning QR Code (Only for VP6800)\n");
        printf("\t\t24. Start Taking Photo (Only for VP6800)\n");
        printf("\t\t25. Stop Taking Photo (Only for VP6800)\n");
        printf("\t\t26. Start Remote Key Injection\n");
        printf("\t\t27. WorldPay Transaction\n");
        printf("\t\t28. Cancel WorldPay Transaction\n");
        printf("\t\t29. Update Firmware (Need to run twice if not for RT1050 or Kernel)\n");
        printf("\t\t30. Update Firmware with zip file\n");
        printf("\t\t31. Set Config by JSON file\n");
        printf("\t\t************************************************\n");
    }
    fflush(stdout);
} /* _NEO2_display_device_menu */
