#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winscard.h>
#include <reader.h>

//#define IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE    SCARD_CTL_CODE(2048)  // works on Windows
#define IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE    SCARD_CTL_CODE(1)

static void loadStrings(SCARDHANDLE hCard);
static void dumphex(const char *msg, const unsigned char *buf, int len);

int main(int argc, char *argv[])
{
    ULONG rv;
    SCARDCONTEXT hContext;
    char readers[1000];
    DWORD dwReaders = sizeof(readers);
    DWORD dwActiveProtocol;
    SCARDHANDLE hCard;
    unsigned char bSendBuffer[258];
    unsigned char bRecvBuffer[258];
    DWORD length;
    unsigned int i;

    rv = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &hContext);
    if (rv != SCARD_S_SUCCESS)
    {
        printf("SCardEstablishContext(): %lX\n", rv);
        return 1;
    }

    rv = SCardListReaders(hContext, NULL, readers, &dwReaders);
    if (rv != SCARD_S_SUCCESS)
    {
        printf("SCardListReaders(): %lX\n", rv);
        return 1;
    }
    if (dwReaders == 0)
    {
        printf("No readers found\n");
        return 1;
    }

    printf("Reader: %s\n", readers);

    rv = SCardConnect(hContext, readers, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0, &hCard, &dwActiveProtocol);
    if (rv != SCARD_S_SUCCESS)
    {
        printf("SCardConnect(): %lX\n", rv);
        return 1;
    }

    printf("\nIOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE = 0x%0x (%d)\n",
        IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE);
    printf("CM_IOCTL_GET_FEATURE_REQUEST = 0x%0x (%d)\n",
        CM_IOCTL_GET_FEATURE_REQUEST, CM_IOCTL_GET_FEATURE_REQUEST);

    /* Get firmware info, this is specific to Gemplus readers */
    bSendBuffer[0] = 0x02;
    length = sizeof(bRecvBuffer);
    rv = SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, bSendBuffer,
        1, bRecvBuffer, sizeof(bRecvBuffer), &length);
    printf("\nSCardControl(Get firmware info for the GemPC reader): %lX\n", rv);

    if (rv == SCARD_S_SUCCESS)
    {
        printf(" \nFirmware: ");
        for (i=0; i<length; i++)
            printf("%02X ", bRecvBuffer[i]);
        bRecvBuffer[length] = '\0';
        printf(" \nFirmware: %s (%ld bytes)\n", bRecvBuffer, length);
    }

    /* Get pinpad features */
    length = sizeof(bRecvBuffer);
    rv = SCardControl(hCard, CM_IOCTL_GET_FEATURE_REQUEST, NULL, 0,
        bRecvBuffer, sizeof(bRecvBuffer), &length);
    printf("\nSCardControl(CM_IOCTL_GET_FEATURE_REQUEST): %lX\n", rv);
    if (rv == SCARD_S_SUCCESS)
        dumphex("Feature buf", bRecvBuffer, length);

    /* Set display messages, this is specific to Gemplus readers */
    loadStrings(hCard);

    return 0;
}

/*Definitions for strings loading*/
#define CMD_LOAD_STRING_HEADER 5
#define CMD_LOAD_STRING_MAX_SIZE 16
#define CMD_LOAD_NB_STRING 10

static char *ppaPinpadString[] = {"Authent. PIN?", "New PIN?", "Confirm new PIN",
    "    OK", "Incorrect PIN",
    "Time Out", "* retries left", "Insert Card", "Card Error", "Locked card"
};

static void loadStrings(SCARDHANDLE hCard)
{
    unsigned char bRecvBuffer[258];
    char acCommandLoad[CMD_LOAD_STRING_HEADER + CMD_LOAD_STRING_MAX_SIZE*CMD_LOAD_NB_STRING];
    unsigned int i, j;
    int k = 0;
    ULONG rv;
    DWORD length;

    /*Load strings in the pinpad memory*/
    acCommandLoad[k++] = (char)0xB2;
    acCommandLoad[k++] = (char)0xA0;
    acCommandLoad[k++] = 0x00;
    acCommandLoad[k++] = 0x4D;//Show that data is valid
    acCommandLoad[k++] = 0x4C;
    for ( i = 0; i < CMD_LOAD_NB_STRING; i ++)
    {
        /*fill the command array with string*/
        for ( j = 0; j < strlen(ppaPinpadString[i]); j++ )
            acCommandLoad[k++] = ppaPinpadString[i][j];

        /*pad with 0x20*/
        while ( j++ < CMD_LOAD_STRING_MAX_SIZE )
            acCommandLoad[k++] = 0x20;
    }

    rv = SCardControl(hCard, IOCTL_SMARTCARD_VENDOR_IFD_EXCHANGE, acCommandLoad,
        sizeof( acCommandLoad ), bRecvBuffer, sizeof(bRecvBuffer), &length);
    printf("\nSCardControl(Set strings to be displayed): %lX\n", rv);
}

static void dumphex(const char *msg, const unsigned char *buf, int len)
{
	int i;
	if (msg)
		printf("%s:", msg);
	for (i = 0; i < len; i++)
		printf(" %02X", buf[i]);
	printf(" (%d bytes)\n", len);
}


