******************************************************************
* MX-DEMO.PRG
* Example for Visual FoxPro
*
* Copyright (C) TDi GmbH
*
* This file includes a sample for the implementation of the
* Matrix Dongle, and the implemantation of the TEA encryption
* algorithm.
******************************************************************

SET TALK OFF
SET CONFIRM ON
CLEAR

*******************************************************************************
**************************** MATRIX-API FUNCTIONS *****************************
*******************************************************************************

DECLARE SHORT Init_MatrixAPI IN matrix32.dll 
DECLARE SHORT Release_MatrixAPI IN matrix32.dll 
DECLARE SHORT Dongle_Find IN matrix32.dll 
DECLARE LONG  GetVersionAPI IN matrix32.dll
DECLARE SHORT GetPortAdr IN matrix32.dll SHORT
DECLARE SHORT Dongle_Count IN matrix32.dll SHORT
DECLARE LONG  Dongle_Version IN matrix32.dll SHORT, SHORT
DECLARE SHORT Dongle_MemSize IN matrix32.dll SHORT, SHORT
DECLARE SHORT Dongle_ReadData IN matrix32.dll LONG, STRING, SHORT, SHORT, SHORT
DECLARE SHORT Dongle_ReadDataEx IN matrix32.dll LONG, STRING, SHORT, SHORT, SHORT, SHORT
DECLARE LONG  Dongle_ReadSerNr IN matrix32.dll LONG, SHORT, SHORT
DECLARE SHORT Dongle_WriteData IN matrix32.dll LONG, STRING, SHORT, SHORT, SHORT
DECLARE SHORT Dongle_WriteDataEx IN matrix32.dll LONG, STRING, SHORT, SHORT, SHORT, SHORT
DECLARE SHORT Dongle_EncryptData IN matrix32.dll LONG, STRING, SHORT, SHORT 
DECLARE SHORT Dongle_DecryptData IN matrix32.dll LONG, STRING, SHORT, SHORT 


  ******************************************
  *** !!! Set your own UserCode here !!! ***
  ******************************************
  lngUserCode = 1234

  ******************************************
  *** !!! Set the Port to scan !!!       ***
  ******************************************
  DNG_Port = 85   && 1-3 = LPT1-LPT3
                  && 85  = USB


  ****************************************************************
  * Init the Matrix API
  ****************************************************************
  nRetCode = Init_MatrixAPI()
  cMsg = "Init_MatrixAPI     Return-Code:  "+LTRIM(RTRIM(STR(nRetCode)))
  MESSAGEBOX(cMsg, "Init the Matrix-API") 

  ****************************************************************
  * Search the number of connected dongles at 'DNG_Port'
  ****************************************************************
  DNG_Count = Dongle_Count(DNG_Port)
  
  IF DNG_Count < 0
     MESSAGEBOX("Error Code:  " + DNG_Count, "DONGLE COUNT")
     nRetCode = Release_MatrixAPI()
     RETURN
  ENDIF
  
  cMsg = LTRIM(RTRIM(STR(DNG_Count))) + "  Dongles found"
  IF DNG_Port = 85
     cMsg = cMsg + " at Port:  " + LTRIM(RTRIM(STR(DNG_Port))) + " (USB)"
  ENDIF
  IF DNG_Port >= 1 AND DNG_Port <= 3
     cMsg = cMsg + " at Port:  " + LTRIM(RTRIM(STR(DNG_Port))) + " (LPT)"
  ENDIF
  
  MESSAGEBOX(cMsg, "DONGLE COUNT")

  IF DNG_Count = 0
     nRetCode = Release_MatrixAPI()
     RETURN
  ENDIF


  ****************************************************************
  * Read the version and memory siize of the Dongle at 'DNG_Port'
  ****************************************************************
  nVersion = Dongle_Version(DNG_Count, DNG_Port)
  IF nVersion <= 0
     cMsg = "Version Error Code:  " + STR(nVersion)
  ELSE
     nVerMinor = INT(BITAND(nVersion, 65535))
     nVerMajor = INT(BITRSHIFT(nVersion ,16))
     cMsg = "Dongle Version   :  " + ALLTRIM(STR(nVerMajor)) + "." + ALLTRIM(STR(nVerMinor))
  ENDIF

  DNG_Mem = Dongle_MemSize(DNG_Count, DNG_Port)
  IF DNG_Mem <= 0
     cMsg = cMsg + CHR(10) + CHR(10)
     cMsg = cMsg + "MemSize Error Code:  " + STR(DNG_Mem)
  ELSE
     DNG_MaxVars = INT(DNG_Mem / 4)
     cMsg = cMsg + CHR(10) + CHR(10)
     cMsg = cMsg + "Dongle MemSize :  " + ALLTRIM(STR(DNG_Mem)) + " Bytes  =  " +;
                                          ALLTRIM(STR(DNG_MaxVars)) + " Variables"
  ENDIF
  MESSAGEBOX(cMsg, "DONGLE VERSION AND MEM-SIZE")


  ****************************************************************
  * Dongle_ReadData: Read Vars from Dongle connected at 'DNG_Port'
  * Each Variable = 4 Bytes
  * 'xvars' is the count of Variables to be read
  ****************************************************************
  xpos  = 2                 && Variable-No. where to start reading
  xvars = 14                && Count of Variables to be read from Dongle
  cBuffer = SPACE(xvars*4)  && Alloc space for the Variables to be read

  ***** Read the values from Dongle *****
  nRetCode = Dongle_ReadDataEx(lngUserCode, @cBuffer, xpos, xvars, DNG_Count, DNG_Port)

  IF nRetCode <= 0
     cMsg = "Read Error Code:  " + STR(nRetCode)
  ELSE
     *** Extract the 'xvars' Variables (each 4 Bytes) form     ***
     *** cBuffer, convert this in DEC and HEX form and display ***
     DECLARE DataIn(xvars)
     STORE 0 TO DataIn
     cMsg = ""
     FOR i = 1 TO xvars
         DataIn(i) = Convert_BinStr_To_Integer(cBuffer, i)
         cMsg = cMsg + "      Var000" + ALLTRIM(STR(i+xpos-1)) + ": " + CHR(9) + ;
                           "(dec)  " + ALLTRIM(STR(DataIn(i),11)) + CHR(9) + ;
                        "   (hex)  " + Convert_BinStr_To_HexStr(cBuffer, i) + CHR(10)
     NEXT
  ENDIF
  MESSAGEBOX(cMsg, "DONGLE READ DATA")


  ****************************************************************
  * Dongle_WriteData: Write Vars to the Dongle at 'DNG_Port'
  * Each Variable = 4 Bytes
  * 'xvars' is the count of Vars to be write
  ****************************************************************
  xpos  = 1                 && Variable-No. where to start writing
  xvars = 15                && Count of Variables to be write in Dongle

  cBuffer = ""
  DECLARE DataOut(xvars)
  FOR i = 1 TO xvars         && Fill the 'cBuffer' with Values
      DataOut(i) = 200 + i   && Integer Value
      cBuffer = cBuffer + Convert_Integer_To_BinStr(DataOut(i))  && move DataOut to cBuffer
  NEXT

  ***** Write the values to Dongle *****
  nRetCode = Dongle_WriteDataEx(lngUserCode, @cBuffer, xpos, xvars, DNG_Count, DNG_Port)

  IF nRetCode <= 0
     cMsg = "Write Error Code:  " + STR(nRetCode)
  ELSE
     cMsg = "Write successfull:" + CHR(10)
     FOR i = 1 TO xvars
         cMsg = cMsg + "      Var000" + ALLTRIM(STR(i+xpos-1)) + ": " + CHR(9) + ;
                            "(dec)  " + ALLTRIM(STR(DataOut[i],11)) + CHR(9) + ;
                         "   (hex)  " + Convert_Integer_To_HexStr(DataOut[i]) + CHR(10)
     NEXT
  ENDIF
  MESSAGEBOX(cMsg, "DONGLE WRITE DATA")


  ****************************************************************
  * Dongle_ReadSerNr: Read and display the SerialNo of the Dongle
  ****************************************************************
  nSerNr = Dongle_ReadSerNr(lngUserCode, DNG_Count, DNG_Port)

  IF nSerNr <= 0
     cMsg = "Error Code:  " + STR(nSerNr)
  ELSE
     cMsg = "SerialNo. (DEC):  " + STR(nSerNr)
  ENDIF
  MESSAGEBOX(cMsg, "DONGLE SERIAL-NO.")


  ****************************************************************
  * TEST 1: Encrypt/Decrypt a 8 Bytes Text-Buffer
  * over the Dongle
  ****************************************************************
  cBuffer = "My Crypt"  && 8 Bytes DataBlock
  cMsg = "Clear Data (STR):      " + CHR(9) + cBuffer
  
  **** Encrypt the 8 Bytes Text-Buffer ***
  nRetCode = Dongle_EncryptData(lngUserCode, @cBuffer, DNG_Count, DNG_Port)

  IF nRetCode <= 0
     cMsg = "Error Code:  " + STR(nRetCode)
  ELSE
     *** convert the encrypted 'cBuffer' in two HEX strings and display ***
     cMsg = cMsg + CHR(10) + CHR(10)
     cMsg = cMsg + "Encrypted Data (HEX):" + CHR(9)
     cMsg = cMsg + Convert_BinStr_To_HexStr(cBuffer, 1)
     cMsg = cMsg + "  :  "
     cMsg = cMsg + Convert_BinStr_To_HexStr(cBuffer, 2)
  ENDIF

  **** Decrypt the 8 Bytes encrypted Buffer ***
  nRetCode = Dongle_DecryptData(lngUserCode, @cBuffer, DNG_Count, DNG_Port)

  IF nRetCode <= 0
     cMsg = "Error Code:  " + STR(nRetCode)
  ELSE
     cMsg = cMsg + CHR(10) + CHR(10)
     cMsg = cMsg + "Decrypted Data (STR):" + CHR(9) + cBuffer
  ENDIF
  MESSAGEBOX(cMsg, "ENCRYPT / DECRYPT OVER DONGLE - TEST 1")


  ****************************************************************
  * TEST 2: Encrypt/Decrypt two LongIntegers (2 x 4 Bytes)
  * over the Dongle
  ****************************************************************
  DECLARE DataBlock(2)
  DataBlock(1) = 1234567890
  DataBlock(2) = 1234567890
  cBuffer = Convert_Integer_To_BinStr(DataBlock(1)) +;
            Convert_Integer_To_BinStr(DataBlock(2))
  
  *** convert 'cBuffer' in two DEC/HEX strings and display ***
  cMsg = "Clear Data:      " + CHR(9) + "(dec)   "
  cMsg = cMsg + ALLTRIM(STR(DataBlock(1), 11)) + CHR(9) + " :  " + ALLTRIM(STR(DataBlock(2), 11))
  cMsg = cMsg + CHR(10)

  cMsg = cMsg + CHR(9) + CHR(9) + "(hex)   "
  cMsg = cMsg + Convert_BinStr_To_HexStr(cBuffer, 1)
  cMsg = cMsg + CHR(9) + " :  "
  cMsg = cMsg + Convert_BinStr_To_HexStr(cBuffer, 2)
  
  
  **** Encrypt the 8 Bytes Buffer ***
  nRetCode = Dongle_EncryptData(lngUserCode, @cBuffer, DNG_Count, DNG_Port)

  IF nRetCode <= 0
     cMsg = "Error Code:  " + STR(nRetCode)
  ELSE
     *** convert the encrypted 'cBuffer' in two DEC/HEX strings and display ***
     DataBlock(1) = Convert_BinStr_To_Integer(cBuffer, 1)
     DataBlock(2) = Convert_BinStr_To_Integer(cBuffer, 2)
     cMsg = cMsg + CHR(10) + CHR(10)
     cMsg = cMsg + "Encrypted Data:" + CHR(9) + "(dec)   "
     cMsg = cMsg + ALLTRIM(STR(DataBlock(1), 11)) + CHR(9) + " :  " + ALLTRIM(STR(DataBlock(2), 11))
     cMsg = cMsg + CHR(10)

     cMsg = cMsg + CHR(9) + CHR(9) + "(hex)   "
     cMsg = cMsg + Convert_BinStr_To_HexStr(cBuffer, 1)
     cMsg = cMsg + CHR(9) + " :  "
     cMsg = cMsg + Convert_BinStr_To_HexStr(cBuffer, 2)
  ENDIF

  **** Decrypt the 8 Bytes encrypted Buffer ***
  nRetCode = Dongle_DecryptData(lngUserCode, @cBuffer, DNG_Count, DNG_Port)

  IF nRetCode <= 0
     cMsg = "Error Code:  " + STR(nRetCode)
  ELSE
     *** convert the 'cBuffer' in two DEC/HEX strings and display ***
     DataBlock(1) = Convert_BinStr_To_Integer(cBuffer, 1)
     DataBlock(2) = Convert_BinStr_To_Integer(cBuffer, 2)
     cMsg = cMsg + CHR(10) + CHR(10)
     cMsg = cMsg + "Decrypted Data:" + CHR(9) + "(dec)   "
     cMsg = cMsg + ALLTRIM(STR(DataBlock(1), 11)) + CHR(9) + " :  " + ALLTRIM(STR(DataBlock(2), 11))
     cMsg = cMsg + CHR(10)

     cMsg = cMsg + CHR(9) + CHR(9) + "(hex)   "
     cMsg = cMsg + Convert_BinStr_To_HexStr(cBuffer, 1)
     cMsg = cMsg + CHR(9) + " :  "
     cMsg = cMsg + Convert_BinStr_To_HexStr(cBuffer, 2)
  ENDIF
  MESSAGEBOX(cMsg, "ENCRYPT / DECRYPT OVER DONGLE - TEST 2")

  nRetCode = Release_MatrixAPI()



  ****************************************************************
  * Encrypt in the application with MxApp_Encrypt
  ****************************************************************
  SET PROCEDURE TO "mxtea.prg"

  DECLARE nData(2)
  nData[1] = 1234567890
  nData[2] = 1234567890
  
  DECLARE nKey(4)
  nKey[1] = 1111122222
  nKey[2] = 1111133333
  nKey[3] = 2222244444
  nKey[4] = 2222255555

  cMsg = "Key: " + CHR(9) + CHR(9) + "  (dec)      " + ALLTRIM(STR(nKey[1], 11)) + CHR(9) + ;
                                               ":  " + ALLTRIM(STR(nKey[2], 11)) + CHR(9) + ;
                                               ":  " + ALLTRIM(STR(nKey[3], 11)) + CHR(9) + ;
                                               ":  " + ALLTRIM(STR(nKey[4], 11)) + CHR(10) + ;
                   CHR(9) + CHR(9) + "  (hex)      " + Convert_Integer_To_HexStr(nKey[1]) + CHR(9) + ;
                                               ":  " + Convert_Integer_To_HexStr(nKey[2]) + CHR(9) + ;
                                               ":  " + Convert_Integer_To_HexStr(nKey[3]) + CHR(9) + ;
                                               ":  " + Convert_Integer_To_HexStr(nKey[4]) + CHR(9) + ;
                   CHR(10) + CHR(10) + ;
         "Clear Data:   " + CHR(9) + "  (dec)      " + ALLTRIM(STR(nData[1], 11)) + CHR(9) + ;
                                               ":  " + ALLTRIM(STR(nData[2], 11)) + CHR(10) + ;
                   CHR(9) + CHR(9) + "  (hex)      " + Convert_Integer_To_HexStr(nData[1]) + CHR(9) + ;
                                               ":  " + Convert_Integer_To_HexStr(nData[2]) + ;
                   CHR(10) + CHR(10)


  MxApp_Encrypt(@nData, @nKey)


  cMsg = cMsg + "Encrypted Data: " + CHR(9) + "  (dec)      " + ALLTRIM(STR(nData[1], 11)) + CHR(9) + ;
                                                        ":  " + ALLTRIM(STR(nData[2], 11)) + CHR(10) + ;
                            CHR(9) + CHR(9) + "  (hex)      " + Convert_Integer_To_HexStr(nData[1]) + CHR(9) + ;
                                                        ":  " + Convert_Integer_To_HexStr(nData[2])
  
  MESSAGEBOX(cMsg, "MX-APP-ENCRYPT")

  RELEASE PROCEDURE "mxtea.prg"

