/**************************************************************/
/* DEMO.JAVA                                                  */
/* Matrix example application for JAVA                        */
/*                                                            */
/* Author: vfr                                                */
/*                                                            */
/* Copyright (C) TDi GmbH                                     */
/**************************************************************/

import java.io.IOException;

public class Demo
{
    private int[] DataIn = new int[256];     /* Buffer to read the Dongle data        */
    private int[] DataOut = new int[256];    /* Buffer for data to be stored in Dongle*/
    private int[] DataBlock = new int[2];    /* Buffer for Encrypt/Decrypt            */
    private int[] KeyData = new int[4];      /* Buffer for KeyData                    */
    private short[][] DNG_Info = new short[3][3];
    private short RetCode;                   /* Return value                          */
    private int API_Version;                 /* Version number of the Matrix-API      */
    private int DNG_Version;                 /* Dongle version number                 */
    private int DNG_Serial;                  /* Dongle serial nummer                  */
    private short DNG_LPTADR;                /* Adress of LPT-Port                    */
    private short DNG_Count;                 /* Number of connected Dongles           */
    private short DNG_Mem;                   /* Memory size of Dongle                 */
    private short DNG_MaxVar;                /* Maximum number of data fields         */
    private short AppSlot;                   /* Application-Slot for Network access   */
    private short DNG_Port;
    private int UserCode;
    private short i;


    public Demo()
    {
        Matrix_Test();
        System.out.println("\nPress <Enter> to continue");
        getchar();
        Matrix_NET_Test();
    }

    public static void main(String args[])
    {
        new Demo();
    }

