using System;
using System.Collections.Generic;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using QCRPG.Framework;
using QCRPG.TSL.FM;
using QCRPG.TSL.NFC;

namespace QC.NFC_DIAG_BRIDGE;

internal class NFC_DIAG_Bridge
{
	private enum CmdCode
	{
		version = 0,
		esn = 1,
		status = 12,
		nvItemRead = 38,
		phoneState = 63,
		subSystemDispatch = 75,
		featureQuery = 81,
		embeddedFileOperation = 89,
		diagProtLoopback = 123,
		extendedBuildID = 124,
		logMask = 115
	}

	private enum SubsystemID
	{
		FTMSubsystem = 11
	}

	public enum ConnectionType
	{
		SERIAL,
		USB,
		INVALID
	}

	public class PacketDataObserver : QCRPG.Framework.IObserver<IncomingPacketData>, QCRPG.Framework.IObserver<OutgoingPacketData>
	{
		public void NotifyObserver(IncomingPacketData packetData)
		{
			if (packetData.type == PacketDataType.Data)
			{
				byte[] array = new byte[258];
				int num = packetData.bytes.Length;
				int num2 = num / 2;
				if (packetData.bytes.Length > 1)
				{
					try
					{
						num = packetData.bytes.Length;
						if (packetData.bytes[num - 1] == 10)
						{
							num--;
						}
						array = Conversions.HexAsciiByteArrayToByteArray(packetData.bytes, num);
						num2 = array.Length;
					}
					catch (Exception ex)
					{
						diagBridgeHandle.LogException(ex);
						Console.WriteLine("\n\nFailed to Conversions.HexAsciiByteArrayToByteArray(packetData.bytes) \n");
					}
				}
				byte b = array[0];
				bool flag = false;
				if (b >= 64 && b <= 79 && num2 > 2 && array[2] == num2 - 3)
				{
					flag = true;
				}
				bool flag2 = false;
				if (b >= 96 && b <= 111 && num2 > 2 && array[2] == num2 - 3)
				{
					flag2 = true;
				}
				if (flag)
				{
					Console.WriteLine("NCI Response Data In (from DUT): " + Conversions.ByteArrayTo0xHexString(array, num2) + "\r\n");
					int num3 = num2;
					byte[] array2 = new byte[10 + num3];
					array2[0] = 75;
					array2[1] = 11;
					array2[2] = 55;
					array2[3] = 0;
					array2[4] = 2;
					array2[5] = 0;
					int num4 = 2 + num3;
					array2[6] = (byte)((uint)num4 & 0xFFu);
					array2[7] = (byte)((num4 & 0xFF00) >> 8);
					array2[8] = (byte)((uint)num3 & 0xFFu);
					array2[9] = (byte)((num3 & 0xFF00) >> 8);
					for (int i = 0; i < num3; i++)
					{
						array2[10 + i] = array[i];
					}
					Console.WriteLine("FTM Diag Response (to QPST): " + Conversions.ByteArrayTo0xHexString(array2) + "\r\n");
					DiagPrintToStream(array2, check: true);
				}
				if (flag2)
				{
					Console.WriteLine("NCI Notification Data In (from DUT): " + Conversions.ByteArrayTo0xHexString(array, num2) + "\r\n");
					byte[] array3 = null;
					array3 = new byte[16 + num2];
					byte[] array4 = new byte[16]
					{
						16, 0, 18, 0, 18, 0, 2, 24, 229, 98,
						42, 197, 255, 1, 0, 0
					};
					for (int j = 0; j < 16; j++)
					{
						array3[j] = array4[j];
					}
					for (int k = 0; k < num2; k++)
					{
						array3[16 + k] = array[k];
					}
					int num5 = array3.Length - 4;
					array3[2] = (byte)num5;
					array3[4] = (byte)num5;
					DiagPrintToStream(array3, check: true);
					Console.WriteLine("Diag log packet 1802 Data Out (to QPST): " + Conversions.ByteArrayTo0xHexString(array3) + "\r\n");
				}
			}
			else if (packetData.type == PacketDataType.WarningMessage)
			{
				Console.WriteLine("Warning: " + Conversions.ByteArrayToString(packetData.bytes));
			}
		}