RETURN


*******************************************************************************
******************** STRING/INTEGER CONVERSION FUNCTIONS **********************
*******************************************************************************

*-----------------------------------------------------------------------------*
FUNCTION Convert_BinStr_To_HexStr  && Convert a Block of 4 Bytes to a HEX-String
*-----------------------------------------------------------------------------*
PARAMETER cStr, nBlock

LOCAL i, nFx, nZe, cHexStr, lnNum, nTmp

  nFx = ABS(4 - 4*nBlock)

  cHexStr = ""
  FOR nZe = 1 To 4
     lnNum = ASC(SUBSTR(cStr, nZe+nFx, 1))
     FOR b = 1 To 2
        nTmp = lnNum - INT(lnNum /16)*16
        DO CASE
           CASE nTmp = 10
                cHexStr = "A" + cHexStr 

           CASE nTmp = 11
                cHexStr = "B" + cHexStr 

           CASE nTmp = 12
                cHexStr = "C" + cHexStr 

           CASE nTmp = 13
                cHexStr = "D" + cHexStr 

           CASE nTmp = 14
                cHexStr = "E" + cHexStr 

           CASE nTmp = 15
                cHexStr = "F" + cHexStr 

           OTHERWISE
                cHexStr = ALLTRIM(STR(nTmp)) + cHexStr 

        ENDCASE

        lnNum = INT(lnNum /16)

     NEXT

  NEXT