    /***************************************************************/
    /* Demo for the Matrix-API functions                           */
    /***************************************************************/
    public void Matrix_Test()
    {
        /*=====================================================*/
        /* In this example we use the demo UserCode 1234.      */
        /* Enter here your personal UserCode.                  */
        /*=====================================================*/
        UserCode = 1234;

        /*=====================================================*/
        /* For USB-Dongles, set DNG_Port = 'U'                 */
        /* For LPT-Dongles, set DNG_Port = 1, 2 oder 3         */
        /*=====================================================*/
//        DNG_Port = 1;   // 1-3 = LPT1-LPT3
        DNG_Port = 'U';   // 'U' (ASCII 85) = USB
        
        
        System.out.print("\n\n");

        
        /*----------------------------------------------------*/
        /* Init Matrix-API                                    */
        /*----------------------------------------------------*/
        RetCode = Matrix.rInit_MatrixAPI();
        if(RetCode < 0)
        {
            System.out.println("Init_MatrixAPI    RetCode:  " + RetCode + " \n");
        }

        
        /*----------------------------------------------------*/
        /* Read the version of the Matrix-API                 */
        /*----------------------------------------------------*/
        API_Version = Matrix.rGetVersionAPI();        
        if(API_Version == 0)
        {
            System.out.println("Error while reading API version!");
        }
        else
        {
            System.out.println("Matrix-API  Version: "
                                + HIWORD(API_Version) + "."
                                + LOWORD(API_Version));
        }

        System.out.print("\n");
        
        /*----------------------------------------------------*/
        /* Search for number of Dongles at 'DNG_Port'         */
        /*----------------------------------------------------*/
        DNG_Count = Matrix.rDongle_Count(DNG_Port);
        if(DNG_Count > 0)
        {
            System.out.println("Found: "+ DNG_Count + " Dongles at Port " + DNG_Port);
            System.out.println("--------------------------------------------------");
        }
        else
        {
            System.out.println("There is no Dongle present at Port " + DNG_Port + " !");
            Matrix.rRelease_MatrixAPI();
            return;
        }


        /*----------------------------------------------------*/
        /* Read memory size of last Dongle at DNG_Port and    */
        /* calculate the maximum number of data fields        */
        /*----------------------------------------------------*/
        DNG_Mem = Matrix.rDongle_MemSize(DNG_Count, DNG_Port);
        if(DNG_Mem > 0)
        {
           DNG_MaxVar = (short)(DNG_Mem / 4);   /* Anzahl der Datenfelder */
           System.out.println("  Memory size: " + DNG_Mem + " Bytes"
                               + " (" + DNG_MaxVar + " Data fields)");
        }
        else
        {
            System.out.println("  Error while determining Dongle memory!  Error-Code: " + DNG_Mem);
            Matrix.rRelease_MatrixAPI();
            return;
        }
 

        /*----------------------------------------------------*/
        /* Read Dongle version from last Dongle at 'DNG_Port' */
        /*----------------------------------------------------*/
        DNG_Version = Matrix.rDongle_Version(DNG_Count, DNG_Port);
        if(DNG_Version > 0)
        {
            System.out.println("  VersionNo. : " + HIWORD(DNG_Version) + "."
                                                 + LOWORD(DNG_Version));
        }
        else
        {
            System.out.println("  Error while reading Dongle version!  Error-Code: " + DNG_Version);
            Matrix.rRelease_MatrixAPI();
            return;
        }


        /*----------------------------------------------------*/
        /* Read the SerialNo. of last Dongle at 'DNG_Port'    */
        /*----------------------------------------------------*/
        DNG_Serial = Matrix.rDongle_ReadSerNr(UserCode,  DNG_Count, DNG_Port);
        if(DNG_Serial > 0)
        {
            System.out.println("  SerialNo.  : " + DNG_Serial);
        }
        else
        {
            System.out.println("  Error while reading Dongle SerialNo.!  Error-Code: " + DNG_Serial);
            Matrix.rRelease_MatrixAPI();
            return;
        }

        
        /*----------------------------------------------------*/
        /* Read 3 data fields from last Dongle at 'DNG_Port'  */
        /* via UserCode and display.                          */
        /*----------------------------------------------------*/
        System.out.println("\nRead / Write of Dongle-Data ");
        System.out.println("--------------------------------------------------");
        System.out.print("\n  Dongle_ReadData  ->");
        
        RetCode = 0;
        try
        {
            RetCode = Matrix.rDongle_ReadData(UserCode, DataIn, (short)3, DNG_Count, DNG_Port);
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }
        if(RetCode < 0)
        {
            System.out.println("  Error while reading Dongle data!  Error-Code: " + RetCode);
            Matrix.rRelease_MatrixAPI();
            return;
        }
        System.out.println("  Var1 = " + DataIn[0]
                         + ", Var2 = " + DataIn[1]
                         + ", Var3 = " + DataIn[2]);

        
        /*----------------------------------------------------*/
        /* Save 3 data fields in last Dongle at 'DNG_Port'    */
        /* via UserCode.                                      */
        /* The values 101,102,103 are saved as example.       */
        /*----------------------------------------------------*/
        System.out.print("\n  Dongle_WriteData ->");
                
        for(i = 0; i < 3; i++)
        {
            DataOut[i] = 101 + i;
        }
        RetCode = 0;
        try
        {
            RetCode = Matrix.rDongle_WriteDataEx(UserCode, DataOut, (short)1, (short) 3, DNG_Count, DNG_Port);
        }
        catch(Throwable e)
        {
            e.printStackTrace();
        }
        if(RetCode < 0)
        {
            System.out.println("  Error while writing Dongle data!  Error-Code: " + RetCode);
            Matrix.rRelease_MatrixAPI();
            return;
        }
        System.out.println("  Dongle data  "
                           + DataOut[0] + ", " + DataOut[1] + ", " + DataOut[2]
                           + "  written successfully");

        System.out.println("\n\nPress <Enter> to continue: ");
        getchar();
        

        /*----------------------------------------------------*/
        /* Encrypt/Decrypt a DataBlock over the Dongle        */
        /*----------------------------------------------------*/
        System.out.println("\nEncrypt/decrypt of Data over the Dongle");
        System.out.println("--------------------------------------------------");
        DataBlock[0] = 1234567890;  /* Clear Data */
        DataBlock[1] = 1234567890;  /* Clear Data */
        System.out.println("  Clear Data:      (dec)  " + DataBlock[0] + "\t" + DataBlock[1]);
        System.out.println("                   (hex)  " + Integer.toHexString(DataBlock[0]) + "\t"
                                                        + Integer.toHexString(DataBlock[1]) + "\n");

        /*--- Encrypt ---*/
        RetCode = 0;
        try
        {
            RetCode = Matrix.rDongle_EncryptData(UserCode, DataBlock, DNG_Count, DNG_Port);
        }
        catch(Throwable excEncrypt)
        {
            excEncrypt.printStackTrace();
        }
        if(RetCode < 0)
        {
            System.out.println(" Data Encryption-Error! " + RetCode);
            Matrix.rRelease_MatrixAPI();
            return;
        }
        System.out.println("  Encrypted Data:  (dec)  " + DataBlock[0] + "\t" + DataBlock[1]);
        System.out.println("                   (hex)  " + Integer.toHexString(DataBlock[0]) + "\t"
                                                        + Integer.toHexString(DataBlock[1]) + "\n");

        /*--- Decrypt ---*/
        RetCode = 0;
        try
        {
            RetCode = Matrix.rDongle_DecryptData(UserCode, DataBlock, DNG_Count, DNG_Port);
        }
        catch(Throwable excDecrypt)
        {
            excDecrypt.printStackTrace();
        }
        if(RetCode < 0)
        {
            System.out.println("  Data Decryption-Error! " + RetCode);
            Matrix.rRelease_MatrixAPI();
            return;
        }
        System.out.println("  Decrypted Data:  (dec)  " + DataBlock[0] + "\t" + DataBlock[1]);
        System.out.println("                   (hex)  " + Integer.toHexString(DataBlock[0]) + "\t"
                                                        + Integer.toHexString(DataBlock[1]));
        
        /*----------------------------------------------------*/
        /* Close Matrix-API                                   */
        /*----------------------------------------------------*/
        Matrix.rRelease_MatrixAPI();

        
        /*----------------------------------------------------*/
        /* Encrypt/Decrypt a DataBlock in the Application     */
        /*----------------------------------------------------*/
        System.out.println("\nEncrypt/decrypt of Data in the Application");
        System.out.println("--------------------------------------------------");

        KeyData[0] = 0x423A612E;  //1111122222;    /* Key Data */
        KeyData[1] = 0x423A8C95;  //1111133333;    /* Key Data */
        KeyData[2] = 0x8474C25C;  //2222244444;    /* Key Data */
        KeyData[3] = 0x8474EDC3;  //2222255555;    /* Key Data */
        
        DataBlock[0] = 1234567890;  /* Clear Data */
        DataBlock[1] = 1234567890;  /* Clear Data */
        
        System.out.println("  Key: (dec) " + KeyData[0] + "\t  " + KeyData[1] + "\t"
                                           + KeyData[2] + "\t" + KeyData[3]);
        System.out.println("       (hex) " + Integer.toHexString(KeyData[0]) + "\t  "
                                           + Integer.toHexString(KeyData[1]) + "\t"
                                           + Integer.toHexString(KeyData[2]) + "\t"
                                           + Integer.toHexString(KeyData[3]) + "\n");
        System.out.println("  Clear Data:     (dec)  " + DataBlock[0] + "\t" + DataBlock[1]);
        System.out.println("                  (hex)  " + Integer.toHexString(DataBlock[0]) + "\t"
                                                       + Integer.toHexString(DataBlock[1]));

        /*--- Encrypt ---*/
        MxTea.MxApp_Encrypt(DataBlock, KeyData);

        System.out.println("  Encrypted Data: (dec)  " + DataBlock[0] + "\t" + DataBlock[1]);
        System.out.println("                  (hex)  " + Integer.toHexString(DataBlock[0]) + "\t"
                                                       + Integer.toHexString(DataBlock[1]));

        /*--- Decrypt ---*/
        MxTea.MxApp_Decrypt(DataBlock, KeyData);

        System.out.println("  Decrypted Data: (dec)  " + DataBlock[0] + "\t" + DataBlock[1]);
        System.out.println("                  (hex)  " + Integer.toHexString(DataBlock[0]) + "\t"
                                                       + Integer.toHexString(DataBlock[1]));

    }


