#include <stdio.h>
#include <winscard.h>

#include <stdlib.h>  
#include "commands.h"
#include <string.h>
#include <sys/utsname.h>
int readerlen,readerstate,atrlen;
char input;
int more_details=0;
int fails=0;
int p;
FILE *fp;
int iList[16];
int iReader;
SCARDHANDLE hCard;
unsigned char *data;
unsigned char *buffer;
SCARDCONTEXT hContext;
DWORD len=15;
UCHAR value[300];
struct ReaderContext *rContext;
SCARD_IO_REQUEST sSendPci, sRecvPci;
PSCARD_READERSTATE_A rgReaderStates[1];
DWORD dwReaderLen, dwState, dwProt, dwAtrLen;
DWORD dwSendLength, dwRecvLength, dwPref, dwReaders;
LPTSTR pcReaders, mszReaders;
BYTE pbAtr[MAX_ATR_SIZE];
BYTE s[300], r[300];
LPCTSTR mszGroups;
LONG rv;
DWORD state;
DWORD protocol;
char readerName[100];
char pcHost[50];
extern int testIBM(int ,char**);
extern int testSIEMENS(int ,char**);
extern int testSCHL(int ,char**);
extern int testAMMI(int ,char**);
extern int testGD(int ,char**);
extern int testBULL(int ,char**);

#define atrammi { 0x3b ,0x7e ,0x13 ,0x0 ,0x0 ,0x80 ,0x53 ,0xff ,0xff ,0xff ,0x62 ,0x0 ,0xff ,0x71 ,0xbf ,0x83 ,0x7 ,0x90 ,0x0 ,0x90,0 }
#define atrbull { 0x3f ,0x67 ,0x25 ,0x0 ,0x21 ,0x20 ,0x0 ,0xf ,0x68 ,0x90 ,0x00,0x90,0x00 }
#define atrgd  { 0x3b ,0xbf ,0x18 ,0x0 ,0x80 ,0x31 ,0x70 ,0x35 ,0x53 ,0x54 ,0x41 ,0x52 ,0x43 ,0x4f ,0x53 ,0x20 ,0x53 ,0x32 ,0x31 ,0x20 ,0x43 ,0x90 ,0x0 ,0x9b ,0x90,0x00 }
#define atribm { 0x3b ,0xef, 0x0, 0xff ,0x81 ,0x31 ,0x86 ,0x45 ,0x49 ,0x42 ,0x4d ,0x20 ,0x4d ,0x46 ,0x43 ,0x34 ,0x30 ,0x30 ,0x30 ,0x30 ,0x38 ,0x33 ,0x31 ,0x43 ,0x90,0x00 }
#define atrschl { 0x3b ,0xe2 ,0x0 ,0x0 ,0x40 ,0x20 ,0x99 ,0x1 ,0x90,0 }
#define atrsiemens { 0x3b ,0xef ,0x0 ,0x0 ,0x81 ,0x31 ,0x20 ,0x49 ,0x0 ,0x5c ,0x50 ,0x43 ,0x54 ,0x10 ,0x27 ,0xf8 ,0xd2 ,0x76 ,0x0 ,0x0 ,0x38 ,0x33 ,0x0 ,0x4d ,0x90,0x00 }

struct card cards[6] = { 
		{ 0,"AMMI",0,atrammi,19,testAMMI},
		{1, "BULL",0,atrbull,11,testBULL},
		{2,"G & D",0,atrgd,24,testGD},
		{3,"IBM",0,atribm,24,testIBM},
		{4,"SCHLUMBERGER",0,atrschl,8,testSCHL},
		{5,"SIEMENS NIXDORF",0,atrsiemens,24,testSIEMENS}
		};
void usage() {
	printf("ifdtest [-usage] [-debug] [-o filename ] \n");
	printf(" -usage : print the usage info\n");
	printf(" -debug : dump command APDUS and responses \n");
	printf(" -o filename : save output to filename \n");
	return;
	}

