示例#1
0
        /// <summary>
        /// Synchronously read a complete packet from a possibly-fragmented stream
        /// </summary>
        /// <remarks>
        /// Not very useful in production, but it made development and testing easier
        /// </remarks>
        public static SsmPacket ReadFromStream(Stream stream)
        {
            SsmPacketParser parser = new SsmPacketParser();

            while (!parser.IsComplete)
            {
                if (parser.bytesReceived != 0)
                {
                    System.Threading.Thread.Sleep(1);
                }

                int bufferLength = stream.Read(parser.buffer, parser.bytesReceived, parser.buffer.Length - parser.bytesReceived);
                if (bufferLength == 0)
                {
                    throw new SsmPacketFormatException("Unexpected end of stream.");
                }

                for (int i = 0; i < bufferLength; i++)
                {
                    int index = parser.bytesReceived + i;
                    parser.CheckByte(index, parser.buffer[index]);
                }
                parser.bytesReceived += bufferLength;
            }

            return(SsmPacket.ParseResponse(parser.buffer, 0, parser.bytesReceived));
        }
示例#2
0
        /// <summary>
        /// Invoked after the ECU identifier response has been received
        /// </summary>
        private void EcuIdentifierResponseRead(IAsyncResult asyncResult)
        {
            Trace.WriteLine("SsmInterface.EcuIdentifierResponseRead");
            GetEcuIdentifierAsyncResult internalState = (GetEcuIdentifierAsyncResult)asyncResult.AsyncState;

            try
            {
                SsmPacket response = internalState.Parser.EndReadFromStream(asyncResult);
                this.ecuIdentifier    = response.EcuIdentifier;
                this.compatibilityMap = response.CompatibilityMap;
            }
            catch (IOException ex)
            {
                internalState.Exception = ex;
            }
            catch (SecurityException ex)
            {
                internalState.Exception = ex;
            }

            Exception localException = internalState.Exception;

            if (localException == null)
            {
                Trace.WriteLine("SsmInterface.EcuIdentifierResponseRead: " + this.ecuIdentifier);
            }
            else
            {
                Trace.WriteLine("SsmInterface.EcuIdentifierResponseRead: " + localException.ToString());
            }
            internalState.Completed();
        }
示例#3
0
        /// <summary>
        /// Synchronously issues a block read request and waits for the response
        /// </summary>
        public byte[] SyncReadBlock(int address, int length)
        {
            SsmPacket request  = SsmPacket.CreateBlockReadRequest(address, length);
            SsmPacket response = this.SyncSendReceive(request);

            return(((List <byte>)response.Values).ToArray());
        }
示例#4
0
        /// <summary>
        /// Synchronously issues a read request and waits for the response
        /// </summary>
        public byte[] SyncReadMultiple(IList <int> addresses)
        {
            SsmPacket request  = SsmPacket.CreateMultipleReadRequest(addresses);
            SsmPacket response = this.SyncSendReceive(request);

            return(((List <byte>)response.Values).ToArray());
        }
示例#5
0
        /// <summary>
        /// Invoked after the read response has been received from the ECU
        /// </summary>
        private void BlockReadResponseReceived(IAsyncResult asyncResult)
        {
            BlockReadAsyncResult internalState = (BlockReadAsyncResult)asyncResult.AsyncState;

            try
            {
                SsmPacket response = internalState.Parser.EndReadFromStream(asyncResult);

                // Uncomment for easier debugging:
                //byte[] data = response.Data;
                //SsmCommand command = response.Command;
                //int payloadLength = response.PayloadLength;
                //IList<byte> values = response.Values;

                foreach (byte value in response.Values)
                {
                    internalState.ValueList.Add(value);
                }
            }
            catch (IOException ex)
            {
                internalState.Exception = ex;
            }
            catch (SecurityException ex)
            {
                internalState.Exception = ex;
            }
            internalState.Completed();
        }
示例#6
0
        /// <summary>
        /// Parse a response packet (which begins with an echo of the request
        /// that elicited the response) from the given (subset of a) byte array.
        /// </summary>
        public static SsmPacket ParseResponse(byte[] data, int offset, int length)
        {
            SsmPacket request       = new SsmPacket(data, offset, length);
            int       requestLength = SsmPacket.HeaderLength + request.PayloadLength;
            SsmPacket response      = new SsmPacket(data, offset + requestLength, length - requestLength);

            return(response);
        }