    /***************************************************************/
    /* Demo for the Matrix Network functions                       */
    /***************************************************************/
    void Matrix_NET_Test()
    {
        System.out.println("\nNetwork functions ");
        System.out.println("--------------------------------------------------");

        /*====================================================*/
        /* Network                                            */
        /* Example: the dongle is prepared with the value 7   */
        /*          in Var0002, meaning AppSlot=2 and         */
        /*          max. Users = 7                            */
        /*====================================================*/

        /*----------------------------------------------------*/
        /* Init Matrix-API                                    */
        /*----------------------------------------------------*/
        RetCode = Matrix.rInit_MatrixAPI();
        if(RetCode < 0)
        {
            System.out.println("Init_MatrixAPI    RetCode:  " + RetCode + "\n");
        }

        /*----------------------------------------------------*/
        /* Max. Users stored in AppSlot 2 (Var0002 of the     */
        /* dongle)                                            */
        /*----------------------------------------------------*/
        AppSlot = 2;

        /*----------------------------------------------------*/
        /* Read the Dongle count from MxNetFile               */
        /* !! 'DNG_Port' is ignored in the Network mode !!    */
        /*----------------------------------------------------*/
        DNG_Count = Matrix.rDongle_Count(DNG_Port);

        /*----------------------------------------------------*/
        /* 'LogIn' will lock one User-Slot and the returned   */
        /* value is the remaining free User-Slots (for our    */
        /* Example RetCode=6)                                 */
        /*----------------------------------------------------*/
        RetCode = Matrix.rLogIn_MatrixNet(UserCode, AppSlot, DNG_Count);
        if(RetCode < 0)
        {
            if(RetCode == -31)
            {
                System.out.println("  All Users are active!");
                System.out.println("  No more User-Slots free\n");
            }
            else
            {
                System.out.println("LogIn failed  " + RetCode);
            }
        }
        else
        {
            System.out.println("LogIn successfull !  Free User-Slots: " + RetCode + " \n");
 
            System.out.print("\n  Press <Enter> to continue:  ");
            getchar();
        }

        /*----------------------------------------------------*/
        /* 'LogOut' will free the User-Slot and the returned  */
        /* value is the remaining free User-Slots (for our    */
        /* Example RetCode=7)                                 */
        /*----------------------------------------------------*/
        RetCode = Matrix.rLogOut_MatrixNet(UserCode, AppSlot, DNG_Count);
        if(RetCode < 0)
        {
            System.out.println("\nLogOut failed  " + RetCode);
        }
        else
        {
            System.out.println("\nLogOut successfull!  Free User-Slots: " + RetCode);
        }

        /*----------------------------------------------------*/
        /* Close Matrix-API                                   */
        /*----------------------------------------------------*/
        Matrix.rRelease_MatrixAPI();
    }
    
    
    /**
     * Handling for Hi- / Lo-Word
     */
    public short HIWORD(int var)
    {
        return (short)(var >>> 16);
    }

    public short LOWORD(int var)
    {
        return (short)(var & 0xffff);
    }

    /**
     * Stop the program until a key is pressed
     */
    public static void getchar()
    {
        int myInt = 1;
        try
        {
            myInt = System.in.read();
            Thread.sleep(200);
            while(System.in.available() > 0)
            {
                myInt = System.in.read();
                Thread.sleep(200);
            }
        }
        catch(InterruptedException e)
        {
            e.printStackTrace();
        }
        catch(IOException e)
        {
            e.printStackTrace();
        }
    }

}

