unit PCSCReader;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,ExtCtrls,strutils;

type
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    Reader: TComboBox;
    BT_Connect: TButton;
    BT_Updata: TButton;
    GroupBox2: TGroupBox;
    M1_UID: TEdit;
    M1_Key: TEdit;
    M1_Data: TEdit;
    M1_Block: TComboBox;
    Radio_KeyA: TRadioButton;
    Radio_KeyB: TRadioButton;
    BT_M1SearchCard: TButton;
    BT_M1ReadCard: TButton;
    BT_M1WriteCard: TButton;
    BT_M1HaltCard: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label5: TLabel;
    Status: TLabel;
    procedure BT_ConnectClick(Sender: TObject);
    procedure BT_UpdataClick(Sender: TObject);
    procedure BT_M1SearchCardClick(Sender: TObject);
    procedure BT_M1ReadCardClick(Sender: TObject);
    procedure BT_M1WriteCardClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure BT_M1HaltCardClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  m_bM1CardActiveFlag: Boolean;

implementation

uses Reader;

{$R *.dfm}

//Connect reader
procedure TForm1.BT_ConnectClick(Sender: TObject);
var
  bConnectFlag:Boolean;
begin
	if(m_bActiveFlag) then
	begin
		//Disconnect
		bConnectFlag := DisconnectReader();
		if(bConnectFlag) then
		begin
      BT_Connect.Caption := 'ConnectReader';
      Reader.Enabled := TRUE;
      Status.Caption := 'Please select PC/SC reader!';
		end;
	end
	else
	begin
    if(Reader.ItemIndex > -1) then
    begin
		  //Connect
		  bConnectFlag := ConnectReader(Reader.ItemIndex);
		  if(bConnectFlag) then
		  begin
        BT_Connect.Caption := 'DisConnect';
        Reader.Enabled := FALSE;
        Status.Caption := 'PC/SC reader connected!';
		  end;
    end;
	end;
end;

//Updata reader
procedure TForm1.BT_UpdataClick(Sender: TObject);
var
  bUpdataFlag : Word;
  i:integer;
begin
	bUpdataFlag := UpdataReader();
  Reader.Clear;
  Reader.Enabled := TRUE;
	if(bUpdataFlag <> 0) then
  begin
		if(m_bReaderCounter <> 0) then
		begin
      for i:= 0 to m_bReaderCounter-1 do
			begin
          Reader.Items.Add(ReaderName[i]);
			end;
      Reader.ItemIndex := 0;
		end;
    BT_Connect.Caption := 'ConnectReader';
    Status.Caption := 'Please select PC/SC reader!';
	end;
end;

//Search Card
procedure TForm1.BT_M1SearchCardClick(Sender: TObject);
var
  iSW:Word;
  CardInfo:array[0..9] of Byte;
  ReceiveLen:array[0..0] of Word;
  UID:string;
  i:integer;
begin
  M1_UID.Text := '';
  M1_Data.Text := '';
  UID := '';
  iSW := GetData(GET_MIFAREONE, @CardInfo[0], ReceiveLen[0]);
	if(SUCCESS = iSW) then
	begin
		//Request card successful
    for i:=0 to CardInfo[0]-1 do
    begin
      UID := UID + inttohex(CardInfo[i+1],2);
    end;
    M1_UID.Text := UID;
    Status.Caption := 'Search card successful!';
		m_bM1CardActiveFlag := TRUE;
	end
	else
	begin
    Status.Caption := 'Search card fail!';
		m_bM1CardActiveFlag := FALSE;
	end;
end;

//Read Card
procedure TForm1.BT_M1ReadCardClick(Sender: TObject);
var
  cKeyType,cKeyConfig:Byte;
  iSW,block,iReceiveLen:Word;
  cReceiveData:array[0..15] of Byte;
  key,Data:string;
  KeyData:array[0..5] of Byte;
  i,j:integer;