示例#7
0
        /// <summary>
        /// Create an ECU identifier request packet
        /// </summary>
        public static SsmPacket CreateEcuIdentifierRequest()
        {
            SsmPacket packet = new SsmPacket();

            packet.SetHeader(SsmDirection.ToEcu, SsmCommand.EcuInitRequest);
            packet.SetLengthByte();
            packet.AppendChecksum();
            return(packet);
        }
示例#8
0
        /// <summary>
        /// Create a block-read response packet
        /// </summary>
        public static SsmPacket CreateBlockReadResponse(byte[] payload)
        {
            SsmPacket packet = new SsmPacket();

            packet.SetHeader(SsmDirection.FromEcu, SsmCommand.ReadBlockResponse);
            packet.AppendPayload(payload);
            packet.SetLengthByte();
            packet.AppendChecksum();
            return(packet);
        }
示例#9
0
 public IAsyncResult BeginSend(SsmPacket packet, AsyncCallback callback, object state)
 {
     this.stream.BeginWrite(
         packet.Data,
         0,
         packet.Data.Length,
         callback,
         internalState);
     return(internalState);
 }
示例#10
0
        /// <summary>
        /// Create a multiple-address-read response packet
        /// </summary>
        public static SsmPacket CreateMultipleReadResponse(IList <byte> values)
        {
            SsmPacket packet = new SsmPacket();

            packet.SetHeader(SsmDirection.FromEcu, SsmCommand.ReadAddressesResponse);
            for (int i = 0; i < values.Count; i++)
            {
                packet.AppendByte(values[i]);
            }
            packet.SetLengthByte();
            packet.AppendChecksum();
            return(packet);
        }
示例#11
0
        /// <summary>
        /// Create an ECU request packet with an arbitrary command and payload.
        /// </summary>
        /// <remarks>
        /// For experimentation...
        /// </remarks>
        /// <param name="direction">Which direction the packet will be traveling.</param>
        /// <param name="command">Command byte.</param>
        /// <param name="payload">Payload.</param>
        /// <returns>SsmPacket built from the given parameters.</returns>
        public static SsmPacket CreateArbitrary(
            SsmDirection direction,
            SsmCommand command,
            byte[] payload)
        {
            SsmPacket packet = new SsmPacket();

            packet.SetHeader(direction, command);
            packet.AppendPayload(payload);
            packet.SetLengthByte();
            packet.AppendChecksum();
            return(packet);
        }
示例#12
0
        /// <summary>
        /// Create a multiple-address-read request packet
        /// </summary>
        public static SsmPacket CreateMultipleReadRequest(IList <int> addresses)
        {
            SsmPacket packet = new SsmPacket();

            packet.SetHeader(SsmDirection.ToEcu, SsmCommand.ReadAddressesRequest);
            for (int i = 0; i < addresses.Count; i++)
            {
                packet.AppendAddress(addresses[i]);
            }
            packet.SetLengthByte();
            packet.AppendChecksum();
            return(packet);
        }
示例#13
0
        /// <summary>
        /// Create a request packet for an arbitrary device with an arbitrary command and payload.
        /// </summary>
        /// <remarks>
        /// For experimentation...
        /// </remarks>
        /// <param name="device">Which device the packet will to go.</param>
        /// <param name="command">Command byte.</param>
        /// <param name="pad">If true, an extra byte will be added to the header.</param>
        /// <param name="payload">Payload.</param>
        /// <returns>SsmPacket built from the given parameters.</returns>
        public static SsmPacket CreateArbitrary(
            byte device,
            byte command,
            bool pad,
            byte[] payload)
        {
            SsmPacket packet = new SsmPacket();

            packet.SetHeader(device, command, pad);
            packet.AppendPayload(payload);
            packet.SetLengthByte();
            packet.AppendChecksum();
            return(packet);
        }
