/// <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)); }
/// <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(); }
/// <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()); }
/// <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()); }
/// <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(); }
/// <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); }
/// <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); }
/// <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); }
public IAsyncResult BeginSend(SsmPacket packet, AsyncCallback callback, object state) { this.stream.BeginWrite( packet.Data, 0, packet.Data.Length, callback, internalState); return(internalState); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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(); } }
/// <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); }
/// <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()); }
/// <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); }
public IAsyncResult BeginSend(SsmPacket packet, AsyncCallback callback, object state) { }
/// <summary> /// SSM's handshake operation /// </summary> /// <param name="buffer"></param> private void Handshake() { SsmPacket packet = SsmPacket.CreateEcuIdentifierResponse(); this.SetResponse(packet.Data); }