RETURN (cHexStr)

*-----------------------------------------------------------------------------*
FUNCTION Convert_BinStr_To_Integer  && Convert a Block of 4 Bytes to Integer
*-----------------------------------------------------------------------------*
PARAMETER cStr, nVar

LOCAL i, nFx, IntValue, lnNum

  nFx = ABS(4 - 4*nVar)
  IntValue = 0

  FOR i = 1 To 4
      lnNum = ASC(SUBSTR(cStr, i+nFx, 1))
      lnNum = BITLSHIFT(lnNum, 8*(i-1))
      IntValue = BITOR(IntValue, lnNum)
  NEXT

RETURN (IntValue)

*-----------------------------------------------------------------------------*
FUNCTION Convert_Integer_To_BinStr  && Convert a Integer of 4 Bytes to Bin-String
*-----------------------------------------------------------------------------*
PARAMETER nValue

LOCAL cBuf

  cBuf = ""

  cBuf = cBuf + CHR(BITAND(nValue, 255))
  cBuf = cBuf + CHR(BITAND(BITRSHIFT(nValue, 8), 255))
  cBuf = cBuf + CHR(BITAND(BITRSHIFT(nValue, 16), 255))
  cBuf = cBuf + CHR(BITAND(BITRSHIFT(nValue, 24), 255))

RETURN (cBuf)

*-----------------------------------------------------------------------------*
FUNCTION Convert_Integer_To_HexStr  && Convert a Integer of 4 Bytes to HEX-String
*-----------------------------------------------------------------------------*
PARAMETER nValue

LOCAL cBuf

  cBuf = Convert_Integer_To_BinStr(nValue)
  cBuf = Convert_BinStr_To_HexStr(cBuf, 1)

RETURN (cBuf)