/// <summary>
 /// Helper method for transforming the information in a KWPReply to a string.
 /// </summary>
 /// <param name="a_reply">The KWPReply.</param>
 /// <returns>A string representing the information in the a_reply.</returns>
 private string getString(KWPReply a_reply)
 {
     if (a_reply.getData().Length == 0)
         return "";
     Encoding ascii = Encoding.ASCII;
     ascii.GetChars(a_reply.getData(), 0, a_reply.getData().Length);
     return ascii.GetString(a_reply.getData(), 0, a_reply.getData().Length);
 }
 private UInt16 getUint16(KWPReply a_reply)
 {
     UInt16 uinteger;
     uinteger = (UInt16)((a_reply.getData()[1] << 8) | (a_reply.getData()[0]));
     return uinteger;
 }
        /// <summary>
        /// This method writes to a symbol in RAM.
        /// The ECU must not be write protected for this to work.
        /// </summary>
        /// <param name="a_symbolNumber">Symbol number to write to.</param>
        /// <param name="a_data">Data to write.</param> 
        /// <returns></returns>
        public bool writeSymbolRequestTest(uint a_symbolNumber, byte[] a_data, int idx)
        {
            LogDataString("writeSymbolRequest: " + a_symbolNumber.ToString());

            KWPReply reply = new KWPReply();
            KWPResult result;
            int LengthToTx = a_data.Length;
            if (LengthToTx > 0x41) LengthToTx = 0x41; // FA
            byte[] symbolNumberAndData = new byte[3 + /*a_data.Length*/ LengthToTx];
            //First two bytes should be the symbol number
            symbolNumberAndData[0] = (byte)(a_symbolNumber >> 8);
            symbolNumberAndData[1] = (byte)(a_symbolNumber);
            symbolNumberAndData[2] = (byte)(0);
            // len len
            // adr adr adr

            for (int i = 0; i < /*a_data.Length*/ LengthToTx; i++)
                symbolNumberAndData[i + 3] = a_data[i];

            //string requestString = "RequestString: ";
            //foreach (byte b in symbolNumberAndData)
            //{
            //    requestString += b.ToString("X2") + " ";
            //}
            //Console.WriteLine(requestString);
            // end dump to console
            //Console.WriteLine("SymbolNumberAndData length: " + symbolNumberAndData.Length.ToString("X8"));
            KWPRequest t_request = new KWPRequest(0x3D, 0x80, symbolNumberAndData);
            //Console.WriteLine(t_request.ToString());
            result = sendRequest(t_request, out reply);
            if (result != KWPResult.OK)
            {
                Console.WriteLine("Result != KWPResult.OK");
                return false;
            }
            //Console.WriteLine("Result = " + reply.getData()[0].ToString("X2"));
            if (reply.getData()[0] == 0x7D)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// This method writes to a symbol in RAM.
        /// The ECU must not be write protected for this to work.
        /// </summary>
        /// <param name="a_symbolNumber">Symbol number to write to.</param>
        /// <param name="a_data">Data to write.</param> 
        /// <returns></returns>
        public bool writeSymbolRequestAddress(uint a_address, byte[] a_data)
        {
            LogDataString("writeSymbolRequest: " + a_address.ToString("X8") + "len: " + a_data.Length.ToString("X4"));

            KWPReply reply = new KWPReply();
            KWPResult result;
            byte[] symbolNumberAndData = new byte[4 + a_data.Length];
            //symbolNumberAndData[0] = (byte)(a_address >> 24);
            symbolNumberAndData[0] = (byte)(a_address >> 16);
            symbolNumberAndData[1] = (byte)(a_address >> 8);
            symbolNumberAndData[2] = (byte)(a_address);
            symbolNumberAndData[3] = (byte)(a_data.Length);
            // len len
            // adr adr adr

            for (int i = 0; i < a_data.Length; i++)
                symbolNumberAndData[i + 4] = a_data[i];

            //string requestString = "RequestString: ";
            //foreach (byte b in symbolNumberAndData)
            //{
            //    requestString += b.ToString("X2") + " ";
            //}
            //Console.WriteLine(requestString);
            // end dump to console
            //Console.WriteLine("SymbolNumberAndData length: " + symbolNumberAndData.Length.ToString("X8"));
            KWPRequest t_request = new KWPRequest(0x3D, /*0x81, */symbolNumberAndData);
            //Console.WriteLine(t_request.ToString());
            result = sendRequest(t_request, out reply);
            if (result != KWPResult.OK)
            {
                Console.WriteLine("Result != KWPResult.OK");
                return false;
            }
               // Console.WriteLine("Result = " + reply.getData()[0].ToString("X2"));
            //Console.WriteLine("Result-total = " + reply.ToString());
            if (reply.getData()[0] == 0x7D)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// This method send a request to receive data from flash. The sendReadRequest
        /// method must be called before this.
        /// </summary>
        /// <param name="r_data">The requested data.</param>
        /// <returns></returns>
        public bool sendRequestDataByOffset(out byte[] r_data)
        {
            LogDataString("sendRequestDataByOffset");

            KWPReply reply = new KWPReply();
            KWPResult result;
            result = sendRequest(new KWPRequest(0x21, 0xF0), out reply);
            r_data = reply.getData();
            if (result == KWPResult.OK)
                return true;
            else
                return false;
        }
        /// <summary>
        /// This method requests data to be transmitted.
        /// </summary>
        /// <param name="a_data">The data to be transmitted.</param>
        /// <returns>KWPResult</returns>
        public KWPResult sendDataTransferRequest(out byte[] a_data)
        {
            LogDataString("sendDataTransferRequest");

            KWPReply reply = new KWPReply();
            KWPResult result;

            //Send request
            //Mode = 0x36
            //PID = no PID used by this request
            //Data = no data
            //Expected result = 0x76
            result = sendRequest(new KWPRequest(0x36), out reply);
            a_data = reply.getData();
            if (reply.getMode() != 0x76)
                return KWPResult.NOK;
            else
                return result;
        }
        /// <summary>
        /// Send a request for a sequrity access with one out of two methods to 
        /// calculate the key.
        /// </summary>
        /// <param name="a_method">Key calculation method [1,2]</param>
        /// <returns>true if sequrity access was granted, otherwise false</returns>
        private bool requestSequrityAccessLevel()
        {
            LogDataString("requestSequrityAccessLevel");
            KWPReply reply = new KWPReply();
            KWPResult result;
            byte[] seed = new byte[2];
            byte[] key = new byte[2];
            // Send a seed request.
            KWPRequest requestForKey = new KWPRequest(0x27, 0x05); // TODO: What is this for T8?
            Console.WriteLine("requestSequrityAccessLevel request for key: " + requestForKey.ToString());
            result = sendRequest(requestForKey, out reply);
            Console.WriteLine("requestSequrityAccessLevel request for key result: " + reply.ToString());

            if (result != KWPResult.OK)
                return false;
            if (reply.getData().Length < 2)
                return false;
            seed[0] = reply.getData()[0];
            seed[1] = reply.getData()[1];
            key = calculateKey(seed);
            // Send key reply.
            KWPRequest sendKeyRequest = new KWPRequest(0x27, 0x06, key);
            Console.WriteLine("requestSequrityAccessLevel send Key request: " + sendKeyRequest.ToString());
            result = sendRequest(sendKeyRequest, out reply);
            Console.WriteLine("requestSequrityAccessLevel send Key reply: " + reply.ToString());
            if (result != KWPResult.OK)
            {
                Console.WriteLine("Security access request was not send");
                return false;
            }

            //Check if sequrity was granted.
            Console.WriteLine("Mode: " + reply.getMode().ToString("X2"));
            Console.WriteLine("Data: " + reply.getData()[0].ToString("X2"));
            if ((reply.getMode() == 0x67) && (reply.getData()[0] == 0x34)) // WAS [0]
            {
                Console.WriteLine("Security access granted");
                return true;
            }

            Console.WriteLine("Security access was not granted: " + reply.ToString());
            return false;
        }