		public void NotifyObserver(OutgoingPacketData packetData)
		{
			if (packetData.type != 0 && packetData.type == PacketDataType.WarningMessage)
			{
				Console.WriteLine("Warning: " + Conversions.ByteArrayToString(packetData.bytes));
			}
		}
	}

	public class PacketObserver : QCRPG.Framework.IObserver<PacketBase>
	{
		public void NotifyObserver(PacketBase packet)
		{
			Console.WriteLine(packet.Info.Name);
			foreach (PacketFieldInfo fieldInfo in packet.Info.FieldInfoList)
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append(fieldInfo.ParameterName + " = " + fieldInfo.Value);
				if (!string.IsNullOrEmpty(fieldInfo.ValueNote))
				{
					stringBuilder.Append(" ( " + fieldInfo.ValueNote + " ) ");
				}
				Console.WriteLine(stringBuilder.ToString());
			}
			Console.WriteLine("Raw bytes = " + Conversions.ByteArrayTo0xHexString(packet.ToByteArray()));
			Console.WriteLine("\r\n");
		}
	}

	public class LogMessageObserver : QCRPG.Framework.IObserver<LogMessage>
	{
		private int errorCount;

		public void ResetErrorCount()
		{
			errorCount = 0;
		}

		public int GetErrorCount()
		{
			return errorCount;
		}

		public void NotifyObserver(LogMessage logMessage)
		{
			foreach (string line in logMessage.Lines)
			{
				Console.WriteLine(logMessage.Type.ToString() + ": " + line + "\r\n");
				if (logMessage.Type == LogMessageType.Error)
				{
					errorCount++;
				}
			}
		}
	}

	private const byte DIAG_TERM_CHAR = 126;

	private static NetworkStream ntwStream = null;

	private static NFC_DIAG_Bridge diagBridgeHandle = null;

	protected static FMBuilder fmBuilder;

	private static NFCBuilder nfcBuilder;

	private static FMAPI fmAPI;

	private static NFCAPI nfcAPI;

	protected static CombinedScripter combinedScripter;

	private PacketDataObserver rawBytesObserver = new PacketDataObserver();

	private PacketObserver packetObserver = new PacketObserver();

	private LogMessageObserver logMessageObserver = new LogMessageObserver();

	private static ConnectionType connectionTypeOptions = ConnectionType.SERIAL;

	private static bool decodeNciCmdPkt = false;

	private static byte[] verResponseMsg = new byte[55]
	{
		0, 79, 99, 116, 32, 48, 56, 32, 50, 48,
		49, 49, 49, 48, 58, 48, 55, 58, 48, 48,
		79, 99, 116, 32, 48, 56, 32, 50, 48, 49,
		49, 49, 48, 58, 48, 55, 58, 48, 48, 65,
		65, 65, 49, 48, 48, 48, 48, 0, 1, 255,
		1, 0, 0, 1, 0
	};

	private static byte[] logMaskResponseFirstMsg = new byte[76]
	{
		115, 0, 0, 0, 1, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 166, 5, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 16, 9,
		0, 0, 32, 4, 0, 0, 0, 0, 0, 0,
		86, 11, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 138, 3, 0, 0, 1, 2, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0
	};

	private static byte[] logMaskResponseSecondMsg = new byte[201]
	{
		115, 0, 0, 0, 4, 0, 0, 0, 0, 0,
		0, 0, 1, 0, 0, 0, 166, 5, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 16, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 64, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0
	};

	private static byte[] esnResponseMsg = new byte[5] { 1, 239, 190, 173, 222 };

	private static byte[] statusResponseMsg = new byte[48]
	{
		12, 0, 0, 0, 206, 250, 190, 186, 6, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 255, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0
	};

	private static byte[] nvItemReadResponseMsg = new byte[69]
	{
		38, 71, 0, 78, 70, 67, 46, 68, 73, 65,
		71, 46, 66, 82, 73, 68, 71, 69, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0
	};

	private static byte[] phoneStateResponseMsg = new byte[4] { 63, 1, 0, 0 };

	private byte[] featureQueryRespMsg = new byte[4] { 81, 0, 0, 0 };

	private static byte[] extendedBuildIDRespMsg = new byte[30]
	{
		124, 2, 0, 0, 232, 3, 0, 0, 16, 39,
		0, 0, 49, 0, 78, 70, 67, 46, 68, 73,
		65, 71, 46, 66, 82, 73, 68, 71, 69, 0
	};

	private static bool startupBuilderDone = false;

	private static void DiagPrintToStream(byte[] response, bool check = false)
	{
		int num = response.Length;
		ushort num2 = Calc_CRC_16_l(response, num);
		byte[] array = new byte[num + 2];
		for (int i = 0; i < num; i++)
		{
			array[i] = response[i];
		}
		array[num] = (byte)(num2 & 0xFFu);
		array[num + 1] = (byte)(num2 >> 8);
		List<byte> list = new List<byte>();
		for (int j = 0; j < array.Length; j++)
		{
			if (array[j] == 125 || array[j] == 126)
			{
				if (check)
				{
					list.Add(125);
					byte item = (byte)(array[j] ^ 0x20u);
					list.Add(item);
				}
				else
				{
					list.Add(array[j]);
				}
			}
			else
			{
				list.Add(array[j]);
			}
		}
		num = list.Count;
		array = new byte[num];
		array = list.ToArray();
		byte[] array2 = new byte[array.Length + 1];
		for (int k = 0; k < array.Length; k++)
		{
			array2[k] = array[k];
		}
		array2[array.Length] = 126;
		if (ntwStream != null)
		{
			ntwStream.Write(array2, 0, array2.Length);
		}
	}

	private static ushort Calc_CRC_16_l(byte[] pBufPtr, int bufLen)
	{
		ushort[] array = new ushort[256]
		{
			0, 4489, 8978, 12955, 17956, 22445, 25910, 29887, 35912, 40385,
			44890, 48851, 51820, 56293, 59774, 63735, 4225, 264, 13203, 8730,
			22181, 18220, 30135, 25662, 40137, 36160, 49115, 44626, 56045, 52068,
			63999, 59510, 8450, 12427, 528, 5017, 26406, 30383, 17460, 21949,
			44362, 48323, 36440, 40913, 60270, 64231, 51324, 55797, 12675, 8202,
			4753, 792, 30631, 26158, 21685, 17724, 48587, 44098, 40665, 36688,
			64495, 60006, 55549, 51572, 16900, 21389, 24854, 28831, 1056, 5545,
			10034, 14011, 52812, 57285, 60766, 64727, 34920, 39393, 43898, 47859,
			21125, 17164, 29079, 24606, 5281, 1320, 14259, 9786, 57037, 53060,
			64991, 60502, 39145, 35168, 48123, 43634, 25350, 29327, 16404, 20893,
			9506, 13483, 1584, 6073, 61262, 65223, 52316, 56789, 43370, 47331,
			35448, 39921, 29575, 25102, 20629, 16668, 13731, 9258, 5809, 1848,
			65487, 60998, 56541, 52564, 47595, 43106, 39673, 35696, 33800, 38273,
			42778, 46739, 49708, 54181, 57662, 61623, 2112, 6601, 11090, 15067,
			20068, 24557, 28022, 31999, 38025, 34048, 47003, 42514, 53933, 49956,
			61887, 57398, 6337, 2376, 15315, 10842, 24293, 20332, 32247, 27774,
			42250, 46211, 34328, 38801, 58158, 62119, 49212, 53685, 10562, 14539,
			2640, 7129, 28518, 32495, 19572, 24061, 46475, 41986, 38553, 34576,
			62383, 57894, 53437, 49460, 14787, 10314, 6865, 2904, 32743, 28270,
			23797, 19836, 50700, 55173, 58654, 62615, 32808, 37281, 41786, 45747,
			19012, 23501, 26966, 30943, 3168, 7657, 12146, 16123, 54925, 50948,
			62879, 58390, 37033, 33056, 46011, 41522, 23237, 19276, 31191, 26718,
			7393, 3432, 16371, 11898, 59150, 63111, 50204, 54677, 41258, 45219,
			33336, 37809, 27462, 31439, 18516, 23005, 11618, 15595, 3696, 8185,
			63375, 58886, 54429, 50452, 45483, 40994, 37561, 33584, 31687, 27214,
			22741, 18780, 15843, 11370, 7921, 3960
		};
		int num = 0;
		int num2 = bufLen * 8;
		ushort num3 = ushort.MaxValue;
		while (num2 >= 8)
		{
			num3 = (ushort)(array[(num3 ^ pBufPtr[num]) & 0xFF] ^ (num3 >> 8));
			num2 -= 8;
			num++;
		}
		if (num2 != 0)
		{
			ushort num4 = (ushort)(pBufPtr[num] << 8);
			while (num2-- != 0)
			{
				if (((uint)(num3 ^ num4) & (true ? 1u : 0u)) != 0)
				{
					num3 >>= 1;
					num3 = (ushort)(num3 ^ 0x8408u);
				}
				else
				{
					num3 >>= 1;
				}
				num4 >>= 1;
			}
		}
		return (ushort)(~num3);
	}

	private static int processDiagPacket_Nfc(byte[] inputDIAGMsg)
	{
		switch (inputDIAGMsg[0])
		{
		case 115:
			Console.WriteLine("Log Mask\n");
			if (inputDIAGMsg[4] == 1)
			{
				DiagPrintToStream(logMaskResponseFirstMsg);
			}
			else if (inputDIAGMsg[4] == 4)
			{
				DiagPrintToStream(logMaskResponseSecondMsg);
			}
			return 1;
		case 0:
			Console.WriteLine("echo for version \n");
			DiagPrintToStream(verResponseMsg);
			return 1;
		case 1:
			Console.WriteLine("echo for esn\n");
			DiagPrintToStream(esnResponseMsg);
			return 1;
		case 12:
			DiagPrintToStream(statusResponseMsg);
			return 1;
		case 63:
			Console.WriteLine("echo for phoneState\n");
			DiagPrintToStream(phoneStateResponseMsg);
			return 1;
		case 38:
			Console.WriteLine("echo for nvItemRead\n");
			DiagPrintToStream(nvItemReadResponseMsg);
			return 1;
		case 75:
			Console.WriteLine("\n>SubsystemDispatch Diag packet received of type {0} \n", inputDIAGMsg[0]);
			Console.WriteLine("\n");
			if (inputDIAGMsg[1] == 11 && inputDIAGMsg[2] == 55 && inputDIAGMsg[3] == 0)
			{
				int num2 = inputDIAGMsg.Length;
				byte[] array = new byte[num2];
				int num3 = 0;
				for (int j = 0; j < num2; j++)
				{
					if (j < num2 - 1)
					{
						if (inputDIAGMsg[j] == 125 || inputDIAGMsg[j + 1] == 94)
						{
							array[num3] = 126;
							j++;
						}
						else
						{
							array[num3] = inputDIAGMsg[j];
						}
					}
					else
					{
						array[num3] = inputDIAGMsg[j];
					}
					num3++;
				}
				int length = 8 + array[6] + array[7] * 256;
				byte b = array[4];
				switch (b)
				{
				case 2:
				{
					Console.WriteLine("Incoming FTM command containing a NCI Command packet");
					Console.WriteLine("FTM Diag Data In (from QPST): " + Conversions.ByteArrayTo0xHexString(array, length) + "\r\n");
					int num5 = array[8] + array[9] * 256;
					byte[] array4 = new byte[num5];
					for (int m = 0; m < num5; m++)
					{
						array4[m] = array[10 + m];
					}
					diagBridgeHandle.Send_Nfc(array4);
					break;
				}
				case 3:
				{
					Console.WriteLine("Incoming FTM command containing a NCI Data packet\r\n");
					Console.WriteLine("FTM Diag Data In (from QPST): " + Conversions.ByteArrayTo0xHexString(array, length) + "\r\n");
					int num4 = array[8] + array[9] * 256;
					byte[] array3 = new byte[num4];
					for (int l = 0; l < num4; l++)
					{
						array3[l] = array[10 + l];
					}
					diagBridgeHandle.Send_Nfc(array3);
					if (b == 3)
					{
						diagBridgeHandle.SendDataAck();
					}
					break;
				}
				case 0:
				{
					Console.WriteLine("Incoming FTM command for I2C Write\r\n");
					Console.WriteLine("FTM Diag Data In (from QPST): " + Conversions.ByteArrayTo0xHexString(array, length) + "\r\n");
					byte slaveAddress2 = array[8];
					byte b3 = array[9];
					byte[] array5 = new byte[b3];
					byte[] array6 = new byte[b3];
					for (int n = 0; n < b3; n++)
					{
						array5[n] = array[10 + 2 * n];
						array6[n] = array[11 + 2 * n];
					}
					diagBridgeHandle.MultiI2cWrite_Nfc(slaveAddress2, b3, array5, array6);
					break;
				}
				case 1:
				{
					Console.WriteLine("Incoming FTM command for I2C Read\r\n");
					Console.WriteLine("FTM Diag Data In (from QPST): " + Conversions.ByteArrayTo0xHexString(array, length) + "\r\n");
					byte slaveAddress = array[8];
					byte b2 = array[9];
					byte[] array2 = new byte[b2];
					for (int k = 0; k < b2; k++)
					{
						array2[k] = array[10 + k];
					}
					diagBridgeHandle.MultiI2cRead_Nfc(slaveAddress, b2, array2);
					break;
				}
				}
			}
			else
			{
				DiagPrintToStream(inputDIAGMsg);
			}
			return 1;
		case 123:
		{
			Console.WriteLine("echo for diagProtLoopback\n");
			int num = 0;
			for (int i = 0; i < inputDIAGMsg.Length; i++)
			{
				if (inputDIAGMsg[i] == 126)
				{
					num = i;
					break;
				}
			}
			ntwStream.Write(inputDIAGMsg, 0, num + 1);
			return 1;
		}
		case 124:
			Console.WriteLine("echo for extendedBuildID\n");
			DiagPrintToStream(extendedBuildIDRespMsg);
			return 1;
		default:
			Console.WriteLine("In default\n");
			return 1;
		}
	}

	private static void CleanupBeforeShutdown_Nfc(TcpClient clientConnectionHandle)
	{
		diagBridgeHandle.CompleteShutdown_Nfc();
		DisconnectFromQPST(clientConnectionHandle);
	}

	private static void DisconnectFromQPST(TcpClient clientConnectionHandle)
	{
		if (clientConnectionHandle.Connected)
		{
			clientConnectionHandle.Close();
			Console.WriteLine(">>>Disconnected from QPST");
		}
	}

	public static void Main(string[] args)
	{
		TcpClient clientConnectionHandle = new TcpClient();
		Console.CancelKeyPress += delegate
		{
			CleanupBeforeShutdown_Nfc(clientConnectionHandle);
		};
		string value = "";
		string value2 = "57600";
		string value3 = "localhost";
		int result = 2500;
		byte b = 0;
		string value4 = "";
		bool flag = false;
		string value5 = "";
		string value6 = "";
		string value7 = "";
		bool flag2 = false;
		if (args.Length < 1)
		{
			Console.WriteLine("Require at least 1 argument\nExample: QC.NFC.DIAG.BRIDGE.exe ComPort=COM10 IPADDRESS=localhost(optional, default=localhost) PORT=2500(optional, default=2500) I2CSlaveAddress=2C(optional, default=2C) BaudRate=57600(optional, default=57600) tclFile=Bringup.tcl tclDir=C:\\QUALCOMM\\WCN\\NFC_DIAG_BRIDGE\\scripts tclInstallPath=C:\\QUALCOMM\\WCN\\NFC_DIAG_BRIDGE\\Tcl Patch=C:\\QUALCOMM\\WCN\\NFC_DIAG_BRIDGE\\FirmwarePatch\\QCA1990_2.4\\Signedrompatch.bin(optional) DecodeNci=true(optional, default=false ) \n");
			return;
		}
		Dictionary<string, string> dictionary = new Dictionary<string, string>(args.Length);
		foreach (string text in args)
		{
			try
			{
				string[] array = text.Split('=');
				dictionary.Add(array[0].ToUpper(), array[1].ToUpper());
			}
			catch (Exception ex)
			{
				Console.WriteLine($"Invalid input argument, no spaces are allowed between =. Example: IPADDRESS=localhost PORT=2500 COMPORT=COM10 etc...ErrorMessage{ex.Message}");
				return;
			}
		}
		if (!dictionary.TryGetValue("IPADDRESS", out value3))
		{
			Console.WriteLine("\nMissing QPST server ipaddress, using default IPADDRESS=localhost");
			value3 = "localhost";
		}
		string value8 = "";
		if (!dictionary.TryGetValue("PORT", out value8))
		{
			Console.WriteLine("\nMissing QPST server port number, using default PORT=2500");
			result = 2500;
		}
		else if (!int.TryParse(value8, out result))
		{
			Console.WriteLine(string.Format("Port number {0} is not valid"));
			return;
		}
		if (!dictionary.TryGetValue("I2CSLAVEADDRESS", out var value9))
		{
			Console.WriteLine("\nMissing I2CSlaveAddress option, using default I2CSLAVEADDRESS=2C");
			value9 = "2C";
		}
		try
		{
			b = Convert.ToByte(value9, 16);
		}
		catch (Exception)
		{
			Console.WriteLine("\n\nInvalid value for i2cSlaveAddress argument\n");
			return;
		}
		if (!dictionary.TryGetValue("COMPORT", out value))
		{
			Console.WriteLine("\nMissing ComPort option");
			return;
		}
		if (!dictionary.TryGetValue("BAUDRATE", out value2))
		{
			Console.WriteLine("\nMissing baudrate option, using default BAUDRATE=57600");
			value2 = "57600";
		}
		if (!dictionary.TryGetValue("PATCH", out value4))
		{
			Console.WriteLine("\nMissing patch FW details, will not download patch");
			flag = false;
		}
		else
		{
			flag = true;
		}
		if (!dictionary.TryGetValue("TCLFILE", out value5) || !dictionary.TryGetValue("TCLDIR", out value6) || !dictionary.TryGetValue("TCLINSTALLPATH", out value7))
		{
			Console.WriteLine("\nMissing options for TCL script filename (TCLFILE), directory (TCLDIR), and/or install path (TCLINSTALLPATH). Will not run startup tcl script.");
			flag2 = false;
		}
		else
		{
			flag2 = true;
		}
		string value10 = "";
		if (!dictionary.TryGetValue("DECODENCI", out value10))
		{
			Console.WriteLine("\nMissing DecodeNci option, using default DECODENCI=false");
			decodeNciCmdPkt = false;
		}
		else
		{
			decodeNciCmdPkt = value10 == "1" || value10 == "TRUE";
		}
		diagBridgeHandle = new NFC_DIAG_Bridge();
		try
		{
			Console.WriteLine("\r\nConnecting.....");
			LingerOption lingerState = new LingerOption(enable: true, 5);
			clientConnectionHandle.Client.LingerState = lingerState;
			try
			{
				clientConnectionHandle.Connect(value3, result);
			}
			catch (Exception ex3)
			{
				diagBridgeHandle.LogException(ex3);
				Console.WriteLine("\n\nFailed to connect to QPST, please make sure QPST is open and configured with above listed IP address and port number\n");
				return;
			}
			byte[] array2 = new byte[274];
			do
			{
				Console.Write("Waiting for QPST connection... ");
				diagBridgeHandle.StartBuilder_Nfc(value7);
				if (flag2 && !diagBridgeHandle.RunScript(value5, value6))
				{
					Console.WriteLine("\nFailed to run startup tcl script");
					return;
				}
				if (!diagBridgeHandle.CompleteStartUp_Nfc(b, value, value2))
				{
					Console.WriteLine("\nFailed to connect to external device on : " + value.ToString() + "\n");
					return;
				}
				Console.WriteLine("Connected to SoC DUT!");
				Thread.Sleep(5000);
				try
				{
					if (flag)
					{
						diagBridgeHandle.DownloadFWPatch_Nfc(value4);
					}
				}
				catch (Exception ex4)
				{
					Console.WriteLine($"\nFailed to download FW patch, error message:{ex4.Message}");
					return;
				}
				ntwStream = clientConnectionHandle.GetStream();
				while (ntwStream.Read(array2, 0, array2.Length) != 0)
				{
					processDiagPacket_Nfc(array2);
				}
			}
			while ((!clientConnectionHandle.Client.Poll(1000, SelectMode.SelectRead) || clientConnectionHandle.Client.Available != 0) && clientConnectionHandle.Client.Connected);
			Console.WriteLine("\n>>>QPST/Server is closed, closing application");
			CleanupBeforeShutdown_Nfc(clientConnectionHandle);
		}
		catch (Exception ex5)
		{
			diagBridgeHandle.LogException(ex5);
		}
	}

	private void InitializeScripters(string tclInstallPath, string firmwarePatchDirectory)
	{
		combinedScripter = new CombinedScripter();
		combinedScripter.AddScripter(fmBuilder.Scripter);
		combinedScripter.AddScripter(nfcBuilder.Scripter);
		if (!firmwarePatchDirectory.EndsWith("\\"))
		{
			firmwarePatchDirectory += "\\";
		}
		combinedScripter.Initialize(tclInstallPath, "set env(NFC_PATCH_PATH) " + firmwarePatchDirectory.Replace("\\", "\\\\"));
		ScripterBase.RegisterLogMessageObserver(logMessageObserver);
	}

	public bool RunScript(string filename, string workingDirectory)
	{
		string currentDirectory = Directory.GetCurrentDirectory();
		try
		{
			Directory.SetCurrentDirectory(workingDirectory);
			logMessageObserver.ResetErrorCount();
			if (!combinedScripter.RunScriptSync(filename))
			{
				Console.WriteLine("Error running tcl script:");
				Console.WriteLine(combinedScripter.GetErrorInfo());
				return false;
			}
			if (logMessageObserver.GetErrorCount() != 0)
			{
				Console.WriteLine("Got error log message when running the tcl script");
				return false;
			}
		}
		catch (Exception value)
		{
			Console.WriteLine(value);
			return false;
		}
		finally
		{
			Directory.SetCurrentDirectory(currentDirectory);
		}
		return true;
	}

	public bool CompleteStartUp_Nfc(byte i2cSlaveAddress, string portName, string baudRateString)
	{
		bool result = OpenConnection_Nfc(i2cSlaveAddress, portName, int.Parse(baudRateString));
		startupBuilderDone = true;
		return result;
	}

	public void SendAndWaitForResponse_Nfc(PacketBase packet)
	{
		if (nfcAPI != null)
		{
			nfcAPI.SendAndWaitForExpectedResponses(packet, 2000);
		}
	}

	public void DownloadFWPatch_Nfc(string Filename)
	{
		if (nfcAPI != null)
		{
			nfcAPI.PatchFirmware(Filename);
		}
	}

	public void Send_Nfc(byte[] packetData)
	{
		if (nfcAPI != null)
		{
			Console.WriteLine("NCI Command Data Out (to DUT): " + Conversions.ByteArrayTo0xHexString(packetData) + "\r\n");
			nfcAPI.Send(packetData, decodeNciCmdPkt);
		}
	}

	public void MultiI2cWrite_Nfc(byte slaveAddress, byte numRegWrites, byte[] address, byte[] value)
	{
		byte b = 0;
		try
		{
			if (nfcAPI != null)
			{
				nfcAPI.SetI2CSlaveAddress(slaveAddress);
				byte[] array = new byte[1];
				for (int i = 0; i < numRegWrites; i++)
				{
					array[0] = value[i];
					nfcAPI.I2CWrite(address[i], array);
				}
			}
		}
		catch
		{
			b = byte.MaxValue;
		}
		finally
		{
			byte[] array2 = new byte[9] { 75, 11, 55, 0, 0, 0, 1, 0, b };
			DiagPrintToStream(array2, check: true);
			Console.WriteLine("I2C Write FTM response packet: " + Conversions.ByteArrayTo0xHexString(array2) + "\r\n");
		}
	}

	public void MultiI2cRead_Nfc(byte slaveAddress, byte numRegReads, byte[] address)
	{
		byte b = 0;
		byte[] array = new byte[numRegReads];
		try
		{
			if (nfcAPI != null)
			{
				nfcAPI.SetI2CSlaveAddress(slaveAddress);
				for (int i = 0; i < numRegReads; i++)
				{
					array[i] = nfcAPI.I2CReadByte(address[i]);
				}
			}
		}
		catch
		{
			b = byte.MaxValue;
		}
		finally
		{
			byte[] array2 = new byte[10 + 2 * numRegReads];
			array2[0] = 75;
			array2[1] = 11;
			array2[2] = 55;
			array2[3] = 0;
			array2[4] = 1;
			array2[5] = 0;
			array2[6] = (byte)(2 + 2 * numRegReads);
			array2[7] = 0;
			array2[8] = b;
			array2[9] = numRegReads;
			for (int j = 0; j < numRegReads; j++)
			{
				array2[10 + 2 * j] = address[j];
				array2[11 + 2 * j] = array[j];
			}
			DiagPrintToStream(array2, check: true);
			Console.WriteLine("I2C Read FTM response packet: " + Conversions.ByteArrayTo0xHexString(array2) + "\r\n");
		}
	}

	public void SendDataAck()
	{
		try
		{
			byte[] array = new byte[8] { 75, 11, 55, 0, 3, 0, 0, 0 };
			Console.WriteLine("FTM Diag Response (to QPST): " + Conversions.ByteArrayTo0xHexString(array) + "\r\n");
			DiagPrintToStream(array, check: true);
		}
		catch (Exception ex)
		{
			LogException(ex);
		}
	}

	public void CompleteShutdown_Nfc()
	{
		if (startupBuilderDone)
		{
			CloseConnection_Nfc();
			Shutdown_Nfc();
			startupBuilderDone = false;
		}
	}

	private bool OpenConnection_Nfc(byte i2cSlaveAddress, string portName, int baudRate)
	{
		try
		{
			nfcAPI.OpenConnection(i2cSlaveAddress, portName, baudRate);
		}
		catch (Exception ex)
		{
			LogException(ex);
			return false;
		}
		return true;
	}

	private void LogException(Exception ex)
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine("Caught exception.");
		stringBuilder.AppendLine("Source: " + ex.Source);
		stringBuilder.AppendLine("Message: " + ex.Message);
		Console.WriteLine("Error  " + stringBuilder.ToString());
	}

	private void StartBuilder_Nfc(string tclInstallPath)
	{
		if (!startupBuilderDone)
		{
			fmBuilder = new FMBuilder();
			nfcBuilder = new NFCBuilder();
			fmBuilder.BuildTSL(PacketReceiveMode.Synchronous);
			nfcBuilder.BuildTSL(PacketReceiveMode.Synchronous);
			InitializeAPIs_Nfc();
			string firmwarePatchDirectory = "";
			InitializeScripters(tclInstallPath, firmwarePatchDirectory);
			startupBuilderDone = true;
		}
	}

	private void InitializeAPIs_Nfc()
	{
		fmAPI = (FMAPI)fmBuilder.API;
		nfcAPI = (NFCAPI)nfcBuilder.API;
		fmAPI.Startup();
		nfcAPI.Startup();
		fmAPI.RegisterSendDataObserver(rawBytesObserver);
		nfcAPI.RegisterSendDataObserver(rawBytesObserver);
		fmAPI.RegisterReceiveDataObserver(rawBytesObserver);
		nfcAPI.RegisterReceiveDataObserver(rawBytesObserver);
		fmAPI.RegisterSendPacketObserver(packetObserver);
		nfcAPI.RegisterSendPacketObserver(packetObserver);
		fmAPI.RegisterReceivePacketObserver(packetObserver);
		nfcAPI.RegisterReceivePacketObserver(packetObserver);
	}

	private void Shutdown_Nfc()
	{
		if (startupBuilderDone)
		{
			nfcAPI.Shutdown();
			nfcAPI.UnregisterSendDataObserver(rawBytesObserver);
			nfcAPI.UnregisterReceiveDataObserver(rawBytesObserver);
			nfcAPI.UnregisterSendPacketObserver(packetObserver);
			nfcAPI.UnregisterReceivePacketObserver(packetObserver);
			startupBuilderDone = false;
		}
	}

	private bool CloseConnection_Nfc()
	{
		try
		{
			if (nfcAPI != null)
			{
				nfcAPI.CloseConnection();
				Console.WriteLine(">>>DUT resources released");
			}
		}
		catch (Exception ex)
		{
			LogException(ex);
			return false;
		}
		return true;
	}
}
