#include <stdio.h>
#include <conio.h>
#include <assert.h>
#include "sense4.h"

/*
VCは構造体は8バイトアライメントされるが、
ELドングル側ではバイトアライメントされるため、
構造体のアライメントを一致させないと正しく
データを渡せない。
pragma でバイトアライメントになるように設定
*/

/*-------------本来はヘッダファイルの内容 (開始)-----------------*/
#ifdef _WIN32
#pragma pack(push, 1)
#endif 

#define IO_PACKAGE_HEADER_SIZE 2 //IO package header length:tag+len
#define MAX_IO_DATA_SIZE	0xf8 // maximum IO data size

/* common error code. */
#define ERR_SUCCESS				0x00	// success
#define ERR_SES					0x80	// SES function execution error
#define ERR_INVALID_PARAMETER	0x81	// invalid parameter

/* IO package */
typedef struct _IO_PACKAGE
{	
	unsigned char tag;	
	unsigned char len;
	unsigned char buff[MAX_IO_DATA_SIZE];
} IO_PACKAGE;

#ifdef _WIN32
#pragma pack(pop)
#endif
/*-------------本来はヘッダファイルの内容 (終了)-----------------*/



/* global variables definition */
SENSE4_CONTEXT stS4Ctx = {0};
unsigned long dwResult = 0;
unsigned long dwBytesReturned = 0;

IO_PACKAGE stDataPkgIn = {0};
IO_PACKAGE stDataPkgOut = {0};

#define S4_EXE_FILE_ID "ef17"

/* for debug purpose only : handle results returned by stDataPkgOut.tag */
#ifdef _DEBUG
void HandleError(unsigned char bErrCode, unsigned char *pbErrInfo)
{
	switch(bErrCode)
	{
	case ERR_SUCCESS:
		printf("Success!\n");
		break;
	case ERR_SES:
		printf("Error during SES Execution :\n%s\n", SesErrMsgs[*pbErrInfo]);
		break;
	case ERR_INVALID_PARAMETER:
		printf("Invalid input,pls check your input data\n");
		break;
	default:
		printf("Undefined error code!\n");
		break;
	}
	return;
}
#else
void HandleError(unsigned char bErrCode, unsigned char *pbErrInfo)
{
	return;
}	
#endif

/* check result for S4Execute(...) */
unsigned long CheckS4ExecutionResult(unsigned long dwResult,unsigned long dwBytesReturned,unsigned char tag)
{
	
	if (dwResult != S4_SUCCESS) 
	{
		printf("S4 Execution failed! \n", dwResult);
		return 0;
	}
	
	if (dwBytesReturned < 2)
	{
		printf("Invalid data package returned!\n");
		return 0;
	}
	
	if (tag != ERR_SUCCESS)
	{
		HandleError(stDataPkgOut.tag, stDataPkgOut.buff);
		return 0;
	}
	return 1;
}


int main(int argc, char* argv[])
{
	unsigned char lpUserPin[] = "12345678";

	/*指定 ELドングルに接続
    if (!(dwResult = OpenS4ByIndex(FIRST_S4_INDEX,&stS4Ctx)))
	{
		return 1;
	}   
	
	dwResult = S4ChangeDir(&stS4Ctx, "\\");
	if (dwResult != S4_SUCCESS) 
	{
		printf("Change directory failed! \n",dwResult);
		S4Close(&stS4Ctx);
		return dwResult;
	}
	
	// ELプログラムを実行するためユーザPINでログイン
	dwResult = S4VerifyPin(&stS4Ctx, lpUserPin, strlen((LPCSTR)lpUserPin), S4_USER_PIN);
	if (dwResult != S4_SUCCESS) 
	{
		printf("Verify Pin failed! \n",dwResult);
		S4Close(&stS4Ctx);
		return dwResult;
	}	
	
	// ELプログラムに渡すデータを設定
	stDataPkgIn.tag = 0; /* no meaning */
	stDataPkgIn.len = 2; /* length of input data */
	stDataPkgIn.buff[0] = 8; /* line */
	stDataPkgIn.buff[1] = 9; /* column */
	printf("Calling Elite EL EXF %s...\n", S4_EXE_FILE_ID);

	dwResult = S4Execute(&stS4Ctx, S4_EXE_FILE_ID, &stDataPkgIn, 
						IO_PACKAGE_HEADER_SIZE + stDataPkgIn.len, 
						&stDataPkgOut, sizeof(IO_PACKAGE), &dwBytesReturned);

	if (!CheckS4ExecutionResult(dwResult, dwBytesReturned, stDataPkgOut.tag))
	{
		ResetAndCloseS4(&stS4Ctx);
		return 1;
	}
	printf("Success!\nThe result is:\n%d\n",stDataPkgOut.buff[0]);
	
	/*ユーザPINでログインしたためデバイスをリセットするため S4Closeではなく */
	ResetAndCloseS4(&stS4Ctx);
	getch();

	return dwResult;
}