* ==========================================================================
* Demo: Remote Update 
* Caution: no error check for the sake of briefness and understandability
* Tips:
* (1)  Remote Update Management (RUM) is a utility that may be utilized by ROCKEY developers 
*      to implement remote updates to their software protection and licensing systems. RUM is 
*      based on "one time use" passwordsĄŁ
* (2)  The RUM process is described below:( some steps is for developer, others for end user)
*     
*      1) "a.Set new basic remote update password"
*         The software developer must first initialize the ROCKEY dongle to set the Basic 
*         Remote Update Password (BRUP). This process requires use of the super password. Once 
*         the BRUP is set it can only be changed by reformatting the dongle by means of the 
*         super password. The initialized dongle may then be distributed to the end user.  
*      2) "b.Get remote update information and the current dongle hardware ID"
*         When software developers need to remote update their software, ROCKEY software at 
*         the user end gets the relevant information (the current remote update information and 
*         hardware ID) and transfers such data by some means to the software developer.
*      3) "d.Change the privilege to super user and acquire the next remote update password."
*         Upon receiving the pertinent information, the software developer gets the next update 
*         password for the end user and transfers the new remote update password to the end user.
*      4) "f.return to password not verified status"
*         next step is demo for end user, so return to password not verified status.
*      5) "g.Verify remote update password and check if the remote update password passes the 
*          verification."
*         After receiving the new update password from the software developer, the user can send 
*         the new password to dongle for verification. If it succeeds, the remote update tag of 
*         dongle is set, the program may check the tag status to determine the corresponding 
*         actions. Because the dongle internal program can also detect the tag, it is recommended 
*         that some part of the update process be performed by the internal program.
* (3) The remote update tag, RemoteTag, is not the update password, it is the information set by 
*     the software developer for identifying the current software update status. Usually, we 
*     recommend you write the software version here, thus the software developer can tell from 
*     which version the user intends to update. It is a 32-bit number, but its highest bit is used 
*     to show whether the "hardware ID" is used or not. If the bit is 1, the update password is 
*     related to the "Hardware ID" of dongle; if it is 0, it means the update password has nothing 
*     to do with the "hardware ID", it only makes reference to the previous update password. 
*     "one time password" simplifies update maintenance of the software developer.
* (4) Additionally, the RemoteTag and RemotePass provided to users are related to each other. The 
*     user can not modify either of the two. If the highest bit of RemoteTag is 1, the update 
*     password is only valid for some specific dongle. In the information the user offers to 
*     software developer, only the hardware ID and the previous update password are necessary. 
*     The last RemoteTag is merely a reference to the software developer, and it does not affect 
*     the next update information. The software developer should set a new RemoteTag as the update 
*     mark different from the previous ones for each update operation.
* ==========================================================================

#include "Dic32_Vfp.h"
clear 
DECLARE integer   DIC_Find IN Dic32u.dll
DECLARE integer   DIC_Open IN Dic32u.dll integer hic, string @  reader_name
DECLARE integer   DIC_Close  IN Dic32u.dll  integer   hic
DECLARE integer   DIC_Command  IN Dic32u.dll  integer  hic, integer cmd, string @  cmddata
DECLARE integer   DIC_Get  IN Dic32u.dll  string @  xdata, integer  p1, integer   p2, string @  buffer
DECLARE integer   DIC_Set  IN Dic32u.dll  string @  xdata, integer  p1, integer  p2, integer   p3, string @  buffer