示例#14
0
        /// <summary>
        /// SSM's read-multiple-addresses operation
        /// </summary>
        /// <param name="addresses"></param>
        private void ReadAddresses(IList <int> addresses)
        {
            byte[] payload = new byte[addresses.Count];

            for (int i = 0; i < addresses.Count; i++)
            {
                int address = addresses[i];
                payload[i] = this.GetValue(address);
            }

            SsmPacket responsePacket = SsmPacket.CreateMultipleReadResponse(payload);

            this.SetResponse(responsePacket.Data);
        }
示例#15
0
        /// <summary>
        /// Read a block of RAM from the ECU
        /// </summary>
        public IAsyncResult BeginBlockRead(int address, int length, AsyncCallback callback, object state)
        {
            this.BeginOperation();

            BlockReadAsyncResult internalState = new BlockReadAsyncResult(callback, state);
            SsmPacket            request       = SsmPacket.CreateBlockReadRequest(address, length);

            this.stream.BeginWrite(
                request.Data,
                0,
                request.Data.Length,
                this.BlockReadRequestWritten,
                internalState);
            return(internalState);
        }
示例#16
0
        /// <summary>
        /// Begins reading multiple disjoint addesses from the ECU
        /// </summary>
        public IAsyncResult BeginMultipleRead(IList <int> addresses, AsyncCallback callback, object state)
        {
            this.BeginOperation();

            MultipleReadAsyncResult internalState = new MultipleReadAsyncResult(callback, state);
            SsmPacket request = SsmPacket.CreateMultipleReadRequest(addresses);

            this.stream.BeginWrite(
                request.Data,
                0,
                request.Data.Length,
                this.MultipleReadRequestWritten,
                internalState);
            return(internalState);
        }
示例#17
0
        /// <summary>
        /// SSM's read-block operation
        /// </summary>
        private void ReadBlock(int blockStart, byte blockLength)
        {
            byte[] payload = new byte[blockLength];

            for (int offset = 0; offset < blockLength; offset++)
            {
                int  address = blockStart + offset;
                byte value   = this.GetValue(address);
                payload[offset] = value;
            }

            SsmPacket responsePacket = SsmPacket.CreateBlockReadResponse(payload);

            this.SetResponse(responsePacket.Data);
        }
示例#18
0
        /// <summary>
        /// Create a block-read request packet
        /// </summary>
        public static SsmPacket CreateBlockReadRequest(int address, int length)
        {
            if (length == int.MinValue)
            {
                throw new ArgumentOutOfRangeException("length");
            }

            SsmPacket packet = new SsmPacket();

            packet.SetHeader(SsmDirection.ToEcu, SsmCommand.ReadBlockRequest);
            packet.AppendAddress(address);
            packet.AppendByte((byte)(length - 1));
            packet.SetLengthByte();
            packet.AppendChecksum();
            return(packet);
        }
示例#19
0
        /// <summary>
        /// Create an ECU identifier response packet
        /// </summary>
        public static SsmPacket CreateEcuIdentifierResponse()
        {
            SsmPacket packet = new SsmPacket();

            packet.SetHeader(SsmDirection.FromEcu, SsmCommand.EcuInitResponse);

            // Remove header and checksum from sample packet data
            List <byte> payload = new List <byte>(SamplePacketData.EcuInitResponse);

            payload.RemoveRange(0, 5);
            payload.RemoveRange(payload.Count - 1, 1);

            packet.AppendPayload(payload.ToArray());
            packet.SetLengthByte();
            packet.AppendChecksum();
            return(packet);
        }
示例#20
0
        /// <summary>
        /// Sends an ECU identifier request
        /// </summary>
        public IAsyncResult BeginGetEcuIdentifier(AsyncCallback callback, object state)
        {
            Trace.WriteLine("SsmInterface.BeginGetEcuIdentifier");
            this.BeginOperation();

            GetEcuIdentifierAsyncResult internalState = new GetEcuIdentifierAsyncResult(
                callback,
                state);
            SsmPacket request = SsmPacket.CreateEcuIdentifierRequest();

            this.stream.BeginWrite(
                request.Data,
                0,
                request.Data.Length,
                this.EcuIdentifierRequestWritten,
                internalState);
            return(internalState);
        }
