import java.io.*;
/**
 * This class can take a variable number of parameters on the command
 * line. Program execution begins with the main() method. The class
 * constructor is not invoked unless an object of type 'Class1'
 * created in the main() method.
 */
public class Sense4Test
{
	public static void main (String[] args)
	{
		
		JavaSense4 sense4 = new JavaSense4();
		
		int [] size = new int[1];
		int ret = 0;
		int size1 = 10;		
		byte lpInBuffer[] = {0x12, 0x34, 0x56, 0x78};
		byte FileID[] = {0x30, 0x30, 0x30, 0x31, 0x00};		
		byte FileID1[] = {0x30, 0x30, 0x30, 0x32, 0x00};		

		byte [] lpOutBuffer = new byte[20];
		int [] lpBytesReturned = {0};			
		SENSE4_CONTEXT[] s4_context = new SENSE4_CONTEXT[0];
		
		ret = sense4.S4Enum(null, size);
		
		s4_context = new SENSE4_CONTEXT[size[0] / 92];
		for (int i = 0;i< size[0] / 92; i++)
		{
			s4_context[i] = new SENSE4_CONTEXT();
		}
		
		ret = sense4.S4Enum(s4_context, size);
		if (0 != ret)
			System.out.print("enumerate sense4 error");
		else
			System.out.println("enumerate sense4 success");
			
		S4OPENINFO s4_OpenInfo = new S4OPENINFO();
		s4_OpenInfo.dwS4OpenInfoSize = 8;
		s4_OpenInfo.dwShareMode = JavaSense4.S4_EXCLUSIZE_MODE;
		
		ret = sense4.S4OpenEx(s4_context[0], s4_OpenInfo);
		if (0 != ret)
			System.out.print("pen sense4 error");
		else
			System.out.println("open sense4 success");

		byte [] frequency = {0x04};
		ret = sense4.S4Control(s4_context[0], JavaSense4.S4_LED_WINK, frequency, 1, null, 0, lpBytesReturned);	
		if (0 != ret)
			System.out.print("sense4 LED wink error");
		else
			System.out.println("sense4 LED wink success");
		
		byte [] Path = {(byte)'\\', 0x00};
		ret = sense4.S4ChangeDir (s4_context[0], Path);
		if (0 != ret)
			System.out.print("change dir error");
		else
			System.out.println("change dir success");
		
		ret = sense4.S4VerifyPin(s4_context[0], ((String)"123456781234567812345678").getBytes(), 24, JavaSense4.S4_DEV_PIN);
		if (0 != ret)
			System.out.print("verify dev pin error");
		else
			System.out.println("verify dev pin success");
		
		ret = sense4.S4EraseDir(s4_context[0], null);
		if (0 != ret)
			System.out.print("erase MF error");
		else
			System.out.println("erase MF success");
		
		S4CREATEDIRINFO s4_CreateDirInfo = new S4CREATEDIRINFO();
		s4_CreateDirInfo.dwS4CreateDirInfoSize = 12;
		s4_CreateDirInfo.szAtr[0] = (byte)0xFF;
		s4_CreateDirInfo.szAtr[1] = (byte)0xFF;
		s4_CreateDirInfo.szAtr[2] = (byte)0xFF;
		s4_CreateDirInfo.szAtr[3] = (byte)0xFF;
		s4_CreateDirInfo.szAtr[4] = (byte)0xFF;
		s4_CreateDirInfo.szAtr[5] = (byte)0xFF;
		s4_CreateDirInfo.szAtr[6] = (byte)0xFF;
		s4_CreateDirInfo.szAtr[7] = (byte)0xFF;
												
		ret = sense4.S4CreateDirEx(s4_context[0], Path, 0, JavaSense4.S4_CREATE_ROOT_DIR,s4_CreateDirInfo );
		if (0 != ret)
			System.out.print("create MF error");
		else
			System.out.println("create MF success");
		
		ret = sense4.S4ChangePin(s4_context[0], ((String)"12345678").getBytes (), 8, ((String)"11111111").getBytes (), 8, JavaSense4.S4_USER_PIN );
		if (0 != ret)
			System.out.print("change user pin error");
		else
			System.out.println("change user pin success");
	
		ret = sense4.S4VerifyPin (s4_context[0], ((String)"123456781234567812345678").getBytes (), 24, JavaSense4.S4_DEV_PIN );
		if (0 != ret)
			System.out.print("verify dev pin error");
		else
			System.out.println("verify dev pin success");

		File demofile = new File("demo_v20.bin");
		long contentsize = demofile.length ();
		byte [] content = new byte[1];
		try
		{
			FileInputStream is = new FileInputStream (demofile);
			content = new byte[(int)contentsize];
			is.read(content, 0, (int)contentsize);
			is.close();
		}
		catch(Exception e)
		{
			System.out.print("read demo_v20.bin error");			
		}

		
		ret = sense4.S4WriteFile (s4_context[0], FileID, 0, content, (int)contentsize, 1000, lpBytesReturned, 
								  JavaSense4.S4_CREATE_NEW , (byte)JavaSense4.S4_EXE_FILE );		
		if (0 != ret)
			System.out.print("write demo_v20.bin error");
		else
			System.out.println("write demo_v20.bin success");

		File demofile1 = new File("demo_v30.bin");
		long cntsize = demofile1.length ();
		byte [] cnt = new byte[1];
		try
		{
			FileInputStream fIs = new FileInputStream (demofile1);
			cnt = new byte[(int)cntsize];
			fIs.read(cnt, 0, (int)cntsize);
			fIs.close();
		}
		catch(Exception e)
		{
			System.out.print("read demo_v30.bin error");
			
		}

		ret = sense4.S4WriteFile (s4_context[0], FileID1, 0, cnt, (int)cntsize, 1000, lpBytesReturned, 
								  JavaSense4.S4_CREATE_NEW , (byte)JavaSense4.S4_XA_EXE_FILE );		
		if (0 != ret)
			System.out.print("write demo_v20.bin error");
		else
			System.out.println("write demo_v30.bin success");
		
		ret = sense4.S4VerifyPin(s4_context[0], ((String)"11111111").getBytes(), 8, JavaSense4.S4_USER_PIN);
		if (0 != ret)
			System.out.print("verify user pin error");
		else
			System.out.println("verify user pin success");

		ret = sense4.S4ExecuteEx(s4_context[0], FileID, JavaSense4.S4_VM_EXE, lpInBuffer, 4, lpOutBuffer, 20, lpBytesReturned);
		if (0 != ret)
			System.out.print("execute demo_v20.bin error");
		else
			System.out.println("execute demo_v20.bin success");
		
		
		ret = sense4.S4ExecuteEx(s4_context[0], FileID1, JavaSense4.S4_XA_EXE, lpInBuffer, 4, lpOutBuffer, 20, lpBytesReturned);
		if (0 != ret)
			System.out.print("execute demo_v30.bin error");
		else
			System.out.println("execute demo_v30.bin success");
		
		ret = sense4.S4Control (s4_context[0], JavaSense4.S4_LED_DOWN, null, 0, null, 0, lpBytesReturned);
		if (0 != ret)
			System.out.print("LED down error");
		else
			System.out.println("LED down success");
		
		ret = sense4.S4Close(s4_context[0]);
		if (0 != ret)
			System.out.print("close sense4 error");
		else
			System.out.print("close sense4 success");
	}
}