int checkATR(char *atr , int atrlen) {
	int i,j;
	if( atrlen == 0) return -1;
	for(i=0;i<6;i++)  {
		if( !cards[i].done ) {
			if( atrlen != cards[i].atrlen ) continue;
			for(j=0;j<atrlen;j++) {
				//myprintf("atr[%d] = %0x cards[%d].atr[%d] = %0x \n",j,atr[j],i,j,cards[i].atr[j]);
				if( (atr[j]&0xff) != cards[i].atr[j] ) break;
			}
			if( j== atrlen) {
				cards[i].done=1;
				return i;
			}
		}
	}
	return -1;
}
void printVersion(char * readerName ) {
    struct utsname *buf;
    int i;
    buf = malloc(sizeof(struct utsname));
    i=uname(buf);
    myprintf("Infineer IFDTest \n");
    myprintf("Reader Under test : %s \n", readerName);
    myprintf("Computer Name : %s \n", buf->nodename);
    myprintf("Version : %s \n",buf->release);
} 
int main(int argc,char** argv ) 
{
int i;
int alldone,card;
char *outfile=NULL;
if( argc > 1 ) {
for(i=1;i<argc;i++) {
	if( strcmp(argv[i],"-usage") == 0) {
		usage();
		return 0;
	}
	if( strcmp(argv[i],"-debug") == 0) 
		more_details=1;
	if(strcmp(argv[i],"-o")== 0) 
	  outfile=argv[i+1];
}
}
if( outfile != NULL) fp = fopen(outfile,"w");
else fp=NULL;
	rv = SCardEstablishContext( SCARD_SCOPE_SYSTEM, pcHost, NULL, &hContext );
	if ( rv != SCARD_S_SUCCESS ) {
			myprintf("ERROR :: Resource Manager not running \n");
			myprintf("Please start the resource manager and try again \n");
   		    return 1;
	} 
  rv = SCardSetTimeout(hContext,100);
  if ( rv != SCARD_S_SUCCESS ) {
    myprintf("ERROR :: Cannot Set timeout \n");
    myprintf("PCSC ERROR: %s\n", pcsc_stringify_error(rv));
    return -1;
  }
  rv = SCardGetStatusChange( hContext, INFINITE, 0, 0 );
 
  if ( rv != SCARD_S_SUCCESS ) {
    myprintf("PCSC ERROR: %s\n", pcsc_stringify_error(rv));
  }                                                      
  mszGroups = 0;
  rv = SCardListReaders( hContext, mszGroups, 0, &dwReaders );
 
  if ( rv != SCARD_S_SUCCESS ) {
    myprintf("PCSC ERROR: %s\n", pcsc_stringify_error(rv));
    myprintf("control: Error listing readers\n");
    return 1;        
 }
mszReaders = (char *)malloc(sizeof(char)*dwReaders);
rv = SCardListReaders( hContext, mszGroups, mszReaders, &dwReaders );
 
if ( rv != SCARD_S_SUCCESS ) {
    myprintf("PCSC ERROR: %s\n", pcsc_stringify_error(rv));
    myprintf("control: Error listing readers\n");
    return 1;
}
 /* Have to understand the multi-string here */
 p = 0;
  for ( i=0; i < dwReaders - 1; i++ ) {
    ++p;
    myprintf("Reader %02d: %s\n", p, &mszReaders[i]);
    iList[p] = i;
    while ( mszReaders[++i] != 0 );
  }
 
  do {
    myprintf("Enter the desired reader number : " );
    scanf("%d", &iReader); 
	myprintf("\n");
    if ( iReader > p || iReader <= 0 ) { 
	 myprintf("Invalid Value - try again\n");
    }
  } while ( iReader > p || iReader <= 0 );
	
  rgReaderStates[0] =
 (PSCARD_READERSTATE_A)
    malloc(sizeof(SCARD_READERSTATE_A));
	strcpy(readerName,&mszReaders[iList[iReader]]);
	printVersion(readerName);
  (rgReaderStates[0])->szReader       = strdup(readerName);
  (rgReaderStates[0])->dwCurrentState = SCARD_STATE_EMPTY; 
	myprintf("Do u want to run testA \n");
	read(0,&input,1);
	if( input == 'y') {
  		if(testA(argc,argv)) { 
			myprintf("testA Failed \n"); 	
			return -1;
		}
	}
	read(0,&input,1);
	myprintf("Do u want to run testB \n");
	read(0,&input,1);
	if( input == 'y') {
  		if(testB(argc,argv)) { 
			myprintf("testB Failed \n"); 	
			return -1;
		}
		myprintf("\n<<  Please remove smart card \n");
		(rgReaderStates[0])->dwCurrentState = SCARD_STATE_PRESENT; 	
		rv = SCardGetStatusChange( hContext,0xFFFFFFFF,rgReaderStates[0],1);
	}
	data = alloca(300);
	buffer = alloca(300);
	alldone=0;
	do {
	if( alldone == 6) break;
	myprintf("==========================\n");
	myprintf(" Part D: Smart Card Provider Test \n");
	myprintf("==========================\n");
	myprintf("Insert one of the following PC/SC test Cards \n");
	for(i=0;i<6;i++) {
		if(  !cards[i].done) {
			myprintf("*  %s\n",cards[i].name);
		}
	}
  		(rgReaderStates[0])->dwCurrentState = SCARD_STATE_EMPTY; 
	 	rv = SCardGetStatusChange( hContext,0xFFFFFFFF,rgReaderStates[0],1); 
		if( (rgReaderStates[0])->dwEventState & SCARD_STATE_PRESENT ) {
			rv = SCardConnect(hContext, readerName,
           	 SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0| SCARD_PROTOCOL_T1,
           	 &hCard, &dwPref); 
		  	if ( rv != SCARD_S_SUCCESS ) {
				continue;
  			}             
			readerlen=100;
			rv = SCardStatus(hCard,readerName,&readerlen,&readerstate,&protocol,r,&atrlen);
		  	if ( rv != SCARD_S_SUCCESS ) {
				continue;
  			}             
			card = checkATR(r,atrlen);
			if(card != -1) {
				myprintf("\nTesting card %s \n",cards[card].name); 
				(cards[card].func)(argc,argv);
				if( fails) myprintf("\n%s card Test Failed \n",cards[card].name);
				fails=0;
				alldone++;
			}
			else {
				myprintf("ATR doesn't match / Test already completed \n");
			}
				myprintf("\n<<  Please remove smart card \n");
				(rgReaderStates[0])->dwCurrentState = SCARD_STATE_PRESENT; 	
				rv = SCardGetStatusChange( hContext,0xFFFFFFFF,rgReaderStates[0],1);
		}
  	} while( alldone < 6  ) ;
}


syntax highlighted by Code2HTML, v. 0.9.1