using System;
using ROCKEY4;
using System.Runtime.InteropServices;


namespace CSSample
{
	/// <summary>
	/// Rockey4 Command.
	/// </summary>
	enum Ry4Cmd:ushort
	{
		RY_FIND=1,			//Find Rockey4.
		RY_FIND_NEXT,		//Find next Rockey4.
		RY_OPEN,			//Open 
		RY_CLOSE,			//Close
		RY_READ,			//Read UDZ
		RY_WRITE,			//Write UDZ
		RY_RANDOM,			//Random
		RY_SEED,			//Seed code
		RY_WRITE_USERID,	//Write UID
		RY_READ_USERID,		//Read UID
		RY_SET_MODULE,		//Write module
		RY_CHECK_MODULE,	//Check module status
		RY_WRITE_ARITHMETIC,//Write UAZ
		RY_CALCULATE1,		//Calculate 1
		RY_CALCULATE2,		//Calculate 2
		RY_CALCULATE3,		//Calculate 3
		RY_DECREASE			//Decrease
	};

	/// <summary>
	/// Rockey4 Type.
	/// </summary>
	enum Ry4Type:uint
	{
		// Rockey4 Type
		TYPE_ROCKEY4=1,			//Normal Ry4.
		TYPE_ROCKEY4Plus,		//Ry4Plus.
		TYPE_ROCKEYUSB,			//Ry4 USB.
		TYPE_ROCKEYUSBPlus,		//Ry4 USB Plus
		TYPE_ROCKEYNET,			//NetRy4
		TYPE_ROCKEYUSBNET		//NetRy4 USB.
	};


	
	enum Ry4ErrCode:uint
	{
		ERR_SUCCESS=0,							//No error.
        ERR_NO_PARALLEL_PORT=0x80300001,		//(0x80300001)No parallel port on the computer 
        ERR_NO_DRIVER,							//(0x80300002)No driver installed 
        ERR_NO_ROCKEY,							//(0x80300003)No ROCKEY4 dongle 
        ERR_INVALID_PASSWORD,					//(0x80300004)ROCKEY4 dongle found, but base password is incorrect
        ERR_INVALID_PASSWORD_OR_ID,				//(0x80300005)Wrong password or ROCKEY4 HID
        ERR_SETID,								//(0x80300006)Set ROCKEY4 HID wrong
        ERR_INVALID_ADDR_OR_SIZE,				//(0x80300007)Read/Write address is wrong
        ERR_UNKNOWN_COMMAND,					//(0x80300008)No such command
        ERR_NOTBELEVEL3,						//(0x80300009)Inside error
        ERR_READ,								//(0x8030000A)Read error
        ERR_WRITE,								//(0x8030000B)Write error
        ERR_RANDOM,								//(0x8030000C)Random error
        ERR_SEED,								//(0x8030000D)Seed Code error
        ERR_CALCULATE,							//(0x8030000E)Calculate error
        ERR_NO_OPEN,							//(0x8030000F)Ry_Open must precede this operation
        ERR_OPEN_OVERFLOW,						//(0x80300010)Too many open dongles (>16)
        ERR_NOMORE,								//(0x80300011)No more dongle
        ERR_NEED_FIND,							//(0x80300012)No Find before FindNext
        ERR_DECREASE,							//(0x80300013)Decrease error
        ERR_AR_BADCOMMAND,						//(0x80300014)Arithmetic instruction error
        ERR_AR_UNKNOWN_OPCODE,					//(0x80300015)Arithmetic operator error
        ERR_AR_WRONGBEGIN,						//(0x80300016)A constant. cannot be in the first instruction
        ERR_AR_WRONG_END,						//(0x80300017)A constant. cannot be in the last instruction 
        ERR_AR_VALUEOVERFLOW,					//(0x80300018)Const number > 63

		ERR_UNKNOWN=0x8030ffff,					//(0x8030FFFF)Unknown error 

		ERR_RECEIVE_NULL=0x80300100,			//(0x80300100)Parallel port can not recieve data.
		ERR_PRNPORT_BUSY=0x80300101				//(0x80300101)Parallel port is busy.

	};