示例#21
0
        /// <summary>
        /// Returns the new packet to the caller
        /// </summary>
        public SsmPacket EndReadFromStream(IAsyncResult asyncResult)
        {
            ReadFromStreamAsyncResult internalState = (ReadFromStreamAsyncResult)asyncResult;

            try
            {
                if (internalState.Exception != null)
                {
                    throw internalState.Exception;
                }

                return(SsmPacket.ParseResponse(this.buffer, 0, this.bytesReceived));
            }
            finally
            {
                internalState.Dispose();
            }
        }
示例#22
0
        /// <summary>
        /// Synchronously sends a request and waits for the response
        /// </summary>
        public SsmPacket SyncSendReceive(SsmPacket request)
        {
            //Console.WriteLine("#### Raw request data:");
            byte[] requestBuffer = request.Data;
            SsmUtility.DumpBuffer(requestBuffer);

            stream.Write(requestBuffer, 0, requestBuffer.Length);
            Thread.Sleep(250);

            byte[] responseBuffer = new byte[2000];
            int    bytesRead      = stream.Read(responseBuffer, 0, responseBuffer.Length);

            Console.WriteLine("Bytes read: {0}", bytesRead);
            Console.WriteLine("#### Raw response data:");
            SsmUtility.DumpBuffer(responseBuffer);

            SsmPacket response = SsmPacket.ParseResponse(responseBuffer, 0, bytesRead);

            return(response);
        }
示例#23
0
        /// <summary>
        /// Write a request to the mock ECU
        /// </summary>
        public override void Write(byte[] buffer, int offset, int count)
        {
            if (buffer[0] != 0x80)
            {
                throw new InvalidOperationException("First byte sent to ECU must be 0x80 (command start byte)");
            }

            /*
             * if (buffer[1] != 0x10)
             * {
             *  throw new InvalidOperationException("Second byte sent to ECU must be 0x10 (destination = ECU)");
             * }
             *
             * if (buffer[2] != 0xF0)
             * {
             *  throw new InvalidOperationException("Third byte sent to ECU must be 0xF0 (source = diagnostic tool)");
             * }
             */
            if (MockEcuStream.GetPacketLength(buffer) != buffer.Length - 5)
            {
                throw new InvalidOperationException("Fourth byte sent to ECU must be equal to \"buffer_length - 5\"");
            }

            if (this.corruptNextResponse)
            {
                byte[] data = new byte[100];
                for (int i = 0; i < data.Length; i++)
                {
                    data[i] = (byte)0x55;
                }

                this.SetResponse(data);
                this.corruptNextResponse = false;
                return;
            }

            SsmPacket packet = SsmPacket.ParseRequest(buffer, offset, count);

            switch (packet.Command)
            {
            case SsmCommand.ReadBlockRequest:
                this.ReadBlock(packet.BlockStart, packet.BlockLength);
                break;

            case SsmCommand.ReadAddressesRequest:
                this.ReadAddresses(packet.Addresses);
                break;

            case SsmCommand.WriteBlockRequest:
                //this.WriteBlock(packet.BlockStart, packet.BlockData);
                break;

            case SsmCommand.WriteAddressesRequest:
                //this.WriteAddresses(packet.Addresses, packet.Values);
                break;

            case SsmCommand.EcuInitRequest:
                this.Handshake();
                break;
            }

            List <byte> temporaryBuffer = new List <byte>(packet.Data.Length + this.response.Length);

            temporaryBuffer.AddRange(packet.Data);
            temporaryBuffer.AddRange(this.response);
            this.SetResponse(temporaryBuffer.ToArray());
        }
示例#24
0
        /// <summary>
        /// Parse a request packet from the given (subset of a) byte array
        /// </summary>
        public static SsmPacket ParseRequest(byte[] data, int offset, int length)
        {
            SsmPacket request = new SsmPacket(data, offset, length);

            return(request);
        }
示例#25
0
 public IAsyncResult BeginSend(SsmPacket packet, AsyncCallback callback, object state)
 {
 }
示例#26
0
        /// <summary>
        /// SSM's handshake operation
        /// </summary>
        /// <param name="buffer"></param>
        private void Handshake()
        {
            SsmPacket packet = SsmPacket.CreateEcuIdentifierResponse();

            this.SetResponse(packet.Data);
        }