using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Ports;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using QCRPG.Framework;
using QCRPG.TSL.BT;
using QCRPG.TSL.BT.Packets;

namespace QC.BT_DIAG_BRIDGE;

internal class BT_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)
		{
			int num = 240;
			if (packetData.type == PacketDataType.Data)
			{
				switch (connectionTypeOptions)
				{
				}
				Console.WriteLine("Data In(from DUT): " + Conversions.ByteArrayTo0xHexString(packetData.bytes) + "\r\n");
				if (packetData.bytes.Length == 1 && (packetData.bytes[0] == 253 || packetData.bytes[0] == 252 || packetData.bytes[0] == 254))
				{
					return;
				}
				byte[] array = null;
				array = ((connectionTypeOptions == ConnectionType.USB) ? ((packetData.bytes.Length <= num) ? new byte[15 + packetData.bytes.Length + 1] : new byte[15 + num + 1]) : ((packetData.bytes.Length <= num) ? new byte[15 + packetData.bytes.Length] : new byte[15 + num]));
				byte[] array2 = new byte[18]
				{
					16, 0, 21, 0, 21, 0, 124, 17, 0, 0,
					199, 229, 98, 42, 197, 255, 1, 0
				};
				byte[] array3 = new byte[15]
				{
					16, 0, 18, 0, 18, 0, 102, 19, 229, 98,
					42, 197, 255, 1, 0
				};
				for (int i = 0; i < 15; i++)
				{
					array[i] = array3[i];
				}
				if (connectionTypeOptions == ConnectionType.USB)
				{
					array[15] = 4;
				}
				if (connectionTypeOptions == ConnectionType.USB)
				{
					if (packetData.bytes.Length > num)
					{
						for (int i = 0; i < num; i++)
						{
							array[16 + i] = packetData.bytes[i];
						}
					}
					else
					{
						for (int i = 0; i < packetData.bytes.Length; i++)
						{
							array[16 + i] = packetData.bytes[i];
						}
					}
				}
				else if (packetData.bytes.Length > num)
				{
					for (int i = 0; i < num; i++)
					{
						array[15 + i] = packetData.bytes[i];
					}
				}
				else
				{
					for (int i = 0; i < packetData.bytes.Length; i++)
					{
						array[15 + i] = packetData.bytes[i];
					}
				}
				int num2 = array.Length - 4;
				array[2] = (byte)num2;
				array[4] = (byte)num2;
				DiagPrintToStream(array);
			}
			else if (packetData.type == PacketDataType.WarningMessage)
			{
				Console.WriteLine("Warning: " + Conversions.ByteArrayToString(packetData.bytes));
			}
		}

		public void NotifyObserver(OutgoingPacketData packetData)
		{
			if (packetData.type == PacketDataType.Data)
			{
				Console.WriteLine("Data Out(to DUT): " + Conversions.ByteArrayTo0xHexString(packetData.bytes) + "\r\n");
			}
			else if (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 = 0;

		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 BT_DIAG_Bridge diagBridgeHandle = new BT_DIAG_Bridge();

	private static BTBuilder btBuilder;

	private static BTAPI btAPI;

	private PacketDataObserver rawBytesObserver = new PacketDataObserver();

	private PacketObserver packetObserver = new PacketObserver();

	private LogMessageObserver logMessageObserver = new LogMessageObserver();

	private static ConnectionType connectionTypeOptions = ConnectionType.SERIAL;

	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, 66, 84, 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, 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[29]
	{
		124, 2, 0, 0, 232, 3, 0, 0, 16, 39,
		0, 0, 49, 0, 66, 84, 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 = true)
	{
		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 i = 0; i < array.Length; i++)
		{
			array2[i] = array[i];
		}
		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(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);
			}
			else if (inputDIAGMsg[4] == 3)
			{
				DiagPrintToStream(logMaskResponseFirstMsg);
			}
			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:
			Console.WriteLine("echo for status\n");
			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");
			DiagPrintToStream(inputDIAGMsg);
			if (inputDIAGMsg[10] == 1 && inputDIAGMsg[1] == 11 && inputDIAGMsg[2] == 4 && inputDIAGMsg[3] == 0)
			{
				int num2 = inputDIAGMsg[6];
				byte[] array = new byte[num2];
				int num3 = 0;
				for (int j = 10; j < 10 + num2 && j < inputDIAGMsg.Length; j++)
				{
					if (inputDIAGMsg[j] == 125 && j + 1 < inputDIAGMsg.Length && inputDIAGMsg[j + 1] == 94)
					{
						array[num3] = 126;
						j++;
						num2++;
					}
					else if (inputDIAGMsg[j] == 125 && j + 1 < inputDIAGMsg.Length && inputDIAGMsg[j + 1] == 93)
					{
						array[num3] = 125;
						j++;
						num2++;
					}
					else
					{
						array[num3] = inputDIAGMsg[j];
					}
					num3++;
				}
				diagBridgeHandle.Send(array);
			}
			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(TcpClient clientConnectionHandle)
	{
		diagBridgeHandle.CompleteShutdown();
		DisconnectFromQPST(clientConnectionHandle);
	}

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

	public static void Main(string[] args)
	{
		bool flag = true;
		string message;
		if (args.Length == 0)
		{
			message = "Input arguments cannot be empty";
			MessageBoxes.ShowErrorBox(message);
			return;
		}
		if (args.Length == 1 && args[0].ToUpper().Contains("UDT"))
		{
			flag = false;
		}
		string value2;
		Handshake handShake;
		bool ignorePatchResponse;
		string value4;
		Dictionary<string, string> dictionary;
		string[] array;
		string value5;
		string value7;
		ConnectionType connectionType;
		string value;
		string value8;
		string value9;
		bool flag2;
		bool flag3;
		if (flag)
		{
			TcpClient clientConnectionHandle = new TcpClient();
			Console.CancelKeyPress += delegate
			{
				CleanupBeforeShutdown(clientConnectionHandle);
			};
			connectionType = ConnectionType.SERIAL;
			value = "";
			value2 = "115200";
			handShake = Handshake.None;
			string value3 = "localhost";
			int result = 2500;
			ignorePatchResponse = false;
			value4 = "";
			if (args.Length < 2)
			{
				Console.WriteLine("Require at least 2 arguments\nExample: QC.BT.DIAG.BRIDGE.exe IPADDRESS=localhost(optional, default=localhost) PORT=2500(optional, default =2500) IOType=SERIAL ConnectionDetails=COM1 BAUDRATE=115200(optional, default = 115200) HANDSHAKE=NONE(optional, default = NONE) PATCH=C:\\Sample.tlv/img(optional) NVM=C:\\NVM.nvm(optional) \n");
				return;
			}
			dictionary = new Dictionary<string, string>(args.Length);
			array = args;
			foreach (string text in array)
			{
				try
				{
					string[] array2 = text.Split('=');
					dictionary.Add(array2[0].ToUpper(), array2[1].ToUpper());
				}
				catch (Exception ex)
				{
					Console.WriteLine($"Invalid input argument, no spaces are allowed between =. Example: IPADDRESS=localhost PORT=2500 IOTYPE=SERIAL etc...ErrorMessage{ex.Message}");
					return;
				}
			}
			value5 = "";
			if (!dictionary.TryGetValue("SKIPPATCHRESPONSE", out value5))
			{
				Console.WriteLine("\nMissing QPST ignore response, using default SkipPatchResponse=false");
				ignorePatchResponse = false;
			}
			if (value5 == "TRUE")
			{
				ignorePatchResponse = true;
			}
			else if (value5 == "FALSE")
			{
				ignorePatchResponse = false;
			}
			if (!dictionary.TryGetValue("IPADDRESS", out value3))
			{
				Console.WriteLine("\nMissing QPST server ipaddress, using default IPADDRESS=localhost");
				value3 = "localhost";
			}
			string value6 = "";
			if (!dictionary.TryGetValue("PORT", out value6))
			{
				Console.WriteLine("\nMissing QPST server port number, using default port number 2500");
				result = 2500;
			}
			else if (!int.TryParse(value6, out result))
			{
				Console.WriteLine(string.Format("Port number {0} is not valid"));
				return;
			}
			value7 = "SERIAL";
			if (!dictionary.TryGetValue("IOTYPE", out value7))
			{
				Console.WriteLine("\nMissing IOType option, valid options are SERIAL, USB");
				return;
			}
			if (value7 == "SERIAL")
			{
				connectionType = ConnectionType.SERIAL;
			}
			else
			{
				if (!(value7 == "USB"))
				{
					Console.WriteLine("Invalid entry, valid options are : SERIAL or USB");
					return;
				}
				connectionType = ConnectionType.USB;
			}
			if (!dictionary.TryGetValue("CONNECTIONDETAILS", out value))
			{
				Console.WriteLine("\nMissing ConnectionDetails option");
				return;
			}
			value8 = "";
			value9 = "";
			flag2 = false;
			flag3 = false;
			switch (connectionType)
			{
			case ConnectionType.SERIAL:
			{
				if (!dictionary.TryGetValue("BAUDRATE", out value2))
				{
					Console.WriteLine("\nMissing baudrate option, using default 115200");
					value2 = "115200";
				}
				if (!dictionary.TryGetValue("SLEEPMODE", out value4))
				{
					Console.WriteLine("\nMissing sleep Mode option, using default None (0)");
					value4 = "0";
				}
				string value10 = "NONE";
				if (!dictionary.TryGetValue("HANDSHAKEMODE", out value10))
				{
					Console.WriteLine("\nMissing handshake mode option, using NONE as default");
					handShake = Handshake.None;
				}
				else
				{
					switch (value10)
					{
					case "NONE":
						handShake = Handshake.None;
						break;
					case "REQUESTTOSEND":
						handShake = Handshake.RequestToSend;
						break;
					case "REQUESTTOSENDXONXOFF":
						handShake = Handshake.RequestToSendXOnXOff;
						break;
					case "XONXOFF":
						handShake = Handshake.XOnXOff;
						break;
					default:
						Console.WriteLine("Invalid handshake option, valid options are NONE, XONXOFF, RequestToSend, RequestToSendXONXOFF");
						return;
					}
				}
				if (!dictionary.TryGetValue("PATCH", out value8))
				{
					Console.WriteLine("\nMissing patch FW details, will not download patch");
					flag2 = false;
				}
				else
				{
					flag2 = true;
				}
				if (!dictionary.TryGetValue("NVM", out value9))
				{
					Console.WriteLine("\nMissing NVM file details, will not download NVM");
					flag3 = false;
				}
				else
				{
					flag3 = true;
				}
				break;
			}
			case ConnectionType.USB:
				if (!dictionary.TryGetValue("NVM", out value9))
				{
					Console.WriteLine("\nMissing NVM file details, will not download NVM");
					flag3 = false;
				}
				else
				{
					flag3 = true;
				}
				break;
			}
			diagBridgeHandle = new BT_DIAG_Bridge();
			try
			{
				Console.WriteLine("Connecting.....");
				LingerOption lingerState = new LingerOption(enable: true, 5);
				clientConnectionHandle.Client.LingerState = lingerState;
				try
				{
					clientConnectionHandle.Connect(value3, result);
				}
				catch (Exception ex)
				{
					diagBridgeHandle.LogException(ex);
					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[] array3 = new byte[512];
				do
				{
					bool flag4 = true;
					Console.Write("Waiting for QPST connection... ");
					if (!diagBridgeHandle.CompleteStartUp(connectionType, value, value2, value4, handShake))
					{
						Console.WriteLine("\nFailed to connect to external device on : " + value.ToString() + "\n");
						return;
					}
					Console.WriteLine("Connected to SoC DUT!");
					try
					{
						if (flag2)
						{
							diagBridgeHandle.DownloadFWPatch(value8, ignorePatchResponse);
						}
					}
					catch (Exception ex)
					{
						Console.WriteLine($"\nFailed to download FW patch, error message:{ex}");
						return;
					}
					try
					{
						if (flag3)
						{
							diagBridgeHandle.DownloadNVM(value9);
						}
					}
					catch (Exception ex)
					{
						Console.WriteLine($"\nFailed to download NVM, error message:{ex.Message}");
						return;
					}
					ntwStream = clientConnectionHandle.GetStream();
					int num;
					while ((num = ntwStream.Read(array3, 0, array3.Length)) != 0)
					{
						processDiagPacket(array3);
						array3 = new byte[512];
					}
				}
				while ((!clientConnectionHandle.Client.Poll(1000, SelectMode.SelectRead) || clientConnectionHandle.Client.Available != 0) && clientConnectionHandle.Client.Connected);
				Console.WriteLine("\n>>>QPST/Server is closed, closing application");
				CleanupBeforeShutdown(clientConnectionHandle);
				return;
			}
			catch (Exception ex)
			{
				diagBridgeHandle.LogException(ex);
				return;
			}
		}
		message = "";
		string[] array4 = args[0].Split(',');
		if (array4.Length < 2)
		{
			message = "Failed to get comma separated options, minimum options required are iotype and connectiondetails";
			MessageBoxes.ShowErrorBox(message);
			Console.WriteLine($"\n{message}");
			message = "";
			return;
		}
		connectionType = ConnectionType.SERIAL;
		value = "";
		value2 = "115200";
		string value11 = "127.0.0.1";
		handShake = Handshake.None;
		ignorePatchResponse = false;
		value4 = "";
		dictionary = new Dictionary<string, string>(args.Length);
		array = array4;
		foreach (string text in array)
		{
			try
			{
				string[] array2 = text.Split('=');
				dictionary.Add(array2[0].ToUpper(), array2[1].ToUpper());
			}
			catch (Exception ex)
			{
				message = $"Invalid input argument, no spaces are allowed between =. Example: IPADDRESS=localhost PORT=2500 IOTYPE=SERIAL etc...ErrorMessage{ex.Message}";
				MessageBoxes.ShowErrorBox(message);
				Console.WriteLine(message);
				message = "";
				return;
			}
		}
		value5 = "";
		if (!dictionary.TryGetValue("SKIPPATCHRESPONSE", out value5))
		{
			Console.WriteLine("\nMissing QPST ignore response, using default SkipPatchResponse=false");
			ignorePatchResponse = false;
		}
		if (value5 == "TRUE")
		{
			ignorePatchResponse = true;
		}
		else if (value5 == "FALSE")
		{
			ignorePatchResponse = false;
		}
		value7 = "";
		if (!dictionary.TryGetValue("IOTYPE", out value7))
		{
			message = "Missing IOType option, valid options are SERIAL, USB";
			MessageBoxes.ShowErrorBox(message);
			Console.WriteLine(message);
			message = "";
			return;
		}
		if (value7 == "SERIAL")
		{
			connectionType = ConnectionType.SERIAL;
		}
		else
		{
			if (!(value7 == "USB"))
			{
				message = "Invalid entry, valid options are : SERIAL or USB";
				MessageBoxes.ShowErrorBox(message);
				Console.WriteLine(message);
				message = "";
				return;
			}
			connectionType = ConnectionType.USB;
		}
		if (!dictionary.TryGetValue("CONNECTIONDETAILS", out value))
		{
			message = "Missing ConnectionDetails option";
			MessageBoxes.ShowErrorBox(message);
			Console.WriteLine(message);
			message = "";
			return;
		}
		if (string.IsNullOrEmpty(value))
		{
			message = "ConnectionDetails cannot be empty";
			MessageBoxes.ShowErrorBox(message);
			Console.WriteLine(message);
			message = "";
			return;
		}
		value = value.ToUpper();
		if (!dictionary.TryGetValue("IPADDRESS", out value11))
		{
			value11 = "127.0.0.1";
		}
		value8 = "";
		value9 = "";
		flag2 = false;
		flag3 = false;
		switch (connectionType)
		{
		case ConnectionType.SERIAL:
		{
			if (!dictionary.TryGetValue("BAUDRATE", out value2))
			{
				Console.WriteLine("\nMissing baudrate option, using default 115200");
				value2 = "115200";
			}
			if (!dictionary.TryGetValue("SLEEPMODE", out value4))
			{
				Console.WriteLine("\nMissing sleep Mode option, using default None (0)");
				value4 = "0";
			}
			string value10 = "NONE";
			if (!dictionary.TryGetValue("HANDSHAKEMODE", out value10))
			{
				Console.WriteLine("\nMissing handshake mode option, using NONE as default");
				handShake = Handshake.None;
			}
			else
			{
				switch (value10)
				{
				case "NONE":
					handShake = Handshake.None;
					break;
				case "REQUESTTOSEND":
					handShake = Handshake.RequestToSend;
					break;
				case "REQUESTTOSENDXONXOFF":
					handShake = Handshake.RequestToSendXOnXOff;
					break;
				case "XONXOFF":
					handShake = Handshake.XOnXOff;
					break;
				default:
					Console.WriteLine("Invalid handshake option, valid options are NONE, XONXOFF, RequestToSend, RequestToSendXONXOFF");
					return;
				}
			}
			if (!dictionary.TryGetValue("PATCH", out value8))
			{
				Console.WriteLine("\nMissing patch FW details, will not download patch");
				flag2 = false;
			}
			else
			{
				flag2 = true;
			}
			if (!dictionary.TryGetValue("NVM", out value9))
			{
				Console.WriteLine("\nMissing NVM file details, will not download NVM");
				flag3 = false;
			}
			else
			{
				flag3 = true;
			}
			break;
		}
		case ConnectionType.USB:
			if (!dictionary.TryGetValue("NVM", out value9))
			{
				Console.WriteLine("\nMissing NVM file details, will not download NVM");
				flag3 = false;
			}
			else
			{
				flag3 = true;
			}
			break;
		}
		diagBridgeHandle = new BT_DIAG_Bridge();
		try
		{
			Console.WriteLine("Connecting.....");
			LingerOption lingerState = new LingerOption(enable: true, 5);
			byte[] array3 = new byte[256];
			Console.Write("Waiting for client connection... ");
			if (!diagBridgeHandle.CompleteStartUp(connectionType, value, value2, value4, handShake))
			{
				message = "\nFailed to connect to external device on : " + value.ToString() + "\n";
				MessageBoxes.ShowErrorBox(message);
				Console.WriteLine(message);
				return;
			}
			Console.WriteLine("Connected to SoC DUT!");
			try
			{
				if (flag2)
				{
					if (!File.Exists(value8))
					{
						message = $"patch file not found on PC at {value8}";
						MessageBoxes.ShowErrorBox(message);
						Console.WriteLine(message);
						message = "";
						return;
					}
					diagBridgeHandle.DownloadFWPatch(value8, ignorePatchResponse);
				}
			}
			catch (Exception ex)
			{
				message = $"Failed to download patch file {ex.Message}";
				MessageBoxes.ShowErrorBox(message);
				Console.WriteLine(message);
				message = "";
				return;
			}
			try
			{
				if (flag3)
				{
					if (!File.Exists(value9))
					{
						message = $"NVM file not found on PC at {value9}";
						MessageBoxes.ShowErrorBox(message);
						Console.WriteLine(message);
						message = "";
						return;
					}
					diagBridgeHandle.DownloadNVM(value9);
				}
			}
			catch (Exception ex)
			{
				message = $"Failed to download NVM file {ex.Message}";
				MessageBoxes.ShowErrorBox(message);
				Console.WriteLine(message);
				message = "";
				return;
			}
			int result2 = 2390;
			string value6 = "";
			if (!dictionary.TryGetValue("PORT", out value6))
			{
				Console.WriteLine("\nMissing QPST server port number, using default port number 2500");
				result2 = 2390;
			}
			else if (!int.TryParse(value6, out result2))
			{
				Console.WriteLine(string.Format("Port number {0} is not valid"));
				return;
			}
			TcpListener tcpListener = null;
			string value3 = value11;
			IPAddress localaddr = IPAddress.Parse(value3);
			tcpListener = new TcpListener(localaddr, result2);
			tcpListener.Start();
			TcpClient tcpClient = tcpListener.AcceptTcpClient();
			Console.WriteLine("Client Connected!");
			byte[] array5 = new byte[512];
			ntwStream = tcpClient.GetStream();
			int num;
			while ((num = ntwStream.Read(array5, 0, array5.Length)) != 0)
			{
				processDiagPacket(array5);
			}
		}
		catch (Exception ex)
		{
			diagBridgeHandle.LogException(ex);
			message = "\nFailed : " + ex.Message;
			MessageBoxes.ShowErrorBox(message);
			Console.WriteLine(message);
			message = "";
		}
	}

	public bool CompleteStartUp(ConnectionType connectionType, string connectionDetails, string baudRateString, string sleepMode, Handshake handShake)
	{
		StartBuilder();
		bool result = OpenConnection(connectionType, connectionDetails, int.Parse(baudRateString), int.Parse(sleepMode), handShake);
		startupBuilderDone = true;
		return result;
	}

	public void HCIReset()
	{
		Reset packet = new Reset();
		SendAndWaitForResponse(packet);
		Thread.Sleep(300);
	}

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

	public void DownloadFWPatch(string Filename, bool ignorePatchResponse)
	{
		if (btAPI == null)
		{
			return;
		}
		if (Path.GetExtension(Filename) == ".IMG")
		{
			btAPI.PatchFirmware(Filename, ignorePatchResponse);
			return;
		}
		if (Path.GetExtension(Filename) == ".TLV")
		{
			btAPI.PatchFirmwareTLV(Filename, ignorePatchResponse);
			return;
		}
		throw new SystemException($"Invalid file extension: {Path.GetExtension(Filename)}, valid types are .img and .tlv");
	}

	public void DownloadNVM(string Filename)
	{
		if (btAPI != null)
		{
			btAPI.WriteNVM(Filename, skipResponseChecks: true);
		}
	}

	public void Send(byte[] packetData)
	{
		byte[] array = null;
		switch (connectionTypeOptions)
		{
		case ConnectionType.SERIAL:
			array = packetData;
			break;
		case ConnectionType.USB:
		{
			array = new byte[packetData.Length - 1];
			for (int i = 0; i < array.Length; i++)
			{
				array[i] = packetData[i + 1];
			}
			break;
		}
		}
		if (btAPI != null)
		{
			btAPI.Send(array);
		}
	}

	public void CompleteShutdown()
	{
		if (startupBuilderDone)
		{
			CloseConnection();
			Shutdown();
			startupBuilderDone = false;
		}
	}

	private bool OpenConnection(ConnectionType connectionType, string connectionDetails, int baudRate, int sleepMode, Handshake handShake)
	{
		connectionTypeOptions = connectionType;
		try
		{
			switch (connectionType)
			{
			case ConnectionType.SERIAL:
				if (sleepMode != 0)
				{
					btAPI.SetSleepMode((ProtocolHCI.SleepModeState)sleepMode);
				}
				btAPI.OpenSerialConnection(connectionDetails, baudRate, handShake);
				break;
			case ConnectionType.USB:
			{
				UsbDeviceInfo usbDeviceInfo = new UsbDeviceInfo(connectionDetails, typeof(ConnectionUsbAtheros));
				btAPI.OpenUsbConnection(usbDeviceInfo);
				break;
			}
			}
		}
		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()
	{
		if (!startupBuilderDone)
		{
			btBuilder = new BTBuilder();
			btBuilder.BuildTSL(PacketReceiveMode.Synchronous, deviceEmulationMode: false, 1, commandLineMode: true);
			InitializeAPIs();
			startupBuilderDone = true;
		}
	}

	private void InitializeAPIs()
	{
		btAPI = (BTAPI)btBuilder.API;
		btAPI.Startup();
		btAPI.RegisterSendDataObserver(rawBytesObserver);
		btAPI.RegisterReceiveDataObserver(rawBytesObserver);
		btAPI.RegisterSendPacketObserver(packetObserver);
		btAPI.RegisterReceivePacketObserver(packetObserver);
	}

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

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