class JavaSense4
{
	public static int S4_RSA_PUBLIC_FILE		=0x00000006;
	public static int S4_RSA_PRIVATE_FILE		=0x00000007;
	public static int S4_EXE_FILE				=0x00000008;
	public static int S4_DATA_FILE				=0x00000009;
	public static int S4_XA_EXE_FILE			=0x0000000b;		

	
	public static int S4_USER_PIN				=0x000000a1;
	public static int S4_DEV_PIN				=0x000000a2;
	public static int S4_AUTHEN_PIN				=0x000000a3;

	
	public static int S4_CREATE_NEW				=0x000000a5;
	public static int S4_UPDATE_FILE			=0x000000a6;
	public static int S4_KEY_GEN_RSA_FILE		=0x000000a7;
	public static int S4_SET_LICENCES			=0x000000a8;
	public static int S4_CREATE_ROOT_DIR		=0x000000ab;
	public static int S4_CREATE_SUB_DIR			=0x000000ac;
	public static int S4_CREATE_MODULE			=0x000000ad;
	public static int S4_FILE_READ_WRITE        =0x00000000;       
	public static int S4_FILE_EXECUTE_ONLY      =0x00000100;       
	public static int S4_CREATE_PEDDING_FILE	=0x00002000;		

	
	public static int S4_EXCLUSIZE_MODE			=0;
	public static int S4_SHARE_MODE				=1;

	
	public static int S4_GET_DEVICE_TYPE		=0x00000025;	
	public static int S4_GET_VM_TYPE			=0x00000027;	
	public static int S4_RESET_DEVICE           =0x00000002;	
	public static int S4_DF_AVAILABLE_SPACE     =0x00000031;	
	public static int S4_EF_INFO                =0x00000032;	
	public static int S4_LED_UP					=0x00000004;	
	public static int S4_LED_DOWN				=0x00000008;	
	public static int S4_LED_WINK				=0x00000028;	
	public static int S4_GET_SERIAL_NUMBER		=0x00000026;	
	public static int S4_GET_DEVICE_USABLE_SPACE=0x00000029;	
	public static int S4_SET_DEVICE_ID			=0x0000002a;	
	
	
	