store 0 to  errcode		   && error code
store 0 to  num		   && number of founded card reader(s)
store 0 to  hic		   && handle of ROCKEY device.
store 0 to  i
cmddata=space(256)
buffer=space(256)
remotepass=space(8)
store 0 to	RemoteTag, HardSerial
dimension temp[8]

	num = DIC_Find()
	for i=0 to num-1
		hic = DIC_Open(i, NULL)
		if (hic >= 0) 
		  exit  	&& Stop searching once one is found.
  	  endif
	endfor
	if (i == num) 
	     return
    endif

	* a.Set the new basic remote update password.
	DIC_Set(@cmddata, REMOTE_TAG, BY_VALUE, 1, NULL) 	&& Set remote tag to 1
    for i= 0 to 7 
       DIC_Set(@buffer,i,1,asc('A'),NULL)       && et the new remote update password 8 As.
    endfor
	DIC_Set(@cmddata, REMOTE_PASS, BY_ARRAY, 0, buffer) 
	errcode = DIC_Command(hic, SET_REMOTE_INFO, @cmddata) 	&& Update remote update info

	* b.Read remote update info
	errcode = DIC_Command(hic, GET_REMOTE_INFO, @cmddata) 
	RemoteTag = DIC_Get(@cmddata, REMOTE_TAG, BY_VALUE, NULL) 
	DIC_Get(@cmddata, REMOTE_PASS, BY_ARRAY, @buffer) 
	?"RemoteTag = ", RemoteTag 
	?"RemotePass = " 
	for i=0 to 7
	   temp[i+1]=DIC_Get(@buffer,i,1,NULL)
    endfor
    ?temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[7],temp[8]
    remotepass=left(buffer,8)

	* c.Get hardware ID of the current dongle 
	errcode = DIC_Command(hic, GET_HARDWARE_INFO, @cmddata) 	&& Get dongle hardware ID
	HardSerial = DIC_Get(@cmddata, HARD_SERIAL, BY_VALUE, NULL) 

	* d.Change to super user
	* Super password is 8 FFs.
	for i=0 to 7
	    DIC_Set(@cmddata,i,1,0xff,NULL)
    endfor
	errcode = DIC_Command(hic, CHECK_SUPER_PASS, @cmddata) 

	* e.Get the next update password of the current one
	DIC_Set(@cmddata, UPGRADE_REMOTE_TAG, BY_VALUE, 2, NULL) 	&& The new update tag is 2
	DIC_Set(@cmddata, UPGRADE_HARD_SERIAL, BY_VALUE, HardSerial, NULL) 
    buffer=left(remotepass,8)
	DIC_Set(@cmddata, UPGRADE_REMOTE_PASS, BY_ARRAY, 0, @buffer) 
	errcode = DIC_Command(hic, GET_UPGRADE_REMOTE_PASS, @cmddata) 
    remotepass=left(cmddata,8)          && Transfer the new remote update password to remotepass

	* f.Change the super user status to common user status
	errcode = DIC_Close(hic) 
	errcode = DIC_Open(hic, NULL) 

	* g.Verify the remote update password
	DIC_Set(@cmddata, REMOTE_TAG, BY_VALUE, 2, NULL) 
	buffer = left( remotepass, 8 )
	DIC_Set(@cmddata, REMOTE_PASS, BY_ARRAY, 0, @buffer) 
	errcode = DIC_Command(hic, CHECK_REMOTE_INFO, @cmddata) 	&& Verify remote update info

	* h.Check if remote update password verification succeeds
	errcode = DIC_Command(hic, GET_CARD_PRIVILEGE, @cmddata) 	&&  Get privilege info
	errcode = DIC_Get(@cmddata, REMOTEPASS_STATUS, BY_VALUE, NULL)
	if (errcode != 0)
		?"Remote update password verification succeeded" 
	else 
	  ?"Remote update password verification failed" 
    endif

	* i.Read the new remote update information
	errcode = DIC_Command(hic, GET_REMOTE_INFO, @cmddata) 
	RemoteTag = DIC_Get(@cmddata, REMOTE_TAG, BY_VALUE, NULL) 
	DIC_Get(@cmddata, REMOTE_PASS, BY_ARRAY, @buffer) 
	?"RemoteTag=  ", RemoteTag 
	?"RemotePass=" 
	for i=0 to 7
	   temp[i+1]=DIC_Get(@buffer,i,1,NULL)
    endfor
    ?temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[7],temp[8]

	errcode = DIC_Close(hic)  
clear dlls
return 	