begin
	if(not m_bM1CardActiveFlag) then
	begin
		Status.Caption := 'Please clicked SearchCard button!';
		Exit;
	end;
   if Radio_KeyA.Checked = TRUE then
   begin
      cKeyType:=$60;
   end
   else
   begin
      cKeyType:=$61;
   end;

	cKeyConfig := $06;
  block      := M1_Block.ItemIndex;

  //Get Key
  key := trim(M1_Key.Text);
  if length(key) <> 12 then
  begin
    MessageBox(0,'Key length must be 6 byte','Error Key',MB_OK);
		Status.Caption := 'Key length must be 6 byte!';
    M1_Key.SetFocus;
		Exit;
  end;
   for i:=0 to 5 do begin
       val('$'+midstr(key,i*2+1,2),KeyData[i],j);
   end;
  M1_Data.Text := '';

	//Authentication
	iSW := Authentication(block, cKeyType, cKeyConfig, @KeyData[0]);
	if(SUCCESS <> iSW) then
	begin
		Status.Caption :='Authentication fail!';
		m_bM1CardActiveFlag := FALSE;
		Exit;
	end;

	//ReadCard
	iReceiveLen := 16;
	iSW := ReadBinaryBlock(block, @cReceiveData[0], iReceiveLen);
	if(SUCCESS = iSW) then
	begin
    Data:='';
    for i:=0 to iReceiveLen-1 do begin
       Data:=Data+inttohex(cReceiveData[i],2);
    end;
    M1_Data.Text := Data;
		Status.Caption :='Read card successful!';
	end
	else
		Status.Caption :='Read card fail!';
end;

//Write Card
procedure TForm1.BT_M1WriteCardClick(Sender: TObject);
var
  cKeyType,cKeyConfig:Byte;
  iSW,block:Word;
  key,Data:string;
  KeyData:array[0..5] of Byte;
  BlockData:array[0..15] of Byte;
  i,j:integer;
begin
	if(not m_bM1CardActiveFlag) then
	begin
		Status.Caption := 'Please clicked SearchCard button!';
		Exit;
	end;
   if Radio_KeyA.Checked = TRUE then
   begin
      cKeyType:=$60;
   end
   else
   begin
      cKeyType:=$61;
   end;

	cKeyConfig := $06;
  block      := M1_Block.ItemIndex;

  //Get Key
  key := trim(M1_Key.Text);
  if length(key) <> 12 then
  begin
    MessageBox(0,'Key length must be 6 byte','Error Key',MB_OK);
		Status.Caption := 'Key length must be 6 byte!';
    M1_Key.SetFocus;
		Exit;
  end;
   for i:=0 to 5 do begin
       val('$'+midstr(key,i*2+1,2),KeyData[i],j);
   end;

	//Authentication
	iSW := Authentication(block, cKeyType, cKeyConfig, @KeyData[0]);
	if(SUCCESS <> iSW) then
	begin
		Status.Caption :='Authentication fail!';
		m_bM1CardActiveFlag := FALSE;
		Exit;
	end;

	//WriteData
  //GetData
  Data := trim(M1_Data.Text);
  if length(Data) <> 32 then
  begin
    MessageBox(0,'Data length must be 16 byte','Error Key',MB_OK);
		Status.Caption := 'Data length must be 16 byte!';
    M1_Data.SetFocus;
		Exit;
  end;
   for i:=0 to 15 do begin
       val('$'+midstr(Data,i*2+1,2),BlockData[i],j);
   end;

	iSW := UpdataBinaryBlock(block, @BlockData[0], 16);
	if(SUCCESS = iSW) then
	begin
		Status.Caption :='Write card successful!';
	end
	else
		Status.Caption :='Write card fail!';
end;

//Halt Card
procedure TForm1.BT_M1HaltCardClick(Sender: TObject);
var
  iSW:Word;
begin

	iSW := TypeA_Halt();
	if(SUCCESS = iSW) then
	begin
		Status.Caption :='Halt card successful!';
	end
	else
		Status.Caption :='Halt card fail!';
end;

//Creat Form
procedure TForm1.FormCreate(Sender: TObject);
var
  i:integer;
begin
  //Block
  for i:= 0 to 63 do
  begin
    M1_Block.Items.Add(IntToStr(i));
  end;
  M1_Block.ItemIndex := 1;

  Radio_KeyA.Checked := TRUE;
  BT_UpdataClick(Sender);
end;

end.