	public static int S4_LOCAL_DEVICE			=0x00;		
	public static int S4_MASTER_DEVICE			=0x80;	
	public static int S4_SLAVE_DEVICE			=0xc0;		

	
	public static int S4_VM_51					=0x00;		
	public static int S4_VM_251_BINARY			=0x01;	
	public static int S4_VM_251_SOURCE	    	=0X02;	

	
	
	public static int S4_VM_EXE					=0x00000000;		
	public static int S4_XA_EXE					=0x00000001;		

	
	/**	Return	Code */
	public static int S4_SUCCESS				=0x00000000;		/** success */
	public static int S4_UNPOWERED				=0x00000001;
	public static int S4_INVALID_PARAMETER		=0x00000002;
	public static int S4_COMM_ERROR				=0x00000003;
	public static int S4_PROTOCOL_ERROR			=0x00000004;
	public static int S4_DEVICE_BUSY			=0x00000005;
	public static int S4_KEY_REMOVED			=0x00000006;
	public static int S4_INSUFFICIENT_BUFFER	=0x00000011;
	public static int S4_NO_LIST				=0x00000012;
	public static int S4_GENERAL_ERROR			=0x00000013;
	public static int S4_UNSUPPORTED			=0x00000014;
	public static int OPEN_LOG_FILE_ERROR		=0x00000015;
	public static int S4_DEVICE_TYPE_MISMATCH	=0x00000020;
	public static int S4_FILE_SIZE_CROSS_7FFF	=0x00000021;
	public static int S4_DEVICE_UNSUPPORTED		=0x00006a81;
	public static int S4_FILE_NOT_FOUND			=0x00006a82;
	public static int S4_INSUFFICIENT_SECU_STATE=0x00006982;
	public static int S4_DIRECTORY_EXIST		=0x00006901;
	public static int S4_FILE_EXIST				=0x00006a80;
	public static int S4_INSUFFICIENT_SPACE		=0x00006a84;
	public static int S4_OFFSET_BEYOND			=0x00006B00;
	public static int S4_PIN_BLOCK				=0x00006983;
	public static int S4_FILE_TYPE_MISMATCH		=0x00006981;
	public static int S4_CRYPTO_KEY_NOT_FOUND	=0x00009403;
	public static int S4_APPLICATION_TEMP_BLOCK	=0x00006985;
	public static int S4_APPLICATION_PERM_BLOCK	=0x00009303;
	public static int S4_DATA_BUFFER_LENGTH_ERROR=0x00006700;
	public static int S4_CODE_RANGE				=0x00010000;
	public static int S4_CODE_RESERVED_INST		=0x00020000;
	public static int S4_CODE_RAM_RANGE			=0x00040000;
	public static int S4_CODE_BIT_RANGE			=0x00080000;
	public static int S4_CODE_SFR_RANGE			=0x00100000;
	public static int S4_CODE_XRAM_RANGE		=0x00200000;
	public static int S4_ERROR_UNKNOWN			=0xffffffff;
	