	/// <summary>
	/// Class1 : example for Rockey4 class library.
	/// </summary>
	class Class1
	{
		/// <summary>
		/// Entry point of program.
		/// </summary>
		[STAThread]
		static void Main(string[] args)
		{			

            //Class of Rockey4. need adding referance of Ry4Com.dll
			CRockey4Class ry4=new CRockey4Class();

            //data used by ry4.DoCmd
			uint	lp1=0,lp2=0;
			ushort	p1=0,p2=0,p3=0,p4=0,handle=0;
			object	obBuffer=(int)0;

            //record found Rockey4(s).
			int		iMaxRockey=0;
			uint[]	uiarrRy4ID=new uint[32];
			uint	iCurrID;

			try
			{
				//demo0: Find rockey. id=0,need setting p1,p2,p3,p4 to password.
				p1=0xc44c; p2=0xc8f8; p3=0x0799; p4=0xc43b;
				ry4.DoCmd((ushort)Ry4Cmd.RY_FIND,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				uiarrRy4ID[iMaxRockey]=lp1;
				iMaxRockey++;

				//demo: Find Next rockey.
				while(true)
				{
					//Find another Ry4.
					p1=0xc44c; p2=0xc8f8; p3=0x0799; p4=0xc43b;
					ry4.DoCmd((ushort)Ry4Cmd.RY_FIND_NEXT,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

					uiarrRy4ID[iMaxRockey]=lp1;
					iMaxRockey++;
				}

			}
			catch(COMException e)
			{
				//Find OK, print all ID.
				for(int i=0; i<iMaxRockey; i++)
				{
					Console.WriteLine("({0}) {1:X8}",i,uiarrRy4ID[i]);
				}

				Console.WriteLine("Found {0} Rockey4(s)",iMaxRockey);
			}

            //select an ID.
			if(iMaxRockey>1)
			{
				Console.WriteLine("Please input the index to open.(>=0,<{0}",iMaxRockey);

				iCurrID=uiarrRy4ID[Convert.ToUInt32(Console.ReadLine())];
			}
			else iCurrID=uiarrRy4ID[0];

			try
			{
				//Demo3: Open. LP1 is Ry4ID.
				lp1=iCurrID;
				p1=0xc44c; p2=0xc8f8; p3=0x0799; p4=0xc43b;

				ry4.DoCmd((ushort)Ry4Cmd.RY_OPEN,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Ry4Type type=(Ry4Type)lp2;;
				Console.WriteLine("Opened,handle is {0:X4},type is {1}",handle,type);

				//Demo4: Write 24 bytes to UDZ. p1=index of first address, p2=length,obBuffer=data,in byte array.
				//Caution: Normal Ry4(include Ry4USB) has 24 bytes UDZ, Ry4Net,Ry4Plus has 80 bytes UDZ.

				byte[]	byWriteData=new byte[24];
				
				for(int i=0; i<24; i++) byWriteData[i]=(byte)i;

				Console.Write("Writting 24 bytes to user data zone...");

				p1=0; p2=24; obBuffer=byWriteData;
				ry4.DoCmd((ushort)Ry4Cmd.RY_WRITE,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Console.WriteLine("[OK]");

				//Demo5: Read UDZ Zone, 24 bytes.
				Console.WriteLine("Reading 24 bytes from user data zone...");

				p1=0;p2=24;obBuffer=0;
				ry4.DoCmd((ushort)Ry4Cmd.RY_READ,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				byte[] byReadData=(byte[])obBuffer;
				
                foreach(byte i in byReadData)
				{
					Console.Write("{0:X2} ",i);
				}

				Console.WriteLine("\n[OK]");

				obBuffer=0;

				//Demo6: Generate 4 random number.
				ushort[] usRandom=new ushort[4];

				Console.WriteLine("Generating 8 bytes random...");

				for(int i=0; i<4; i++)
				{
					ry4.DoCmd((ushort)Ry4Cmd.RY_RANDOM,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);
					usRandom[i]=p1;
				}

				foreach(ushort i in usRandom)
				{
					Console.Write("{0:X4} ",i);
				}

				Console.WriteLine("\n[OK]");

				//Demo7:Generate seed code. lp2 is seed.
				Console.WriteLine("Generating seed code, seed=0x193F4701...");

				lp2=0x193F4701;
				ry4.DoCmd((ushort)Ry4Cmd.RY_SEED,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Console.WriteLine("[OK], seed code is {0:X4} {1:X2} {2:X4} {3:X4}",p1,p2,p3,p4);

				//Demo8:Write UID to 0x19303A78.
				Console.WriteLine("Writting user ID, ID=0x19303A78...");

				lp1=0x19303A78;
				ry4.DoCmd((ushort)Ry4Cmd.RY_WRITE_USERID,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Console.WriteLine("[OK]");

				lp1=0;

				//Demo9: Read UID.
				Console.WriteLine("Reading user ID...");
				ry4.DoCmd((ushort)Ry4Cmd.RY_READ_USERID,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Console.WriteLine("[OK],User ID is {0:X8}",lp1);

				//Demo10:Set module 0x08, number is 3, can be decreased.
				Console.WriteLine("Setting module 8, number is 3, can be decreased...");

				p1=8; p2=3; p3=1;
				ry4.DoCmd((ushort)Ry4Cmd.RY_SET_MODULE,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Console.WriteLine("[OK]");

				//Demo11:Check module. p1=module index
				Console.WriteLine("Checking module 8...");

				p1=8;
				ry4.DoCmd((ushort)Ry4Cmd.RY_CHECK_MODULE,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Console.WriteLine("[OK], bValidate={0}, bDecreasable={1}",p2,p3);

				//Demo12: Decrease. p1=module index.
				for(int i=0; i<3; i++)
				{
					p1=8;
					Console.Write("Module 8,Decrease {0}... ",i);
					ry4.DoCmd((ushort)Ry4Cmd.RY_DECREASE,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

					//Check module status
					p1=8;
					ry4.DoCmd((ushort)Ry4Cmd.RY_CHECK_MODULE,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);


					Console.WriteLine("[OK], bValidate={0}, bDecreasable={1}",p2,p3);
				}

				//Demo13:Write arithmetic to UAZ,
 
				string csArith="A=A+B,C=C+D,B=E+F,D=G+H";

				Console.WriteLine("Writting arithmetic to UAZ,{0}",csArith);

				p1=0; obBuffer=csArith;
				ry4.DoCmd((ushort)Ry4Cmd.RY_WRITE_ARITHMETIC,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Console.WriteLine("[OK]");

				obBuffer=0;

				//Demo14,Calculate 1
				Console.Write("Calculate 1,A=1,B=2,C=3,D=4...");

				lp1=0; lp2=8; p1=1; p2=2; p3=3; p4=4;
				ry4.DoCmd((ushort)Ry4Cmd.RY_CALCULATE1,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Console.WriteLine("[OK],result: A={0:X4},B={1:X4},C={2:X4},D={3:X4}",p1,p2,p3,p4);

				//Demo15,Calculate 2
				Console.Write("Calculate 2,A=1,B=2,C=3,D=4...");

				lp1=0; lp2=0x19303A09; p1=1; p2=2; p3=3; p4=4;
				ry4.DoCmd((ushort)Ry4Cmd.RY_CALCULATE2,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Console.WriteLine("[OK],result: A={0:X4},B={1:X4},C={2:X4},D={3:X4}",p1,p2,p3,p4);

				//Demo16,Calculate 3
				Console.Write("Calculate 3,A=1,B=2,C=3,D=4...");

				lp1=0; lp2=8; p1=1; p2=2; p3=3; p4=4;
				ry4.DoCmd((ushort)Ry4Cmd.RY_CALCULATE3,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Console.WriteLine("[OK],result: A={0:X4},B={1:X4},C={2:X4},D={3:X4}",p1,p2,p3,p4);

				//Demo17,Close.
				Console.Write("Closing handle {0:X4}...",handle);

				ry4.DoCmd((ushort)Ry4Cmd.RY_CLOSE,ref handle,ref lp1,ref lp2,ref p1,ref p2,ref p3,ref p4,ref obBuffer);

				Console.WriteLine("[OK]");				

			}
			catch(COMException e)
			{
				Ry4ErrCode errCode=(Ry4ErrCode)e.ErrorCode;

				Console.WriteLine("Failed, errcode: {0}",errCode);

				Console.WriteLine("Details:{0}",e);                

			}

		}
	}
}

 
 
 