Files
tbf/NfcHandler/CR95HF_Reader.cs

249 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.IO.Ports;
//*****************************************************************************
// Copyright 2020 Sensus GmbH Ludwigshafen. All rights reserved.
// Author: Venkat, Rajeshwar
//*****************************************************************************
namespace Sensus.iPerl.NfcHandler
{
public class CR95HF_Reader
{
private readonly byte [] CR95HF_CMD_ECHO = { 0x55 };
private readonly byte[] CR95HF_CMD_IDN = { 0x01, 0x00 }; //CommandCode(0x01), Length(0x00)
private readonly byte[] CR95HF_CMD_PROTOCOL_SELECT_ON = { 0x02, 0x02, 0x01, 0x0D }; //CommandCode(0x02), Length(0x02), ISO/IEC 15693(0x01), 26 Kbps H, Wait for SOF, 10% modulation, Single subcarrier S, CRC appended (0x0D)
private readonly byte[] CR95HF_CMD_PROTOCOL_SELECT_OFF = { 0x02, 0x02, 0x00, 0x00 }; //CommandCode(0x02), Length(0x02), Protocol off (0x00), Protocol off (0x00)
private List<byte> CR95HF_CMD_SEND_RECEIVE = new List<byte>(); // Command code (0x04), Length (this is number of bytes after this length byte), REQUEST_FLAGS(0x02) and payload (this varies based on device command)
private readonly byte REQUEST_FLAGS = 0x02; // Single subcarrier freq, High data rate, No Inventory/ProtExtn/Select/Address/Option flags
private SERIAL_Driver _SERIAL_Driver;
public event DelNfc_CR95HF_MessageHandler MessageEvent;
private static readonly Dictionary<byte, string> CR95HF_ErrorCodes = new Dictionary<byte, string>
{
{ 0x00 , "Success, No error" },
{ 0x80 , "Success, No error" },
{ 0xA0 , "Success, No error" },
{ 0xC0 , "Success, No error" },
{ 0x82 , "Invalid command length" },
{ 0x83 , "Invalid protocol"},
{ 0x63 , "EEmdSOFerror23, SOF error in high part(duration 2 to 3 etu) in ISO/IEC 14443B"},
{ 0x65 , "EEmdSOFerror10, SOF error in low part(duration 10 to 11 etu) in ISO/IEC 14443B"},
{ 0x66 , "EEmdEgt error, Extended Guard Time error in ISO/IEC 14443B"},
{ 0x67 , "ETr1 Too Big Too long, TR1 send by the card, reception stopped in ISO/IEC 14443BT"},
{ 0x68 , "ETr1Too small Too small, TR1 send by the card in ISO/IEC 14443B"},
{ 0x71 , "EinternalError, Wrong frame format decoded"},
{ 0x85 , "EUserStop, Stopped by user(used only in Card mode)"},
{ 0x86 , "ECommError, Hardware communication error"},
{ 0x87 , "EFrameWaitTOut,Frame wait time out (no valid reception)"},
{ 0x88 , "EInvalidSof,Invalid SOF" },
{ 0x89 , "EBufOverflow,Too many bytes received and data still arriving" },
{ 0x8A , "EFramingError,if start bit = 1 or stop bit = 0"},
{ 0x8B , "EEgtError,EGT time out" },
{ 0x8C , "EInvalidLen,Valid for ISO/IEC 18092, if Length<3" },
{ 0x8D , "ECrcError,CRC error, Valid only for ISO/IEC 18092" },
{ 0x8E , "ERecvLost,CRC error,When reception is lost without EOF received(or subcarrier was lost)"},
{ 0x8F , "ENoField,CRC error,When Listen command detects the absence of external field)"},
{ 0x90 , "EUnintByte,Residual bits in last byte. Useful for ACK/NAK reception of ISO/IEC 14443 Type A"},
{ 0xFF , "Invalid COM port, request Failed" },
};
public CR95HF_Reader(SERIAL_Driver serialdriver)
{
_SERIAL_Driver = serialdriver;
}
#region Message Event
private void OnMessageEvent(string message)
{
NfcMessageEventArgs e = new NfcMessageEventArgs();
e.Message = message;
if (MessageEvent != null)
{
MessageEvent(this, e);
}
e = null;
}
#endregion
public bool OpenConnection(string comport, int baudrate, int databits, Parity parity, StopBits stopbits)
{
return _SERIAL_Driver.OpenConnection(comport, baudrate, databits, parity, stopbits);//Port Intialization and Port Open;
}
public bool CR95HF_Connect()
{
byte[] bytesReceived;
if (_SERIAL_Driver.isOpen())
{
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_IDN));
_SERIAL_Driver.SendMessage(CR95HF_CMD_IDN, CR95HF_CMD_IDN.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if (bytesReceived.Length == 17 && (bytesReceived[0] == 0x00 || bytesReceived[0] == 0x80))
{
string strReader = System.Text.Encoding.ASCII.GetString(bytesReceived);
strReader = strReader.Substring(2, 12);
OnMessageEvent("CombiHead '" + strReader + "'");
}
else
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_PROTOCOL_SELECT_ON));
_SERIAL_Driver.SendMessage(CR95HF_CMD_PROTOCOL_SELECT_ON, CR95HF_CMD_PROTOCOL_SELECT_ON.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] != 0x00) && (bytesReceived[0] != 0x80))
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
OnMessageEvent("NFC CR95HF: Protocol ON");
return true;
}
public bool CR95HF_RFProtocolOn()
{
byte[] bytesReceived;
if (_SERIAL_Driver.isOpen())
{
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_PROTOCOL_SELECT_ON));
_SERIAL_Driver.SendMessage(CR95HF_CMD_PROTOCOL_SELECT_ON, CR95HF_CMD_PROTOCOL_SELECT_ON.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] != 0x00) && (bytesReceived[0] != 0x80))
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return true;
}
public bool CR95HF_RFProtocolOff()
{
byte[] bytesReceived;
if (_SERIAL_Driver.isOpen())
{
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_PROTOCOL_SELECT_OFF));
_SERIAL_Driver.SendMessage(CR95HF_CMD_PROTOCOL_SELECT_OFF, CR95HF_CMD_PROTOCOL_SELECT_OFF.Length);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] != 0x00) && (bytesReceived[0] != 0x80))
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return true;
}
public bool CR95HF_SendRecv(byte[] fromDevice, out byte[] toDevice)
{
CR95HF_CMD_SEND_RECEIVE = new List<byte>();
toDevice = null;
if (_SERIAL_Driver.isOpen())
{
CR95HF_CMD_SEND_RECEIVE.Add(0x04);//Command Code
CR95HF_CMD_SEND_RECEIVE.Add((byte)(1 + fromDevice.Length)); // This is bytes from device + 1 (because request flags byte added here)
CR95HF_CMD_SEND_RECEIVE.Add(REQUEST_FLAGS);
CR95HF_CMD_SEND_RECEIVE.AddRange(fromDevice);
//OnMessageEvent("Tx- " + Tools.ByteArrayToHexString(CR95HF_CMD_SEND_RECEIVE.ToArray()));
_SERIAL_Driver.SendMessage(CR95HF_CMD_SEND_RECEIVE.ToArray(), CR95HF_CMD_SEND_RECEIVE.Count);
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
byte[] bytesReceived = _SERIAL_Driver.GetRawData();
//OnMessageEvent("Rx- " + Tools.ByteArrayToHexString(bytesReceived));
if ((bytesReceived[0] == 0x00) || (bytesReceived[0] == 0x80) || (bytesReceived[0] == 0xA0) || (bytesReceived[0] == 0xC0))
{
toDevice = new byte[bytesReceived[1]];
for (int i = 0; i < Convert.ToInt32(bytesReceived[1]); i++)
{
toDevice[i] = bytesReceived[2 + i];
}
}
else
{
if (CR95HF_ErrorCodes.ContainsKey(bytesReceived[0]))
OnMessageEvent("NFC CR95HF error: " + CR95HF_ErrorCodes[bytesReceived[0]]);
else
OnMessageEvent("NFC CR95HF error: Unidentified");
return false;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return true;
}
public bool CR95HF_Echo()
{
if (_SERIAL_Driver.isOpen())
{
if (_SERIAL_Driver.SendMessage(CR95HF_CMD_ECHO, 1))
{
if (_SERIAL_Driver.GetRawData().Length == 0) return false;
byte[] bytesReceived = _SERIAL_Driver.GetRawData();
if ((bytesReceived.Length == 1) && (bytesReceived[0] == CR95HF_CMD_ECHO[0]))
return true;
}
}
else
{
OnMessageEvent(_SERIAL_Driver.ErrorMessage);
return false;
}
return false;
}
}
}