	/** functions */
	public native int S4Startup();
	
	public native int S4Cleanup();
	
	public native int S4Enum(SENSE4_CONTEXT[] s4_context, 
							 int[] size);
	
	public native int S4Open(SENSE4_CONTEXT s4_context);
	
	public native int S4OpenEx(SENSE4_CONTEXT s4_context, 
							   S4OPENINFO S4OpenInfo);			
	
	public native int S4Close(SENSE4_CONTEXT s4_context);
			
	public native int S4Control(SENSE4_CONTEXT s4_context, 
								int ctlCode, 
								byte[] inBuff,
								int inBuffLen,
								byte[] outBuff, 
								int outBuffLen, 
								int[] bytesReturned);
		
	public native int S4CreateDir(SENSE4_CONTEXT s4_context,
								  byte[] lpszDirID, 
								  int dwDirSize, 
								  int dwFlags);
		
	public native int S4CreateDirEx(SENSE4_CONTEXT s4_context,
								  byte[] lpszDirID,
								  int dwDirSize,
								  int dwFlags,
								  S4CREATEDIRINFO CreateDirInfo);
	
	public native int S4ChangeDir(SENSE4_CONTEXT s4_context, 
								  byte[] lpszPath);
	
	public native int S4EraseDir(SENSE4_CONTEXT s4_context, 
								 byte[] lpszDirID);
	
	public native int S4VerifyPin(SENSE4_CONTEXT s4_context, 
								  byte[] lpPin,
								  int dwPinLen, 
								  int dwPinType);	
	
	public native int S4ChangePin(SENSE4_CONTEXT s4_context, 
								  byte[] lpOldPin, 
								  int dwOldPinLen,
								  byte[] lpNewPin, 
								  int dwNewPinLen, 
								  int dwPinType);
	
	public native int S4WriteFile(SENSE4_CONTEXT s4_context, 
								  byte[] lpszFileID, 
								  int dwOffset,
								  byte[] byteBuffer, 
								  int dwBufferSize, 
								  int dwFileSize,
								  int[] lpBytesWritten,
								  int dwFlags, 
								  byte bFileType);
	
	public native int S4Execute(SENSE4_CONTEXT s4_context, 
								byte[] lpszFileID,
								byte[] lpInbuffer, 
								int dwInbufferSize,
								byte[] lpOutBuffer, 
								int dwOutBufferSize,
								int[] lpBytesReturned);

	public native int S4ExecuteEx(SENSE4_CONTEXT s4_context, 
								byte[] lpszFileID,
								int    dwFlag,
								byte[] lpInbuffer, 
								int dwInbufferSize,
								byte[] lpOutBuffer, 
								int dwOutBufferSize,
								int[] lpBytesReturned);
	
	static {
		System.loadLibrary("JavaSense4");
	}
}

class SENSE4_CONTEXT
{
	public int dwIndex;
	public int dwVersion;
	public int hLock;
	public byte[] reserve;
	public byte[] bAtr;
	public byte[] bID;
	public int dwAtrLen;
	SENSE4_CONTEXT()
	{
		reserve = new byte[12];
		bAtr = new byte[56];
		bID = new byte[8];
	}
}

class EFINFO
{
	public short EfID;
	public byte EfType;
	public short EfSize;
}


class S4OPENINFO
{
	public int dwS4OpenInfoSize;
	public int dwShareMode;
}


class S4CREATEDIRINFO
{
	public int dwS4CreateDirInfoSize;
	byte [] szAtr;
	S4CREATEDIRINFO()
	{
		szAtr = new byte[8];
	}
}




