//---------------------------------------------------------------------------

#include <windows.h>
#include <stdio.h>
#include <assert.h>
//---------------------------------------------------------------------------
#include "sense4.h"

BOOL ReadFile1(char* filename, BYTE* pbBuffer, DWORD dwLen);
#define VM_BIN_LENGTH 372
#define XA_BIN_LENGTH 253


int main(int argc, char* argv[])
{
	SENSE4_CONTEXT         *s4CtxList =NULL ;
	DWORD			dwSize=0;
	DWORD			dwRet = 0;
 	DWORD                   dwReturnLen = 0;
        BYTE                    *pbBuffer = NULL;
        BYTE                    *pBuf = NULL;
        BYTE                    inBuff[4];
        BYTE                    outBuff[4];
        DWORD                   dwReturned = 0;
	/** Assume that the developer PIN is "123456781234567812345678" */
	BYTE			pDevPin[24]={0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,
					  0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,
					  0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38};

 	/** Assume that the user PIN is "123456781234567812345678" */
        BYTE                    pUserPin[8] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38};
        S4OPENINFO              openInfo;
        S4CREATEDIRINFO         crtInfo;
	int i = 7;
	BYTE frequence = 4;

	/** Enumerate the device number plugged*/
	dwRet = S4Enum(NULL,&dwSize);

	/** Allocate memory according to the size returned last line         */
	s4CtxList = (SENSE4_CONTEXT *)malloc(dwSize);

	/** Get device context         */
	if(S4Enum(s4CtxList,&dwSize)== S4_SUCCESS)
		printf("Enum device ok! \n");
	else
	{
		printf("Enum device failed.\n");
		free(s4CtxList);
                s4CtxList = NULL;
                return 0;
	}

        openInfo.dwS4OpenInfoSize = 8;
        openInfo.dwShareMode = S4_EXCLUSIZE_MODE;
	/** Open the specified device*/
	if(S4OpenEx(&s4CtxList[0], &openInfo) == S4_SUCCESS)
	{
		/** Print device ID     */
		printf("Open device success. Device ID is :");

		do
		{
			printf("%02x",s4CtxList[0].bID[7-i]);
			i--;
		}while (i>=0);

		printf("\n");
	}
	else
	{
		printf("Open device failure.\n");
 		free(s4CtxList);
                s4CtxList = NULL;
                return 0;
	}

	/** Verify DEV PIN to get the privilege*/
	dwRet=S4VerifyPin(&s4CtxList[0],pDevPin,24,S4_DEV_PIN);

	/** Create MF        */
        crtInfo.dwS4CreateDirInfoSize = 12;
        memcpy(crtInfo.szAtr, "98765432", 8);
	dwRet=S4CreateDirEx(&s4CtxList[0],"\\",0,S4_CREATE_ROOT_DIR, &crtInfo);
	if(dwRet == S4_SUCCESS)
		printf("Created MF success.\n");
	else
	{
	        /** Change current directory to MF    */
        	S4ChangeDir(&s4CtxList[0], "\\");

        	/** Verfity DEV PIN   */
	        dwRet=S4VerifyPin(&s4CtxList[0],pDevPin,24,S4_DEV_PIN);
        	if(dwRet  == S4_SUCCESS)
	            printf("Verify Dev PIN success.\n");
        	else {
	            printf("Verify Dev PIN failed.\n");
 Err1:

                    S4Close(&s4CtxList[0]);
                    free(s4CtxList);
                    s4CtxList = NULL;
                    if ( NULL != pbBuffer )
                          free(pbBuffer);
                    pbBuffer = NULL;
                   if ( NULL != pBuf )
                          free(pBuf);
                    pBuf = NULL;

                    printf("Close SenseLock EL successfully! \nPress any key to continue...");
                    getchar();
                    return 0;
                }

		/** Failed to create MF, the cause can be non-empty device. Try to erase root directory and recreate it.*/
		dwRet=S4EraseDir(&s4CtxList[0], NULL);
		if(dwRet == S4_SUCCESS)
			printf("Erase MF success.\n");
		else{
		        printf("Erase MF failed.\n");
                        goto Err1;
                }
		dwRet=S4CreateDirEx(&s4CtxList[0],"\\",0,S4_CREATE_ROOT_DIR, &crtInfo);
		if(dwRet == S4_SUCCESS)
			printf("Created MF again , success.\n");
		else{
			printf("Created MF again , failed.\n");
                        goto Err1;
                }
	}

	/** LED up*/
	dwRet = S4Control(&s4CtxList[0],S4_LED_UP,NULL,0,outBuff,20,&dwReturned);
	assert(S4_SUCCESS == dwRet);


	/** LED wink*/
	dwRet = S4Control(&s4CtxList[0],S4_LED_WINK,&frequence,1,outBuff,20,&dwReturned);
	assert(S4_SUCCESS == dwRet);

	/** Change current directory to MF*/
	S4ChangeDir(&s4CtxList[0], "\\");

	/** Verify DEV PIN */
	dwRet=S4VerifyPin(&s4CtxList[0],pDevPin,24,S4_DEV_PIN);
	if(dwRet == S4_SUCCESS)
	    printf("Verify Dev PIN success.\n");
	else {
	    printf("Verify Dev PIN failed.\n");
            goto Err1;
        }

	dwRet=S4CreateDir(&s4CtxList[0],"0001",2000,S4_CREATE_SUB_DIR);
	if(dwRet == S4_SUCCESS)
	    printf("Create sub directory 0001 success.\n");
	else {
	    printf("Create sub directory 0001 failed.\n");
            goto Err1;
        }

	/** Change current directory to 0001*/
	dwRet = S4ChangeDir(&s4CtxList[0], "\\0001");
	if(dwRet == S4_SUCCESS)
	    printf("Change directory 0001 success.\n");
	else{
	    printf("Change directory 0001 failed.\n");
            goto Err1;
        }

	pbBuffer = (BYTE *)malloc(VM_BIN_LENGTH);
 	if(!ReadFile1("demo_v20.bin", pbBuffer, VM_BIN_LENGTH))
	{
		printf("Read demo20.bin Error!\n");
		goto Err1;
	}

	dwRet=S4VerifyPin(&s4CtxList[0],pDevPin,24,S4_DEV_PIN);
	if(dwRet == S4_SUCCESS)
	    printf("Verify Dev PIN success.\n");
	else {
	    printf("Verify Dev PIN failed.\n");
            goto Err1;
        }

	/** Create VM_EXE whose ID is 0101 in "0001"*/
	dwRet = S4WriteFile(&s4CtxList[0],
                             "0001",
                             0,
                             pbBuffer,
                             VM_BIN_LENGTH,
                             VM_BIN_LENGTH,
                             &dwReturnLen,
                             S4_CREATE_NEW,
                             S4_EXE_FILE
                             );
	if(dwRet == S4_SUCCESS)
	    printf("Write file 0001 success.\n");
	else{
	    printf("Write file 0001 failed.\n");
            goto Err1;
        }

	pBuf = (BYTE *)malloc(XA_BIN_LENGTH);
 	if(!ReadFile1("demo_v30.bin", pBuf, XA_BIN_LENGTH))
	{
		printf("Read demo30.bin Error!\n");
		goto Err1;
	}

	/** Create XA_EXE whose ID is 0002 in "0001"*/
	dwRet=S4WriteFile(&s4CtxList[0],
                          "0002",
                          0,
                          pBuf,
                          XA_BIN_LENGTH,
                          XA_BIN_LENGTH+126,
                          &dwReturnLen,
                          S4_CREATE_NEW,
                          S4_XA_EXE_FILE
                          );
	if(dwRet == S4_SUCCESS)
	    printf("Write file 0002 success.\n");
	else{
	    printf("Write file 0002 failed.\n");
            goto Err1;
        }


	/** Verify User PIN to get the executive privilege*/
	dwRet=S4VerifyPin(&s4CtxList[0],pUserPin,8,S4_USER_PIN);
 	assert(S4_SUCCESS == dwRet);

	/** the content in inBuf is parameter passed in for executable files*/
	memcpy(inBuff,"\x12\x34\x56\x78",0x04);

	dwRet=S4ExecuteEx(&s4CtxList[0],
                           "0001",
                           S4_VM_EXE,
                           inBuff,
                           0x04,
                           outBuff,
                           0x04,
                           &dwReturned
                           );
	if(dwRet == S4_SUCCESS){
	    printf("Execute vm file 0001 success.\n");
            printf("Execute return: %02x %02x %02x %02x\n", outBuff[0],outBuff[1],outBuff[2],outBuff[3]);
        }
	else{
	    printf("Execute vm file 0001 failed.\n");
            goto Err1;
        }

        dwReturned = 0;
	dwRet=S4ExecuteEx(&s4CtxList[0],
                           "0002",
                           S4_XA_EXE,
                           inBuff,
                           0x04,
                           outBuff,
                           0x04,
                           &dwReturned
                           );
	if(dwRet == S4_SUCCESS){
	    printf("Execute xa file 0002 success.\n");
            printf("Execute return: %02x %02x %02x %02x\n", outBuff[0],outBuff[1],outBuff[2],outBuff[3]);
        }            
	else{
	    printf("Execute xa file 0002 failed.\n");
            goto Err1;
        }

	/** have LED down*/
	dwRet = S4Control(&s4CtxList[0],S4_LED_DOWN,NULL,0,outBuff,20,&dwReturned);
	assert(S4_SUCCESS == dwRet);

        goto Err1;
}
//---------------------------------------------------------------------------

BOOL ReadFile1(char* filename, BYTE* pbBuffer, DWORD dwLen)
{
	FILE *filein = NULL;

	if(!pbBuffer) return FALSE;

	if((filein = fopen(filename, "rb")) == NULL)
	{
		return FALSE;
	}
	else
	{
		if( fread( pbBuffer, 1, dwLen, filein ) <= 0)
		{
			return FALSE;
		}
		else
		{
			fclose(filein);
			return TRUE;
		}
	}
}


