using System; using System.Net.Mail; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace Card_Dispenser_Service { internal class K720 { #region Native DLL Imports [DllImport("K720_Dll.dll")] public static extern int K720_CommOpen(string strport); [DllImport("K720_Dll.dll")] public static extern int K720_CommOpenWithBaud(string strport, int Baudate); [DllImport("K720_Dll.dll")] public static extern int K720_CommClose(int ComHandle); [DllImport("K720_Dll.dll")] public static extern int K720_SetCommBaud(int ComHandle, int Baudate, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_Reset(int ComHandle, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_GetHardVersion(int ComHandle, byte[] _Version, char[] RecordInfo); /*************************************S50***********************************************/ [DllImport("K720_Dll.dll")] public static extern int K720_S50DetectCard(int ComHandle, byte MacAddr, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S50GetCardID(int ComHandle, byte MacAddr, byte[] _CardID, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S50LoadSecKey(int ComHandle, byte MacAddr, byte SectorAddr, byte _KEYType, byte[] _KEY, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S50ReadBlock(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S50WriteBlock(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S50InitValue(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S50Increment(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S50Decrement(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S50Halt(int ComHandle, byte MacAddr, char[] RecordInfo); /*************************************S70***********************************************/ [DllImport("K720_Dll.dll")] public static extern int K720_S70DetectCard(int ComHandle, byte MacAddr, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S70DetectCard(int ComHandle, byte MacAddr, byte[] _CardID, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S70LoadSecKey(int ComHandle, byte MacAddr, byte SectorAddr, byte _KEYType, byte[] _KEY, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S70ReadBlock(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S70WriteBlock(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S70InitValue(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S70Increment(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S70Decrement(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_S70Halt(int ComHandle, byte MacAddr, char[] RecordInfo); /*************************************UL***********************************************/ [DllImport("K720_Dll.dll")] public static extern int K720_ULDetectCard(int ComHandle, byte MacAddr, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_ULGetCardID(int ComHandle, byte MacAddr, byte[] _CardID, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_ULReadBlock(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_ULWriteBlock(int ComHandle, byte MacAddr, byte SectorAddr, byte BlockAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_ULHalt(int ComHandle, byte MacAddr, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_ULGetCardID_ex(int ComHandle, byte MacAddr, byte[] _CardID, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_ULReadBlock_ex(int ComHandle, byte MacAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_ULWriteBlock_ex(int ComHandle, byte MacAddr, byte[] _BlockData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_ULLoadSecKey_ex(int ComHandle, byte MacAddr, byte[] _KEY, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_ULWriteSecKey_ex(int ComHandle, byte MacAddr, byte[] _KEY, char[] RecordInfo); /*************************************CPU TypeA***********************************************/ [DllImport("K720_Dll.dll")] public static extern int K720_CPUCardPowerOn(int ComHandle, byte MacAddr, byte[] AtrData, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_CPUAPDU(int ComHandle, byte MacAddr, byte SCH, int datalen, byte[] _APDUData, byte[] RCH, byte[] _exData, int[] exdatalen, char[] RecordInfo); /*************************************D1801***********************************************/ [DllImport("K720_Dll.dll")] public static extern int K720_GetVersion(int ComHandle, byte MacAddr, byte[] _Version, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_SendCmd(int ComHandle, byte MacAddr, byte[] p_Cmd, int length, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_Query(int ComHandle, byte MacAddr, byte[] StateInfo, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_SensorQuery(int ComHandle, byte MacAddr, byte[] StateInfo, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_GetCountSum(int ComHandle, byte MacAddr, byte[] StateInfo, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_ClearSendCount(int ComHandle, byte MacAddr, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_ClearRecycleCount(int ComHandle, byte MacAddr, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_AutoTestMac(int ComHandle, byte MacAddr, char[] RecordInfo); /*************************************15693***********************************************/ [DllImport("K720_Dll.dll")] public static extern int K720_15693LockDSFID(int ComHandle, byte MacAddr, bool Uid, byte[] UID, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_15693LockAFI(int ComHandle, byte MacAddr, bool Uid, byte[] UID, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_15693LockBlock(int ComHandle, byte MacAddr, bool Uid, byte[] UID, byte LockAddress, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_15693WriteAFI(int ComHandle, byte MacAddr, bool Uid, byte[] UID, byte WriteBit, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_15693WriteDSFID(int ComHandle, byte MacAddr, bool Uid, byte[] UID, byte WriteBit, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_15693ReadSafeBit(int ComHandle, byte MacAddr, bool Uid, byte[] UID, byte BlockAddr, byte BlockLen, byte[] ReadBlockLen, byte[] BlockLockStatus, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_15693GetMessage(int ComHandle, byte MacAddr, bool Uid, byte[] UID, byte[] Message, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_15693ChooseCard(int ComHandle, byte MacAddr, bool Uid, byte[] UID, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_15693WriteData(int ComHandle, byte MacAddr, bool Uid, byte[] UID, byte BlockAddr, byte BlockLen, byte[] _BlockData, byte[] WriteBlockLen, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_15693ReadData(int ComHandle, byte MacAddr, bool Uid, byte[] UID, byte BlockAddr, byte BlockLen, byte[] _BlockData, byte[] ReadBlockLen, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_15693GetUid(int ComHandle, byte MacAddr, byte[] UID, char[] RecordInfo); [DllImport("K720_Dll.dll")] public static extern int K720_MoveCard(byte pm); [DllImport("K720_Dll.dll")] public static extern int K720_CheckCardPosition(byte[] DeviceStatus, byte[] TransportStatus, byte[] CardBoxStatus, byte[] RetainBoxStatus); [DllImport("K720_Dll.dll")] public static extern int K720_setlog(bool flag, string path); #endregion #region Internal State Variables public int ComHandle { get; private set; } = 0; public byte MacAddr { get; private set; } = 0; public readonly char[] RecordInfo = new char[1000]; private readonly byte[] uid = new byte[8]; public string m_PortNmae = string.Empty; int m_BaudRate = 9600; internal enum CardCommand { Dispense, Return, Recycle, Read } #endregion #region Public Business Logic Interface private K720() { } public static K720 Instance { get { if (_instance == null) { _instance = new K720(); } return _instance; } } public bool Connect(string portName, int baudRate = 9600) { ComHandle = K720_CommOpenWithBaud(portName, baudRate); if (ComHandle <= 0) { Utils.LogToFile("Open serial port failed."); return false; } int nRet = -1; for (int i = 0; i < 16; i++) { nRet = K720_AutoTestMac(ComHandle, (byte)i, RecordInfo); if (nRet == 0) { MacAddr = (byte)i; break; } } if (nRet == 0) { Utils.LogToFile($"Connect Success. Found K720 Machine at MacAddr: {MacAddr}"); return true; } else { Utils.LogToFile("Can not find K720 Machine. Checking power and connection."); K720_CommClose(ComHandle); ComHandle = 0; return false; } } public bool Disconnect() { if (ComHandle == 0) return false; int nRet = K720_CommClose(ComHandle); if (nRet == 0) { Utils.LogToFile("Disconnected comm port successfully."); return false; } else { Utils.LogToFile($"Disconnect failed with error code: {nRet}"); return true ; } ComHandle = 0; } public bool MoveCardToReadPosition() { int nRet = SendCmd(CardCommand.Dispense); if (nRet == 0) { Utils.LogToFile("Move card to read position success"); return true; } Utils.LogToFile("Move card to read position failed"); return false; } public bool MoveCardToNonClipPosition() { int nRet = SendCmd(CardCommand.Return); if (nRet == 0) { Utils.LogToFile("Move card to non-clip position success"); return true; } Utils.LogToFile("Move card to non-clip position failed"); return false; } public bool RecycleCard() { int code = SendCmd(CardCommand.Recycle); if (code == 0) return true;return false; } public bool EnterCard() { byte[] info = new byte[4]; int nRet = K720_SensorQuery(ComHandle, MacAddr, info, RecordInfo); if (nRet != 0) { Utils.LogToFile("Check card position failed"); return false; } if ((info[0] & 0x04) == 0x04) // Device failure, requires reset { byte[] cmd = new byte[] { (byte)'R', (byte)'S' }; nRet = K720_SendCmd(ComHandle, MacAddr, cmd, 2, RecordInfo); if (nRet != 0) { Utils.LogToFile("Reset failed during EnterCard procedure"); return false; } Thread.Sleep(1500); } if ((info[3] & 0x03) != 0x00) { Utils.LogToFile("Channel contains a card, cannot execute enter operation"); return false; } byte[] enterCmd = new byte[] { (byte)'F', (byte)'C', (byte)'8' }; nRet = K720_SendCmd(ComHandle, MacAddr, enterCmd, 3, RecordInfo); if (nRet != 0) { Utils.LogToFile("Enter card failed"); return false; } Utils.LogToFile("Front card entrance successful"); return true; } public bool S50DetectCard() { int nRet = K720_S50DetectCard(ComHandle, MacAddr, RecordInfo); if (nRet == 0) { Utils.LogToFile("S50 Detect Card Success"); return true; } Utils.LogToFile("S50 Detect Card Failed"); return false; } public string S50GetCardID() { byte[] cardId = new byte[10]; int nRet = K720_S50GetCardID(ComHandle, MacAddr, cardId, RecordInfo); if (nRet == 0) { string parsedId = $"{cardId[0]:X2} {cardId[1]:X2} {cardId[2]:X2} {cardId[3]:X2}"; Utils.LogToFile($"S50 Get Card ID Success: {parsedId}"); return parsedId; } Utils.LogToFile("S50 Get Card ID Failed"); return null; } public string S50ReadBlock(int sectorIndex, int blockIndex) { byte[] readData = new byte[20]; int nRet = K720_S50ReadBlock(ComHandle, MacAddr, (byte)sectorIndex, (byte)blockIndex, readData, RecordInfo); if (nRet == 0) { string hexString = ""; for (int i = 0; i < 16; i++) { hexString += readData[i].ToString("X2"); } Utils.LogToFile($"S50 Read Block Success on Sec:{sectorIndex} Blk:{blockIndex}"); return hexString; } Utils.LogToFile($"S50 Read Block Failed on Sec:{sectorIndex} Blk:{blockIndex}"); return null; } public bool S50LoadSectorKey(int sectorIndex, string hexPassword, byte keyType = 0x00) { if (string.IsNullOrEmpty(hexPassword) || hexPassword.Length != 12) { Utils.LogToFile("Password length validation failed. Must be 12 hexadecimal characters."); return false; } byte[] passwordBytes = new byte[10]; Utils.StringToArray(hexPassword, passwordBytes); // keyTypeOffset handles key assignment (e.g., KeyA or KeyB mapping via 0x30 base) int nRet = K720_S50LoadSecKey(ComHandle, MacAddr, (byte)sectorIndex, (byte)(keyType + 0x30), passwordBytes, RecordInfo); if (nRet == 0) { Utils.LogToFile($"Verify Password Success for Sector: {sectorIndex}"); return true; } Utils.LogToFile($"Verify Password Failed for Sector: {sectorIndex}"); return false; } public bool ISO15693ChooseCard(bool useUidCondition) { int nRet = K720_15693ChooseCard(ComHandle, MacAddr, useUidCondition, uid, RecordInfo); if (nRet == 0) { Utils.LogToFile("15693 Choose card success"); return true; } Utils.LogToFile("15693 Choose card failed"); return false; } public string ISO15693GetUid() { int nRet = K720_15693GetUid(ComHandle, MacAddr, uid, RecordInfo); if (nRet == 0) { string hexUid = $"{uid[0]:X2}{uid[1]:X2}{uid[2]:X2}{uid[3]:X2}{uid[4]:X2}{uid[5]:X2}{uid[6]:X2}{uid[7]:X2}"; Utils.LogToFile($"15693 Get Uid Success: {hexUid}"); return hexUid; } Utils.LogToFile("15693 Get Uid Failed"); return null; } public string ISO15693ReadData(bool useUidCondition, byte startBlock, byte blockLength) { byte[] readData = new byte[50]; byte[] lenPayload = new byte[2]; int nRet = K720_15693ReadData(ComHandle, MacAddr, useUidCondition, uid, startBlock, blockLength, readData, lenPayload, RecordInfo); if (nRet == 0) { string dataResult = ""; for (int i = 0; i < lenPayload[0]; i++) { dataResult += readData[i].ToString("X2"); } Utils.LogToFile("15693 Read Data Success"); return dataResult; } Utils.LogToFile("15693 Read Data Failed"); return null; } public bool ISO15693WriteData(bool useUidCondition, byte startBlock, byte blockLength, string hexPayloadData) { byte[] dataBuffer = new byte[100]; byte[] lenPayload = new byte[2]; Utils.StringToArray(hexPayloadData, dataBuffer); int nRet = K720_15693WriteData(ComHandle, MacAddr, useUidCondition, uid, startBlock, blockLength, dataBuffer, lenPayload, RecordInfo); if (nRet == 0) { Utils.LogToFile($"15693 Write Data Success, length parsed: {lenPayload[0]}"); return true; } Utils.LogToFile("15693 Write Data Failed"); return false; } public bool ISO15693WriteAFI(bool useUidCondition, string hexValue) { if (string.IsNullOrEmpty(hexValue) || hexValue.Length != 2) { Utils.LogToFile("AFI parameter format validation failure."); return false; } byte[] segmentData = new byte[2]; Utils.StringToArray(hexValue, segmentData); int nRet = K720_15693WriteAFI(ComHandle, MacAddr, useUidCondition, uid, segmentData[0], RecordInfo); if (nRet == 0) { Utils.LogToFile("15693 Write AFI Data Success"); return true; } Utils.LogToFile("15693 Write AFI Data Failed"); return false; } public bool ISO15693LockAFI(bool useUidCondition) { int nRet = K720_15693LockAFI(ComHandle, MacAddr, useUidCondition, uid, RecordInfo); if (nRet == 0) { Utils.LogToFile("15693 Lock AFI Success"); return true; } Utils.LogToFile("15693 Lock AFI Failed"); return false; } public bool ISO15693WriteDSFID(bool useUidCondition, string hexValue) { if (string.IsNullOrEmpty(hexValue) || hexValue.Length != 2) { Utils.LogToFile("DSFID parameter format validation failure."); return false; } byte[] segmentData = new byte[2]; Utils.StringToArray(hexValue, segmentData); int nRet = K720_15693WriteDSFID(ComHandle, MacAddr, useUidCondition, uid, segmentData[0], RecordInfo); if (nRet == 0) { Utils.LogToFile("15693 Write DSFID Data Success"); return true; } Utils.LogToFile("15693 Write DSFID Data Failed"); return false; } public bool ISO15693LockDSFID(bool useUidCondition) { int nRet = K720_15693LockDSFID(ComHandle, MacAddr, useUidCondition, uid, RecordInfo); if (nRet == 0) { Utils.LogToFile("15693 Lock DSFID Success"); return true; } Utils.LogToFile("15693 Lock DSFID Failed"); return false; } public string ISO15693ReadSafeBit(bool useUidCondition, byte targetBlock, byte blockCount) { byte[] readBuffer = new byte[500]; byte[] actualLength = new byte[2]; int nRet = K720_15693ReadSafeBit(ComHandle, MacAddr, useUidCondition, uid, targetBlock, blockCount, readBuffer, actualLength, RecordInfo); if (nRet == 0) { string bitChain = ""; for (int i = 0; i < actualLength[0]; i++) { bitChain += readBuffer[i].ToString("X2"); } Utils.LogToFile("15693 Read Safe Bit Data Success"); return bitChain; } Utils.LogToFile("15693 Read Safe Bit Data Failed"); return null; } public string ISO15693GetMessage(bool useUidCondition) { byte[] extractionBuffer = new byte[100]; int nRet = K720_15693GetMessage(ComHandle, MacAddr, useUidCondition, uid, extractionBuffer, RecordInfo); if (nRet == 0) { string infoBlock = ""; for (int i = 0; i < 8; i++) { infoBlock += extractionBuffer[i].ToString("X2"); } Utils.LogToFile("15693 Get Card Information Success"); return infoBlock; } Utils.LogToFile("15693 Get Card Information Failed"); return null; } public bool ISO15693LockBlock(bool useUidCondition, byte blockIndex) { int nRet = K720_15693LockBlock(ComHandle, MacAddr, useUidCondition, uid, blockIndex, RecordInfo); if (nRet == 0) { Utils.LogToFile($"15693 Lock Block Success on Block: {blockIndex}"); return true; } Utils.LogToFile($"15693 Lock Block Failed on Block: {blockIndex}"); return false; } public string MIFAREULGetCardID() { byte[] cardId = new byte[10]; int nRet = K720_ULGetCardID_ex(ComHandle, MacAddr, cardId, RecordInfo); if (nRet == 0) { string parsedId = $"{cardId[0]:X2} {cardId[1]:X2} {cardId[2]:X2} {cardId[3]:X2}"; Utils.LogToFile($"Mifare UL Get Card ID Success: {parsedId}"); return parsedId; } Utils.LogToFile("Mifare UL Get Card ID Failed"); return null; } internal int SendCmd(CardCommand cardCommand) { String command = String.Empty; switch (cardCommand) { case CardCommand.Dispense: command = "FC4"; break; case CardCommand.Return: command = "FC8"; break; case CardCommand.Recycle: command = "CP"; break; case CardCommand.Read: command = "FC6"; break; default: break; } int nRet; byte[] cmd = new byte[10]; byte[] sourceBytes = System.Text.Encoding.ASCII.GetBytes(command); // Copy up to 10 bytes safely into your fixed-size buffer int bytesToCopy = Math.Min(sourceBytes.Length, cmd.Length); Array.Copy(sourceBytes, 0, cmd, 0, bytesToCopy); nRet = K720_SendCmd(ComHandle, MacAddr, cmd, sourceBytes.Length, RecordInfo); if (nRet == 0) { Utils.LogToFile("Command executed " + " " + command, "SendCmd"); } else { Utils.LogToFile("Command failed", "SendCmd"); } return nRet; } public string Write_Command(String data, byte sectorAddr = 0, byte blockAddr = 1) { // 1. Hard Block: Prevent writing to the Manufacturer Block (Sector 0, Block 0) if (sectorAddr == 0 && blockAddr == 0) { return new string("Write Error: Cannot write to Sector 0, Block 0 (Manufacturer/UID block).".ToCharArray()); } // 2. Warning Check: If user selects Block 3 (Sector Trailer) if (blockAddr == 3) { string warnMsg = $"Warning: You are attempting to write to Sector {sectorAddr}, Block 3.\n\n" + "This is the Sector Trailer. Writing data here overwrites your access keys. " + "If the formatting is wrong, this sector will be permanently locked.\n\n" + "Do you want to proceed?"; DialogResult result = MessageBox.Show(warnMsg, "Critical Security Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); if (result == DialogResult.No) { return new string("Write canceled by user (Protected Block 3).".ToCharArray()); } } byte keyType = 0x30; // Key A (Try switching to 0x31 for Key B if Key A fails) byte[] keyData = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; // Prepare 16 bytes of data to write from textBox18 byte[] writeData = new byte[16]; string inputHex = data.Trim(); for (int i = 0; i < 16; i++) { if (i * 2 + 2 <= inputHex.Length) { writeData[i] = Convert.ToByte(inputHex.Substring(i * 2, 2), 16); } else { writeData[i] = 0x00; } } Task.Run(() => { int nRet; char[] recordInfo = new char[256]; String returnString = String.Empty; // 1. Detect Card nRet = K720_S50DetectCard(ComHandle, MacAddr, recordInfo); if (nRet != 0) { returnString = "Card Detection Failed 0x" + nRet.ToString("X2"); return returnString; } // 2. Authenticate Key immediately prior to writing nRet = K720_S50LoadSecKey(ComHandle, MacAddr, sectorAddr, keyType, keyData, recordInfo); if (nRet != 0) { returnString = "Key Authentication Failed 0x" + nRet.ToString("X2"); return returnString; } // 3. Execute Write Block nRet = K720_S50WriteBlock(ComHandle, MacAddr, sectorAddr, blockAddr, writeData, recordInfo); if (nRet == 0) { returnString = "Write Data Success"; return returnString; } else { string message = "Write Data Failed 0x" + nRet.ToString("X8"); // Show full hex error format returnString = message; } return returnString; }); return String.Empty; } static String buffer = String.Empty; public String Read_Command(String data, byte sectorAddr, byte blockAddr) { // Capture necessary UI state on the UI thread before spinning off byte keyType = 0x30; // 0x30 for Key A, 0x31 for Key B[cite: 1] byte[] keyData = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; String returnString = String.Empty; // Spin off a separate background thread using a lambda expression Task.Run(() => { int nRet; byte[] readData = new byte[20]; // Allocate a fixed character array buffer for RecordInfo char[] recordInfo = new char[256]; // 1. Detect the S50 card[cite: 1] nRet = K720_S50DetectCard(ComHandle, MacAddr, recordInfo); if (nRet != 0) { returnString = "Card Detection Failed 0x" + nRet.ToString("X2"); return returnString; } // 2. Load and verify the sector security key[cite: 1] nRet = K720_S50LoadSecKey(ComHandle, MacAddr, sectorAddr, keyType, keyData, recordInfo); if (nRet != 0) { returnString = "Key Authentication Failed 0x" + nRet.ToString("X2"); return returnString; } // 3. Read the target block data[cite: 1] nRet = K720_S50ReadBlock(ComHandle, MacAddr, sectorAddr, blockAddr, readData, recordInfo); if (nRet == 0) { string str = ""; for (int i = 0; i < 16; i++) { str += readData[i].ToString("X2"); // Formats each byte as uppercase Hex[cite: 1] } // Safely update UI controls from the background thread data = str; returnString = "Read Data Success"; return returnString; } else { string message = "Read Data Failed 0x" + nRet.ToString("X2"); returnString = message; } return returnString; }); return String.Empty; } private static K720 _instance; #endregion } }