15 | Antus
16 | -
17 | He and Dimented24x7 created the first free tool for reading and writing (LS1Flash) and he contributed enormously to this one.
18 |
19 |
20 |
21 | Dimented24x7
22 | -
23 | For his work on LS1Flash, for sharing his disassembly of a 411 operating system, and for the first free definition of a 411 operating system's calibration data.
24 |
25 |
26 |
27 | NSFW
28 | -
29 | Tried to write PCM Hammer despite knowing far too little about the hardware side of things... Was rescued by everyone else listed here.
30 |
31 |
32 |
33 | PeteS
34 | -
35 | He speaks J1850 VPW like a native, and tortures PCMs for sadistic pleasure. His troubleshooting and testing has been invaluable.
36 |
37 |
38 |
39 | Tazzi
40 | -
41 | His code made it possible for PCM Hammer to support J2534 devices.
42 |
43 |
44 |
Tazzi and PeteS are also working on custom hardware that should provide high speed reading and writing at a low price - that's the "DVI" that you see in the list of supported interfaces. Keep an eye out for updates.
45 |
46 |
47 | And last but not least, thanks to the whole car-hacking community - to everyone who has looked under their hoods or into their OBD2 messages, and posted about it on the internet. And especially to everyone who has sent us words of encouragement along the way. It's always nice to be reminded that there are plenty more people out there who are just as stoked about this as we are!
48 |
49 |
50 |
51 | Mikebb203
52 | -
53 | Modified PCM Hammer to IPC Hammer. Only possible due to the great work of all the others working on PCM Hammer.
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/IPCLibrary/Logging/MathValueConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Xml.Serialization;
5 |
6 | namespace PcmHacking
7 | {
8 | public class MathValue
9 | {
10 | [XmlAttribute]
11 | public string Name { get; set; }
12 |
13 | [XmlAttribute]
14 | public string Units { get; set; }
15 |
16 | [XmlAttribute]
17 | public string XParameter { get; set; }
18 |
19 | [XmlAttribute]
20 | public string XConversion { get; set; }
21 |
22 | [XmlAttribute]
23 | public string YParameter { get; set; }
24 |
25 | [XmlAttribute]
26 | public string YConversion { get; set; }
27 |
28 | [XmlAttribute]
29 | public string Formula { get; set; }
30 |
31 | [XmlAttribute]
32 | public string Format { get; set; }
33 | }
34 |
35 | public class MathValueConfiguration
36 | {
37 | [XmlElement("MathValue")]
38 | public List MathValues;
39 | }
40 |
41 | public class MathValueConfigurationLoader
42 | {
43 | private readonly ILogger logger;
44 |
45 | public MathValueConfiguration Configuration { get; private set; }
46 |
47 | public MathValueConfigurationLoader(ILogger logger)
48 | {
49 | this.logger = logger;
50 | }
51 |
52 | public bool Initialize()
53 | {
54 | try
55 | {
56 | using (Stream stream = File.OpenRead("MathValues.configuration"))
57 | {
58 | XmlSerializer serializer = new XmlSerializer(typeof(MathValueConfiguration));
59 | this.Configuration = (MathValueConfiguration)serializer.Deserialize(stream);
60 | return true;
61 | }
62 | }
63 | catch (Exception exception)
64 | {
65 | this.logger.AddUserMessage("Unable to load math-value configuration.");
66 | this.logger.AddDebugMessage(exception.ToString());
67 | return false;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Tests/ScanToolTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using System.Threading.Tasks;
4 |
5 | using PcmHacking;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 |
8 | namespace Tests
9 | {
10 | [TestClass]
11 | public class ScanToolTests
12 | {
13 | [TestMethod]
14 | public async Task SendRequest()
15 | {
16 | // Create the object we're going to test.
17 | TestLogger logger = new TestLogger();
18 | TestPort port = new TestPort(logger);
19 | Message response = null;
20 | Action responseSetter = (x) => { response = x; };
21 | ScanToolDeviceImplementation device = new ScanToolDeviceImplementation(responseSetter, null, port, logger);
22 |
23 | // Specify the sequence of bytes that we would expect to get back from the serial port.
24 | // Note that the test passes, but the first sequence ends with ">\r\n" and the second ends with "\r\n>" - this seems suspicious.
25 | port.EnqueueBytes(Encoding.ASCII.GetBytes("OK>\r\n"));
26 | port.EnqueueBytes(Encoding.ASCII.GetBytes("6CF0107C01003147315959C3\r\n>"));
27 | port.BytesToReceive.Position = 0;
28 |
29 | // Send a message.
30 | Message message = new Message(new byte[] { 0x6c, 0x10, 0xF0, 0x3C, 0x01 });
31 | bool sendSuccess = await device.SendMessage(message);
32 |
33 | // Confirm success.
34 | Assert.IsTrue(sendSuccess, "Send success.");
35 |
36 | // Confirm that the device sent the bytes we expect it to send.
37 | Assert.AreEqual("AT SH 6C 10 F0 \r\n", System.Text.Encoding.ASCII.GetString(port.MessagesSent[0]), "Set-header command");
38 | Assert.AreEqual("3C 01\r\n", Encoding.ASCII.GetString(port.MessagesSent[1]), "Read block 1 command");
39 |
40 | // Confirm that the device interpreted the response as expected.
41 | Assert.IsNotNull(response, "Response should not be null.");
42 | Assert.AreEqual("6C F0 10 7C 01 00 31 47 31 59 59", response.GetBytes().ToHex(), "Response message");
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/IPCLogger/O2SensorsAndTrims.xml.profile:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/IPCLibrary/Misc/AwayMode.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Runtime.InteropServices;
4 | using System.Text;
5 |
6 | namespace PcmHacking
7 | {
8 | public class AwayMode : IDisposable
9 | {
10 | [FlagsAttribute]
11 | public enum EXECUTION_STATE : uint
12 | {
13 | ES_SYSTEM_REQUIRED = 0x00000001,
14 | ES_DISPLAY_REQUIRED = 0x00000002,
15 | // Legacy flag, should not be used.
16 | // ES_USER_PRESENT = 0x00000004,
17 | ES_AWAYMODE_REQUIRED = 0x00000040,
18 | ES_CONTINUOUS = 0x80000000,
19 | }
20 |
21 | [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
22 | private static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
23 |
24 | private EXECUTION_STATE previousState;
25 |
26 | public AwayMode()
27 | {
28 | this.previousState = SetThreadExecutionState(
29 | EXECUTION_STATE.ES_CONTINUOUS
30 | | EXECUTION_STATE.ES_DISPLAY_REQUIRED
31 | | EXECUTION_STATE.ES_SYSTEM_REQUIRED
32 | | EXECUTION_STATE.ES_AWAYMODE_REQUIRED);
33 | }
34 |
35 | #region IDisposable Support
36 | private bool disposedValue = false; // To detect redundant calls
37 |
38 | protected virtual void Dispose(bool disposing)
39 | {
40 | if (!disposedValue)
41 | {
42 | if (disposing)
43 | {
44 | // TODO: dispose managed state (managed objects).
45 | }
46 |
47 | SetThreadExecutionState(this.previousState);
48 |
49 | disposedValue = true;
50 | }
51 | }
52 |
53 | ///
54 | /// Override finalizer to ensure that 'away mode' is released even if Dispose is not called.
55 | ///
56 | ~AwayMode()
57 | {
58 | // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
59 | Dispose(false);
60 | }
61 |
62 | // This code added to correctly implement the disposable pattern.
63 | public void Dispose()
64 | {
65 | // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
66 | Dispose(true);
67 | GC.SuppressFinalize(this);
68 | }
69 |
70 | #endregion
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/IPCLogger/Example3.xml.profile:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/IPCLogger/Example1.xml.profile:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/IPCHammer/DialogBoxes/A7k140mphForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace PcmHacking.DialogBoxes
12 | {
13 | ///
14 | /// Prompt the user to enter a valid VIN.
15 | ///
16 | public partial class A7k140mphForm : Form
17 | {
18 | ///
19 | /// This will be copied into the text box when the dialog box appears.
20 | /// When the dialog closes, if the user provided a valid VIN it will
21 | /// be returned via this property. If they didn't, this will be null.
22 | ///
23 | public Boolean Tach { get; set; }
24 | public Boolean Speedo { get; set; }
25 | ///
26 | /// Constructor.
27 | ///
28 | public A7k140mphForm()
29 | {
30 | InitializeComponent();
31 | }
32 |
33 | ///
34 | /// Load event handler.
35 | ///
36 | private void A7k140mphForm_Load(object sender, EventArgs e)
37 | {
38 |
39 |
40 | }
41 |
42 | ///
43 | /// OK button click handler.
44 | ///
45 | private void okButton_Click(object sender, EventArgs e)
46 | {
47 |
48 | this.Tach = this.Tach;
49 | this.DialogResult = DialogResult.OK;
50 | }
51 |
52 | ///
53 | /// Cancel button click handler.
54 | ///
55 | private void cancelButton_Click(object sender, EventArgs e)
56 | {
57 |
58 |
59 | this.DialogResult = DialogResult.Cancel;
60 | }
61 |
62 | private void checkBox1_CheckedChanged(object sender, EventArgs e)
63 | {
64 |
65 | if (this.checkBox1.Checked == true)
66 | {
67 | this.Tach = true;
68 | }
69 | else
70 | {
71 | this.Tach = false;
72 | }
73 | }
74 |
75 | private void checkBox2_CheckedChanged(object sender, EventArgs e)
76 | {
77 |
78 | if (this.checkBox2.Checked == true)
79 | {
80 | this.Speedo = true;
81 | }
82 | else
83 | {
84 | this.Speedo = false;
85 | }
86 | }
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/IPCLibrary/Misc/Crc.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace PcmHacking
6 | {
7 | ///
8 | /// From https://barrgroup.com/Embedded-Systems/How-To/CRC-Calculation-C-Code
9 | ///
10 | public class Crc
11 | {
12 | private static UInt32[] crcTable;
13 | private const int WIDTH = 8 * 4;
14 | private const UInt32 TOPBIT = 0x80000000;
15 | private const UInt32 POLYNOMIAL = 0x04C11DB7;
16 |
17 | public Crc()
18 | {
19 | if (crcTable == null)
20 | {
21 | crcTable = new UInt32[256];
22 | UInt32 remainder;
23 |
24 | /*
25 | * Compute the remainder of each possible dividend.
26 | */
27 | for (int dividend = 0; dividend < 256; ++dividend)
28 | {
29 | /*
30 | * Start with the dividend followed by zeros.
31 | */
32 | remainder = (UInt32)(dividend << (WIDTH - 8));
33 |
34 | /*
35 | * Perform modulo-2 division, a bit at a time.
36 | */
37 | for (int bit = 8; bit > 0; --bit)
38 | {
39 | /*
40 | * Try to divide the current data bit.
41 | */
42 | if ((remainder & TOPBIT) != 0)
43 | {
44 | remainder = (remainder << 1) ^ POLYNOMIAL;
45 | }
46 | else
47 | {
48 | remainder = (remainder << 1);
49 | }
50 | }
51 |
52 | /*
53 | * Store the result into the table.
54 | */
55 | crcTable[dividend] = remainder;
56 | }
57 | }
58 | }
59 |
60 | public UInt32 GetCrc(byte[] buffer, UInt32 start, UInt32 length)
61 | {
62 | byte data;
63 | UInt32 remainder = 0;
64 |
65 | for (UInt32 index = start; index < start + length; index++)
66 | {
67 | /*
68 | * Divide the message by the polynomial, a byte at a time.
69 | */
70 | data = (byte)(buffer[index] ^ (remainder >> (WIDTH - 8)));
71 | remainder = crcTable[data] ^ (remainder << 8);
72 | }
73 |
74 | /*
75 | * The final remainder is the CRC.
76 | */
77 | return (remainder);
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/IPCHammer/DialogBoxes/DelayDialogBox.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Data;
5 | using System.Drawing;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 | using System.Windows.Forms;
10 |
11 | namespace PcmHacking
12 | {
13 | ///
14 | /// This form reminds the user to pause before attempting a full read.
15 | ///
16 | public partial class DelayDialogBox : Form
17 | {
18 | ///
19 | /// Timer to drive the countdown text.
20 | ///
21 | private Timer timer;
22 |
23 | ///
24 | /// Number of seconds to wait. This value will count down with each timer tick.
25 | ///
26 | private int secondsRemaining = 10;
27 |
28 | ///
29 | /// Constructor.
30 | ///
31 | public DelayDialogBox()
32 | {
33 | this.FormBorderStyle = FormBorderStyle.FixedDialog;
34 | this.StartPosition = FormStartPosition.CenterParent;
35 | InitializeComponent();
36 | }
37 |
38 | ///
39 | /// Start the timer when the dialog box loads.
40 | ///
41 | private void DelayDialogBox_Load(object sender, EventArgs e)
42 | {
43 | this.Timer_Tick(null, null);
44 | this.timer = new Timer();
45 | timer.Interval = 1000;
46 | timer.Tick += Timer_Tick;
47 | timer.Start();
48 | }
49 |
50 | ///
51 | /// Decrement the countdown with each timer tick, close the form when we reach zero.
52 | ///
53 | private void Timer_Tick(object sender, EventArgs e)
54 | {
55 | if (secondsRemaining > 0)
56 | {
57 | this.countdown.Text = secondsRemaining + " seconds remaining...";
58 | this.secondsRemaining--;
59 | }
60 | else
61 | {
62 | this.countdown.Text = "Continuing...";
63 | this.continueButton_Click(this, e);
64 | }
65 | }
66 |
67 | ///
68 | /// Close the form with an "OK" result.
69 | ///
70 | private void continueButton_Click(object sender, EventArgs e)
71 | {
72 | this.DialogResult = DialogResult.OK;
73 | }
74 |
75 | ///
76 | /// Close the form with a "Cancel" result.
77 | ///
78 | private void cancelButton_Click(object sender, EventArgs e)
79 | {
80 | this.DialogResult = DialogResult.Cancel;
81 | }
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/IPCLogger/Failed.json:
--------------------------------------------------------------------------------
1 | 1154 failed
2 |
3 |
4 |
5 | {
6 | "Conversion": {
7 | "Name": "C",
8 | "Expression": "x*5/255"
9 | },
10 | "Name": "Exhaust Gas Temperature",
11 | "DefineBy": 1,
12 | "ByteCount": 1,
13 | "Address": "0x1515"
14 | },
15 |
16 |
17 |
18 | {
19 | "Conversion": {
20 | "Name": "C",
21 | "Expression": "x-40"
22 | },
23 | "Name": "Engine Oil Temp 2",
24 | "DefineBy": 1,
25 | "ByteCount": 1,
26 | "Address": "0x153E"
27 | },
28 |
29 |
30 |
31 | {
32 | "Conversion": {
33 | "Name": "C",
34 | "Expression": "x+40/0.75"
35 | },
36 | "Name": "Transmission Temperature",
37 | "DefineBy": 1,
38 | "ByteCount": 1,
39 | "Address": "0x1603"
40 | },
41 |
42 |
43 | {
44 | "Conversion": {
45 | "Name": "C",
46 | "Expression": "(X+40)*(256/192)"
47 | },
48 | "Name": "Transmission Oil Temp",
49 | "DefineBy": 1,
50 | "ByteCount": 1,
51 | "Address": "0x1949"
52 | },
53 |
54 |
55 | {
56 | "Conversion": {
57 | "Name": "steps",
58 | "Expression": "x"
59 | },
60 | "Name": "IAC position",
61 | "DefineBy": 1,
62 | "ByteCount": 1,
63 | "Address": "0x1179"
64 | },
65 |
66 |
67 | {
68 | "Conversion": {
69 | "Name": "RPM",
70 | "Expression": "x*8"
71 | },
72 | "Name": "Target idle speed 2",
73 | "DefineBy": 1,
74 | "ByteCount": 1,
75 | "Address": "0x11C9"
76 | },
77 |
78 |
79 | {
80 | "Conversion": {
81 | "Name": "Seconds",
82 | "Expression": "x"
83 | },
84 | "Name": "Engine Off Time",
85 | "DefineBy": 1,
86 | "ByteCount": 1,
87 | "Address": "0x13B5"
88 | },
--------------------------------------------------------------------------------
/Tests/TestPort.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace PcmHacking
9 | {
10 | ///
11 | /// This class allows test cases to specify data to receive, and examine data that was sent.
12 | ///
13 | public class TestPort : IPort
14 | {
15 | public List MessagesSent { get; }
16 |
17 | public MemoryStream BytesToReceive { get; }
18 |
19 | public TestPort(ILogger logger)
20 | {
21 | this.MessagesSent = new List();
22 | this.BytesToReceive = new MemoryStream();
23 | }
24 |
25 | public void EnqueueBytes(byte[] bytes)
26 | {
27 | this.BytesToReceive.Write(bytes, 0, bytes.Length);
28 | }
29 |
30 | ///
31 | /// This returns the string that appears in the drop-down list.
32 | ///
33 | public override string ToString()
34 | {
35 | return "Test Port";
36 | }
37 |
38 | ///
39 | /// Pretend to open a port.
40 | ///
41 | Task IPort.OpenAsync(PortConfiguration configuration)
42 | {
43 | return Task.CompletedTask;
44 | }
45 |
46 | ///
47 | /// Pretend to close a port.
48 | ///
49 | public void Dispose()
50 | {
51 | }
52 |
53 | ///
54 | /// Send bytes to the mock PCM.
55 | ///
56 | Task IPort.Send(byte[] buffer)
57 | {
58 | this.MessagesSent.Add(buffer);
59 |
60 | return Task.CompletedTask;
61 | }
62 |
63 | ///
64 | /// Receive bytes from the mock PCM.
65 | ///
66 | Task IPort.Receive(byte[] buffer, int offset, int count)
67 | {
68 | BytesToReceive.Read(buffer, offset, count);
69 | return Task.FromResult(count);
70 | }
71 |
72 | ///
73 | /// Discard anything in the input and output buffers.
74 | ///
75 | public Task DiscardBuffers()
76 | {
77 | return Task.FromResult(0);
78 | }
79 |
80 | ///
81 | /// Sets the read timeout.
82 | ///
83 | public void SetTimeout(int milliseconds)
84 | {
85 | }
86 |
87 | ///
88 | /// Indicates the number of bytes waiting in the queue.
89 | ///
90 | Task IPort.GetReceiveQueueSize()
91 | {
92 | // return Task.FromResult(0);
93 | throw new NotImplementedException();
94 | }
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/Tests/MathTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using Microsoft.VisualStudio.TestTools.UnitTesting;
5 | using PcmHacking;
6 |
7 | namespace Tests
8 | {
9 | [TestClass]
10 | public class MathTests
11 | {
12 | [TestMethod]
13 | public void MathValueTest()
14 | {
15 | ProfileParameter rpm = new ProfileParameter();
16 | rpm.Name = "Engine Speed";
17 | rpm.Conversion = new Conversion();
18 | rpm.Conversion.Name = "RPM";
19 | rpm.Conversion.Expression = "x";
20 |
21 | ProfileParameter maf = new ProfileParameter();
22 | maf.Name = "Mass Air Flow";
23 | maf.Conversion = new Conversion();
24 | maf.Conversion.Name = "g/s";
25 | maf.Conversion.Expression = "x";
26 |
27 | MathValue load = new MathValue();
28 | load.XParameter = rpm.Name;
29 | load.XConversion = rpm.Conversion.Name;
30 | load.YParameter = maf.Name;
31 | load.YConversion = maf.Conversion.Name;
32 | load.Format = "0.00";
33 | load.Formula = "(y*60)/x";
34 |
35 | LogProfile profile = new LogProfile();
36 | profile.ParameterGroups.Add(new ParameterGroup());
37 | profile.ParameterGroups[0].Parameters.Add(rpm);
38 | profile.ParameterGroups[0].Parameters.Add(maf);
39 |
40 | //MockDevice mockDevice = new MockDevice();
41 | //MockLogger mockLogger = new MockLogger();
42 | //Vehicle vehicle = new Vehicle(
43 | // new MockDevice(),
44 | // new Protocol(),
45 | // mockLogger,
46 | // new ToolPresentNotifier(mockDevice, mockLogger));
47 | //Logger logger = new Logger(vehicle, profile, mathValueConfiguration);
48 |
49 | //MathValueConfigurationLoader loader = new MathValueConfigurationLoader();
50 | //loader.Initialize();
51 | MathValueConfiguration mathValueConfiguration = new MathValueConfiguration();
52 | mathValueConfiguration.MathValues = new List();
53 | mathValueConfiguration.MathValues.Add(load);
54 |
55 | DpidValues dpidValues = new DpidValues();
56 | dpidValues.Add(rpm, new ParameterValue() { RawValue = 1000 });
57 | dpidValues.Add(maf, new ParameterValue() { RawValue = 100 });
58 |
59 | MathValueProcessor processor = new MathValueProcessor(profile, mathValueConfiguration);
60 | IEnumerable mathValues = processor.GetMathValues(dpidValues);
61 |
62 | Assert.AreEqual(1, mathValues.Count(), "Number of math values.");
63 | string loadValue = mathValues.First();
64 | Assert.AreEqual("6.00", loadValue, "Load value.");
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/IPCLogger/Memory.json.profile:
--------------------------------------------------------------------------------
1 | {
2 | "ParameterGroups": [
3 | {
4 | "Dpid": "0xFE",
5 | "Parameters": [
6 | {
7 | "Conversion": {
8 | "Name": "RPM",
9 | "Expression": "x*.25"
10 | },
11 | "Name": "Engine Speed",
12 | "DefineBy": 1,
13 | "ByteCount": 2,
14 | "Address": "0xC"
15 | },
16 | {
17 | "Conversion": {
18 | "Name": "g\/s",
19 | "Expression": "x\/100"
20 | },
21 | "Name": "Mass Air Flow",
22 | "DefineBy": 1,
23 | "ByteCount": 2,
24 | "Address": "0x10"
25 | },
26 | {
27 | "Conversion": {
28 | "Name": "kpa",
29 | "Expression": "x"
30 | },
31 | "Name": "Manifold Absolute Pressure",
32 | "DefineBy": 1,
33 | "ByteCount": 1,
34 | "Address": "0xB"
35 | },
36 | {
37 | "Conversion": {
38 | "Name": "%",
39 | "Expression": "x\/2.56"
40 | },
41 | "Name": "Throttle Position Sensor",
42 | "DefineBy": 1,
43 | "ByteCount": 1,
44 | "Address": "0x11"
45 | }
46 | ],
47 | "TotalBytes": 6
48 | },
49 | {
50 | "Dpid": "0xFD",
51 | "Parameters": [
52 | {
53 | "Conversion" : {
54 | "Name": "Raw",
55 | "Expression": "0x"
56 | },
57 | "Name": "Address FF8800",
58 | "DefineBy": 2,
59 | "ByteCount": 2,
60 | "Address": "0xFF8800"
61 | },
62 | {
63 | "Conversion": {
64 | "Name": "Raw",
65 | "Expression": "0x"
66 | },
67 | "Name": "Address FF8802",
68 | "DefineBy": 2,
69 | "ByteCount": 2,
70 | "Address": "0xFF8802"
71 | },
72 | {
73 | "Conversion": {
74 | "Name": "Raw",
75 | "Expression": "0x"
76 | },
77 | "Name": "Ignition Advance Multiplier",
78 | "DefineBy": 2,
79 | "ByteCount": 2,
80 | "Address": "0xFF8250"
81 | }
82 | ],
83 | "TotalBytes": 6
84 | }
85 | ]
86 | }
--------------------------------------------------------------------------------
/IPCLogger/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace IPCLogger.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("IPCLogger.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/VpwExplorer/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace PcmExplorer.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PcmExplorer.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/IPCLibrary/Misc/ToolPresentNotifier.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace PcmHacking
8 | {
9 | ///
10 | /// Send VPW "tool present" messages to keep the PCM in a state receptive to reading and writing.
11 | ///
12 | public class ToolPresentNotifier
13 | {
14 | ///
15 | /// Provides access to the Results and Debug panes.
16 | ///
17 | ILogger logger;
18 |
19 | ///
20 | /// Generates VPW messages.
21 | ///
22 | Protocol protocol;
23 |
24 | ///
25 | /// The device to send messages with.
26 | ///
27 | Device device;
28 |
29 | ///
30 | /// When the last message was sent.
31 | ///
32 | DateTime lastNotificationTime = DateTime.MinValue;
33 |
34 | ///
35 | /// Constructor.
36 | ///
37 | public ToolPresentNotifier(Device device, Protocol protocol, ILogger logger)
38 | {
39 | this.logger = logger;
40 | this.protocol = protocol;
41 | this.device = device;
42 | }
43 |
44 | ///
45 | /// Send a tool-present message, if the time is right.
46 | ///
47 | ///
48 | public async Task Notify()
49 | {
50 | // Tool present / 3F is required every 2.5 seconds.
51 | //
52 | // This timer ensures we won't call it more often than every 2 seconds,
53 | // but there is no upper bound because other code could spend lots of
54 | // time between calls to this code.
55 | //
56 | // Consider reducing this to 1.5 seconds if 2 seconds isn't fast enough.
57 | if(DateTime.Now > this.lastNotificationTime + TimeSpan.FromSeconds(2))
58 | {
59 | await this.SendNotification();
60 | this.lastNotificationTime = DateTime.Now;
61 | }
62 | }
63 |
64 | ///
65 | /// Send a tool-present message, even if not much time has passed. This is to aid in polling.
66 | ///
67 | ///
68 | public async Task ForceNotify()
69 | {
70 | await this.SendNotification();
71 | }
72 |
73 | ///
74 | /// Send a tool-present message.
75 | ///
76 | private async Task SendNotification()
77 | {
78 | this.logger.AddDebugMessage("Sending 'test device present' notification.");
79 | Message message = this.protocol.CreateTestDevicePresentNotification();
80 | TimeoutScenario originalScenario = await this.device.SetTimeout(TimeoutScenario.Minimum);
81 | await this.device.SendMessage(message);
82 | await this.device.SetTimeout(originalScenario);
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/IPCLibrary/Messages/BlockId.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace PcmHacking
8 | {
9 | public class BlockId
10 | {
11 | public const byte Vin1 = 0x01; // 5 bytes of VIN
12 | public const byte Vin2 = 0x02; // 6 bytes of VIN
13 | public const byte Vin3 = 0x03; // 6 bytes of VIN
14 | public const byte HardwareID = 0x08; // Hardware ID
15 | public const byte Serial1 = 0x05; // 4 bytes of Serial
16 | public const byte Serial2 = 0x06; // 4 bytes of Serial
17 | public const byte Serial3 = 0x07; // 4 bytes of Serial
18 | public const byte CalibrationID = 0x0B; // Calibration ID
19 | public const byte OperatingSystemID = 0x0A; // Operating System ID aka OSID
20 | public const byte EngineCalID = 0xFF; // Engine Segment Calibration ID
21 | public const byte EngineDiagCalID = 0x0C; // Engine Diagnostic Calibration ID
22 | public const byte TransCalID = 0x0D; // Transmission Segment Calibration ID
23 | public const byte TransDiagID = 0x0E; // Transmission Diagnostic Calibration ID
24 | public const byte FuelCalID = 0x0F; // Fuel Segment Calibration ID
25 | public const byte SystemCalID = 0x10; // System Segment Calibration ID
26 | public const byte SpeedCalID = 0x11; // Speed Calibration ID
27 | public const byte BCC = 0x14; // Broad Cast Code
28 | public const byte OilLifePerc = 0x6D; // Oil Life Remaining Percent
29 | public const byte OperatingSystemLvl = 0x93; // Operating System Level
30 | public const byte EngineCalLvl = 0x94; // Engine Segment Calibration Level
31 | public const byte EngineDiagCalLvl = 0x95; // Engine Diagnostic Calibration Level
32 | public const byte TransCalLvl = 0x96; // Transmission Segment Calibration Level
33 | public const byte TransDiagLvl = 0x97; // Transmission Diagnostic Calibration Level
34 | public const byte BootSector = 0x98; // Fuel Segment Calibration Level
35 | public const byte SystemCalLvl = 0x99; // System Segment Calibration Level
36 | public const byte SpeedCalLvl = 0x9A; // Speed Calibration Level
37 | public const byte MEC = 0xA0; // Manufacturers Enable Counter
38 | }
39 |
40 | public class BlockIdIPC
41 | {
42 | public const byte SpeedoCal = 0x90;
43 | public const byte TachCal = 0x91;
44 | public const byte FuelCal = 0x92;
45 | public const byte CoolantTempCal = 0x93;
46 | public const byte VoltCal = 0x94;
47 | public const byte OilCal = 0x95;
48 | public const byte TransTempCal = 0x97;
49 | public const byte Options = 0x9A;
50 | public const byte Options99 = 0x80;
51 |
52 |
53 | }
54 |
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/IPCLibrary/Ports/MockPort.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace PcmHacking
8 | {
9 | ///
10 | /// This class is just here to enable testing without any actual interface hardware.
11 | ///
12 | ///
13 | /// Eventually the Receive method should return simulated VPW responses.
14 | ///
15 | public class MockPort : IPort
16 | {
17 | public const string PortName = "Mock Port";
18 |
19 | private MockPcm pcm;
20 |
21 | public MockPort(ILogger logger)
22 | {
23 | this.pcm = new MockPcm(logger);
24 | }
25 |
26 | ///
27 | /// This returns the string that appears in the drop-down list.
28 | ///
29 | public override string ToString()
30 | {
31 | return PortName;
32 | }
33 |
34 | ///
35 | /// Pretend to open a port.
36 | ///
37 | Task IPort.OpenAsync(PortConfiguration configuration)
38 | {
39 | return Task.CompletedTask;
40 | }
41 |
42 | ///
43 | /// Pretend to close a port.
44 | ///
45 | public void Dispose()
46 | {
47 | }
48 |
49 | ///
50 | /// Send bytes to the mock PCM.
51 | ///
52 | Task IPort.Send(byte[] buffer)
53 | {
54 | this.pcm.ResetCommunications();
55 |
56 | foreach(byte b in buffer)
57 | {
58 | this.pcm.Push(b);
59 | }
60 |
61 | this.pcm.EndOfData();
62 |
63 | return Task.CompletedTask;
64 | }
65 |
66 | ///
67 | /// Receive bytes from the mock PCM.
68 | ///
69 | Task IPort.Receive(byte[] buffer, int offset, int count)
70 | {
71 | byte[] responseBuffer = this.pcm.GetResponse();
72 |
73 | int index = 0;
74 | for(; index < count && index < responseBuffer.Length; index++)
75 | {
76 | buffer[offset + index] = responseBuffer[index];
77 | }
78 |
79 | return Task.FromResult(index);
80 | }
81 |
82 | ///
83 | /// Discard anything in the input and output buffers.
84 | ///
85 | public Task DiscardBuffers()
86 | {
87 | return Task.FromResult(0);
88 | }
89 |
90 | ///
91 | /// Sets the read timeout.
92 | ///
93 | public void SetTimeout(int milliseconds)
94 | {
95 | }
96 |
97 | ///
98 | /// Indicates the number of bytes waiting in the queue.
99 | ///
100 | Task IPort.GetReceiveQueueSize()
101 | {
102 | // return Task.FromResult(0);
103 | throw new NotImplementedException();
104 | }
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/IPCLibrary/Messages/Protocol.Misc.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace PcmHacking
6 | {
7 | public partial class Protocol
8 | {
9 | ///
10 | /// Tell the bus that a test device is present.
11 | ///
12 | public Message CreateTestDevicePresentNotification()
13 | {
14 | byte[] bytes = new byte[] { Priority.Physical0High, DeviceId.Broadcast, DeviceId.Tool, Mode.TestDevicePresent };
15 | return new Message(bytes);
16 | }
17 |
18 | ///
19 | /// Create a broadcast message telling all modules to clear diagnostic trouble codes.
20 | ///
21 | public Message CreateClearDiagnosticTroubleCodesRequest()
22 | {
23 | byte[] bytes = new byte[] { Priority.Functional0, 0x6A, DeviceId.Tool, Mode.ClearDiagnosticTroubleCodes };
24 | return new Message(bytes);
25 | }
26 |
27 | ///
28 | /// Create a broadcast message telling all modules to clear diagnostic information.
29 | ///
30 | public Message CreateClearDiagnosticInformationRequest()
31 | {
32 | byte[] bytes = new byte[] { Priority.Physical0High, DeviceId.Broadcast, DeviceId.Tool, Mode.ClearDiagnosticInformation };
33 | return new Message(bytes);
34 | }
35 |
36 | ///
37 | /// Create a broadcast message telling all devices to disable normal message transmission (disable chatter)
38 | ///
39 | public Message CreateDisableNormalMessageTransmission()
40 | {
41 | byte[] Bytes = new byte[] { Priority.Physical0, DeviceId.Broadcast, DeviceId.Tool, Mode.SilenceBus, SubMode.Null };
42 | return new Message(Bytes);
43 | }
44 |
45 | ///
46 | /// Create a broadcast message telling all devices to disable normal message transmission (disable chatter)
47 | ///
48 | public Message CreateDisableNormalMessageTransmissionOK()
49 | {
50 | byte[] bytes = new byte[] { Priority.Physical0, DeviceId.Tool, DeviceId.Pcm, Mode.SilenceBus + Mode.Response, SubMode.Null };
51 | return new Message(bytes);
52 | }
53 |
54 | ///
55 | /// Create a broadcast message telling all devices to clear their DTCs
56 | ///
57 | public Message ClearDTCs()
58 | {
59 | byte[] bytes = new byte[] { Priority.Functional0, 0x6A, DeviceId.Tool, Mode.ClearDiagnosticTroubleCodes };
60 | return new Message(bytes);
61 | }
62 |
63 | ///
64 | /// PCM Response to Clear DTCs
65 | ///
66 | public Message ClearDTCsOK()
67 | {
68 | byte[] bytes = new byte[] { Priority.Functional0Low, 0x6B, DeviceId.Pcm, Mode.ClearDiagnosticTroubleCodes + Mode.Response };
69 | return new Message(bytes);
70 | }
71 |
72 | public Response ParseRecoveryModeBroadcast(Message message)
73 | {
74 | Response rc = this.DoSimpleValidation(message, 0x6C, 0x62, 0x01);
75 | if (!rc.Value) rc = this.DoSimpleValidation(message, 0x6C, 0xA2, 0x00);
76 | return rc;
77 | }
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/IPCLogger/OldProfiles/Idle2.profile:
--------------------------------------------------------------------------------
1 | {
2 | "ParameterGroups": [
3 | {
4 | "Dpid": "0xFE",
5 | "Parameters": [
6 | {
7 | "Conversion": {
8 | "Name": "RPM",
9 | "Expression": "x*.25"
10 | },
11 | "Name": "Engine Speed",
12 | "DefineBy": 1,
13 | "ByteCount": 2,
14 | "Address": "0xC"
15 | },
16 | {
17 | "Conversion": {
18 | "Name": "g\/s",
19 | "Expression": "x\/100"
20 | },
21 | "Name": "Mass Air Flow",
22 | "DefineBy": 1,
23 | "ByteCount": 2,
24 | "Address": "0x10"
25 | },
26 | {
27 | "Conversion": {
28 | "Name": "Raw",
29 | "Expression": "x"
30 | },
31 | "Name": "PID 1105; 128=DFCO",
32 | "DefineBy": 1,
33 | "ByteCount": 1,
34 | "Address": "0x1105"
35 | },
36 | {
37 | "Conversion": {
38 | "Name": "RPM",
39 | "Expression": "x*12.5"
40 | },
41 | "Name": "Desired Idle Speed",
42 | "DefineBy": 1,
43 | "ByteCount": 1,
44 | "Address": "0x1192"
45 | }
46 | ],
47 | "TotalBytes": 6
48 | },
49 | {
50 | "Dpid": "0xFD",
51 | "Parameters": [
52 | {
53 | "Conversion": {
54 | "Name": "kpa",
55 | "Expression": "x"
56 | },
57 | "Name": "Manifold Absolute Pressure",
58 | "DefineBy": 1,
59 | "ByteCount": 1,
60 | "Address": "0xB"
61 | },
62 | {
63 | "Conversion": {
64 | "Name": "%",
65 | "Expression": "(x-128)\/1.28"
66 | },
67 | "Name": "Left Long Term Fuel Trim",
68 | "DefineBy": 1,
69 | "ByteCount": 1,
70 | "Address": "0x7"
71 | },
72 | {
73 | "Conversion": {
74 | "Name": "Mode",
75 | "Expression": "x"
76 | },
77 | "Name": "Fueling Mode",
78 | "DefineBy": 1,
79 | "ByteCount": 2,
80 | "Address": "0x3"
81 | },
82 | {
83 | "Conversion": {
84 | "Name": "Degrees",
85 | "Expression": "x*(100.0/255.0)"
86 | },
87 | "Name": "Throttle Position",
88 | "DefineBy": 1,
89 | "ByteCount": 1,
90 | "Address": "0x11"
91 | },
92 | ],
93 | "TotalBytes": 6
94 | }
95 | ]
96 | }
--------------------------------------------------------------------------------
/IPCLibrary/Logging/Logger.cs:
--------------------------------------------------------------------------------
1 | //#define FAST_LOGGING
2 |
3 | using System;
4 | using System.Collections.Generic;
5 | using System.IO;
6 | using System.Linq;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace PcmHacking
11 | {
12 | ///
13 | /// Requests log data from the Vehicle.
14 | ///
15 | public class Logger
16 | {
17 | private readonly Vehicle vehicle;
18 | private readonly LogProfileAndMath profileAndMath;
19 | private DpidCollection dpids;
20 |
21 | #if FAST_LOGGING
22 | private DateTime lastRequestTime;
23 | #endif
24 |
25 | ///
26 | /// Constructor.
27 | ///
28 | public Logger(Vehicle vehicle, LogProfileAndMath profileAndMath, MathValueConfiguration mathValueConfiguration)
29 | {
30 | this.vehicle = vehicle;
31 | this.profileAndMath = profileAndMath;
32 | }
33 |
34 | ///
35 | /// Invoke this once to begin a logging session.
36 | ///
37 | public async Task StartLogging()
38 | {
39 | this.dpids = await this.vehicle.ConfigureDpids(this.profileAndMath.Profile);
40 |
41 | if (this.dpids == null)
42 | {
43 | return false;
44 | }
45 |
46 | int scenario = ((int)TimeoutScenario.DataLogging1 - 1);
47 | scenario += this.profileAndMath.Profile.ParameterGroups.Count;
48 | await this.vehicle.SetDeviceTimeout((TimeoutScenario)scenario);
49 |
50 | #if FAST_LOGGING
51 | if (!await this.vehicle.RequestDpids(this.dpids))
52 | {
53 | return false;
54 | }
55 |
56 | this.lastRequestTime = DateTime.Now;
57 | #endif
58 | return true;
59 | }
60 |
61 | ///
62 | /// Invoke this repeatedly to get each row of data from the PCM.
63 | ///
64 | ///
65 | public async Task> GetNextRow()
66 | {
67 | LogRowParser row = new LogRowParser(this.profileAndMath.Profile);
68 |
69 | #if FAST_LOGGING
70 | // if (DateTime.Now.Subtract(lastRequestTime) > TimeSpan.FromSeconds(2))
71 | {
72 | await this.vehicle.ForceSendToolPresentNotification();
73 | }
74 | #endif
75 | #if !FAST_LOGGING
76 | if (!await this.vehicle.RequestDpids(this.dpids))
77 | {
78 | return null;
79 | }
80 | #endif
81 |
82 | while (!row.IsComplete)
83 | {
84 |
85 | RawLogData rawData = await this.vehicle.ReadLogData();
86 | if (rawData == null)
87 | {
88 | return null;
89 | }
90 |
91 | row.ParseData(rawData);
92 | }
93 |
94 | DpidValues dpidValues = row.Evaluate();
95 |
96 | IEnumerable mathValues = this.profileAndMath.MathValueProcessor.GetMathValues(dpidValues);
97 |
98 | return dpidValues
99 | .Select(x => x.Value.ValueAsString)
100 | .Concat(mathValues)
101 | .ToArray();
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/IPCLibraryWindowsForms/Devices/J2534DeviceFinder.cs:
--------------------------------------------------------------------------------
1 | using J2534;
2 | using Microsoft.Win32;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace PcmHacking
10 | {
11 | class J2534DeviceFinder
12 | {
13 | private const string PASSTHRU_REGISTRY_PATH = "Software\\PassThruSupport.04.04";
14 | private const string PASSTHRU_REGISTRY_PATH_6432 = "Software\\Wow6432Node\\PassThruSupport.04.04";
15 |
16 | ///
17 | /// Find all installed J2534 DLLs
18 | ///
19 | public static List FindInstalledJ2534DLLs(ILogger logger)
20 | {
21 | List installedDLLs = new List();
22 |
23 | try
24 | {
25 | RegistryKey myKey = Registry.LocalMachine.OpenSubKey(PASSTHRU_REGISTRY_PATH, false);
26 | if ((myKey == null))
27 | {
28 | myKey = Registry.LocalMachine.OpenSubKey(PASSTHRU_REGISTRY_PATH_6432, false);
29 | if ((myKey == null))
30 | {
31 | return installedDLLs;
32 | }
33 |
34 | }
35 |
36 | string[] devices = myKey.GetSubKeyNames();
37 | foreach (string device in devices)
38 | {
39 | J2534.J2534Device tempDevice = new J2534.J2534Device();
40 | RegistryKey deviceKey = myKey.OpenSubKey(device);
41 | if ((deviceKey == null))
42 | {
43 | continue; //Skip device... its empty
44 | }
45 |
46 | tempDevice.Vendor = (string)deviceKey.GetValue("Vendor", "");
47 | tempDevice.Name = (string)deviceKey.GetValue("Name", "");
48 | tempDevice.ConfigApplication = (string)deviceKey.GetValue("ConfigApplication", "");
49 | tempDevice.FunctionLibrary = (string)deviceKey.GetValue("FunctionLibrary", "");
50 | tempDevice.CAN = (int)(deviceKey.GetValue("CAN", 0));
51 | tempDevice.ISO14230 = (int)(deviceKey.GetValue("ISO14230", 0));
52 | tempDevice.ISO15765 = (int)(deviceKey.GetValue("ISO15765", 0));
53 | tempDevice.ISO9141 = (int)(deviceKey.GetValue("ISO9141", 0));
54 | tempDevice.J1850PWM = (int)(deviceKey.GetValue("J1850PWM", 0));
55 | tempDevice.J1850VPW = (int)(deviceKey.GetValue("J1850VPW", 0));
56 | tempDevice.SCI_A_ENGINE = (int)(deviceKey.GetValue("SCI_A_ENGINE", 0));
57 | tempDevice.SCI_A_TRANS = (int)(deviceKey.GetValue("SCI_A_TRANS", 0));
58 | tempDevice.SCI_B_ENGINE = (int)(deviceKey.GetValue("SCI_B_ENGINE", 0));
59 | tempDevice.SCI_B_TRANS = (int)(deviceKey.GetValue("SCI_B_TRANS", 0));
60 | installedDLLs.Add(tempDevice);
61 | }
62 | return installedDLLs;
63 | }
64 | catch (Exception exception)
65 | {
66 | logger.AddDebugMessage("Error occured while finding installed J2534 devices");
67 | logger.AddDebugMessage(exception.ToString());
68 | return installedDLLs;
69 | }
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/IPCLibrary/Messages/Message.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace PcmHacking
9 | {
10 | ///
11 | /// Message is a thin wrapper around an array of bytes.
12 | ///
13 | ///
14 | /// I'll admit that this might be overkill as opposed to just passing around byte arrays.
15 | /// But the ToString method makes messages easier to view in the debugger.
16 | ///
17 | public class Message
18 | {
19 | ///
20 | /// The message content.
21 | ///
22 | private byte[] message;
23 |
24 | ///
25 | /// When the message was created.
26 | ///
27 | private ulong timestamp;
28 |
29 | ///
30 | /// Error code, if applicable.
31 | ///
32 | private ulong error;
33 |
34 | ///
35 | /// Returns the length of the message.
36 | ///
37 | public int Length
38 | {
39 | get
40 | {
41 | return this.message.Length;
42 | }
43 | }
44 |
45 | ///
46 | /// Get the Nth byte of the message.
47 | ///
48 | public byte this[int index]
49 | {
50 | get
51 | {
52 | return this.message[index];
53 | }
54 | }
55 |
56 | ///
57 | /// Constructor.
58 | ///
59 | public Message(byte[] message)
60 | {
61 | this.message = message;
62 | }
63 |
64 | ///
65 | /// Constructor.
66 | ///
67 | public Message(byte[] message, ulong timestamp, ulong error)
68 | {
69 | this.message = message;
70 | this.timestamp = timestamp;
71 | this.error = error;
72 | }
73 |
74 | ///
75 | /// When the message was created or recevied.
76 | ///
77 | public ulong TimeStamp
78 | {
79 | get { return this.timestamp; }
80 | set { this.timestamp = value; }
81 | }
82 |
83 | ///
84 | /// The error associated with creating or receiving this message.
85 | ///
86 | public ulong Error
87 | {
88 | get { return this.error; }
89 | set { this.error = value; }
90 | }
91 |
92 | ///
93 | /// Get the raw bytes.
94 | ///
95 | ///
96 | [DebuggerStepThrough]
97 | public byte[] GetBytes()
98 | {
99 | return this.message;
100 | }
101 |
102 | ///
103 | /// Generate a descriptive string for this message.
104 | ///
105 | ///
106 | /// This is the most valuable thing - it makes messages easy to view in the debugger.
107 | ///
108 | public override string ToString()
109 | {
110 | return string.Join(" ", Array.ConvertAll(message, b => b.ToString("X2")));
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/IPCApps.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.30717.126
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IpcHammer", "IPCHammer\IpcHammer.csproj", "{A6B28831-A16F-48F3-8C48-9B02CF0B6678}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{0AA6F273-995D-4ADE-8CBB-DB1B6E8A0FCE}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IPCLibrary", "IPCLibrary\PcmLibrary.csproj", "{0B317C5A-E078-4A96-8E7A-00601BCA1429}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IPCLogger", "IPCLogger\PcmLogger.csproj", "{6A473C4F-A1A3-4CFB-8167-13F4064C1639}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IPCLibraryWindowsForms", "IPCLibraryWindowsForms\PcmLibraryWindowsForms.csproj", "{4ADB5D87-D4D5-4D12-8681-A9E2D4C52DF6}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VpwExplorer", "VpwExplorer\VpwExplorer.csproj", "{2B57ABC7-9994-4DB3-9403-B22471A0DDA1}"
17 | EndProject
18 | Global
19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
20 | Debug|Any CPU = Debug|Any CPU
21 | Release|Any CPU = Release|Any CPU
22 | EndGlobalSection
23 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
24 | {A6B28831-A16F-48F3-8C48-9B02CF0B6678}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
25 | {A6B28831-A16F-48F3-8C48-9B02CF0B6678}.Debug|Any CPU.Build.0 = Debug|Any CPU
26 | {A6B28831-A16F-48F3-8C48-9B02CF0B6678}.Release|Any CPU.ActiveCfg = Release|Any CPU
27 | {A6B28831-A16F-48F3-8C48-9B02CF0B6678}.Release|Any CPU.Build.0 = Release|Any CPU
28 | {0AA6F273-995D-4ADE-8CBB-DB1B6E8A0FCE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {0AA6F273-995D-4ADE-8CBB-DB1B6E8A0FCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {0AA6F273-995D-4ADE-8CBB-DB1B6E8A0FCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {0AA6F273-995D-4ADE-8CBB-DB1B6E8A0FCE}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {0B317C5A-E078-4A96-8E7A-00601BCA1429}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {0B317C5A-E078-4A96-8E7A-00601BCA1429}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {0B317C5A-E078-4A96-8E7A-00601BCA1429}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {0B317C5A-E078-4A96-8E7A-00601BCA1429}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {6A473C4F-A1A3-4CFB-8167-13F4064C1639}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {6A473C4F-A1A3-4CFB-8167-13F4064C1639}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {6A473C4F-A1A3-4CFB-8167-13F4064C1639}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {6A473C4F-A1A3-4CFB-8167-13F4064C1639}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {4ADB5D87-D4D5-4D12-8681-A9E2D4C52DF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {4ADB5D87-D4D5-4D12-8681-A9E2D4C52DF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {4ADB5D87-D4D5-4D12-8681-A9E2D4C52DF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {4ADB5D87-D4D5-4D12-8681-A9E2D4C52DF6}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {2B57ABC7-9994-4DB3-9403-B22471A0DDA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {2B57ABC7-9994-4DB3-9403-B22471A0DDA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {2B57ABC7-9994-4DB3-9403-B22471A0DDA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {2B57ABC7-9994-4DB3-9403-B22471A0DDA1}.Release|Any CPU.Build.0 = Release|Any CPU
48 | EndGlobalSection
49 | GlobalSection(SolutionProperties) = preSolution
50 | HideSolutionNode = FALSE
51 | EndGlobalSection
52 | GlobalSection(ExtensibilityGlobals) = postSolution
53 | SolutionGuid = {E19457D5-96EB-4FDE-A87C-B4B72B547EEE}
54 | EndGlobalSection
55 | EndGlobal
56 |
--------------------------------------------------------------------------------
/IPCLibraryWindowsForms/Devices/DeviceFactory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace PcmHacking
8 | {
9 | public class DeviceFactory
10 | {
11 | ///
12 | /// This might not really need to be async. If the J2534 stuff doesn't need it, then this doesn't need it either.
13 | ///
14 | public static Device CreateDeviceFromConfigurationSettings(ILogger logger)
15 | {
16 | switch(Configuration.DeviceCategory)
17 | {
18 | case Configuration.Constants.DeviceCategorySerial:
19 | return CreateSerialDevice(Configuration.SerialPort, Configuration.SerialPortDeviceType, logger);
20 |
21 | case Configuration.Constants.DeviceCategoryJ2534:
22 | return CreateJ2534Device(Configuration.J2534DeviceType, logger);
23 |
24 | default:
25 | return null;
26 | }
27 | }
28 |
29 | public static Device CreateSerialDevice(string serialPortName, string serialPortDeviceType, ILogger logger)
30 | {
31 | try
32 | {
33 | IPort port;
34 | if (string.Equals(MockPort.PortName, serialPortName))
35 | {
36 | port = new MockPort(logger);
37 | }
38 | else if (string.Equals(HttpPort.PortName, serialPortName))
39 | {
40 | port = new HttpPort(logger);
41 | }
42 | else
43 | {
44 | port = new StandardPort(serialPortName);
45 | }
46 |
47 | Device device;
48 | switch (serialPortDeviceType)
49 | {
50 | case OBDXProDevice.DeviceType:
51 | device = new OBDXProDevice(port, logger);
52 | break;
53 |
54 | case AvtDevice.DeviceType:
55 | device = new AvtDevice(port, logger);
56 | break;
57 | case AvtDevice2.DeviceType:
58 | device = new AvtDevice2(port, logger);
59 | break;
60 | case MockDevice.DeviceType:
61 | device = new MockDevice(port, logger);
62 | break;
63 |
64 | case ElmDevice.DeviceType:
65 | device = new ElmDevice(port, logger);
66 | break;
67 |
68 | default:
69 | device = null;
70 | break;
71 | }
72 |
73 | if (device == null)
74 | {
75 | return null;
76 | }
77 |
78 | return device;
79 | }
80 | catch (Exception exception)
81 | {
82 | logger.AddUserMessage($"Unable to create {serialPortDeviceType} on {serialPortName}.");
83 | logger.AddDebugMessage(exception.ToString());
84 | return null;
85 | }
86 | }
87 |
88 | public static Device CreateJ2534Device(string deviceType, ILogger logger)
89 | {
90 | foreach(var device in J2534DeviceFinder.FindInstalledJ2534DLLs(logger))
91 | {
92 | if (device.Name == deviceType)
93 | {
94 | return new J2534Device(device, logger);
95 | }
96 | }
97 |
98 | return null;
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/IPCLibrary/Messages/Protocol.Speed.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace PcmHacking
6 | {
7 | public partial class Protocol
8 | {
9 | public class HighSpeedPermissionResult
10 | {
11 | public bool IsValid { get; set; }
12 | public byte DeviceId { get; set; }
13 | public bool PermissionGranted { get; set; }
14 | }
15 |
16 | ///
17 | /// Create a request for a module to test VPW speed switch to 4x is OK
18 | ///
19 | public Message CreateHighSpeedPermissionRequest(byte deviceId)
20 | {
21 | return new Message(new byte[] { Priority.Physical0, deviceId, DeviceId.Tool, Mode.HighSpeedPrepare });
22 | }
23 |
24 | ///
25 | /// Create a request for a specific module to switch to VPW 4x
26 | ///
27 | public Message CreateBeginHighSpeed(byte deviceId)
28 | {
29 | return new Message(new byte[] { Priority.Physical0, deviceId, DeviceId.Tool, Mode.HighSpeed });
30 | }
31 |
32 | ///
33 | /// Parse the response to a request for permission to switch to 4X mode.
34 | ///
35 | public HighSpeedPermissionResult ParseHighSpeedPermissionResponse(Message message)
36 | {
37 | byte[] actual = message.GetBytes();
38 | byte[] granted = new byte[] { Priority.Physical0, DeviceId.Tool, DeviceId.Pcm, Mode.HighSpeedPrepare + Mode.Response };
39 |
40 | // Priority
41 | if (actual[0] != granted[0])
42 | {
43 | return new HighSpeedPermissionResult() { IsValid = false };
44 | }
45 |
46 | // Destination
47 | if (actual[1] != granted[1])
48 | {
49 | return new HighSpeedPermissionResult() { IsValid = false };
50 | }
51 |
52 | // Source
53 | byte moduleId = actual[2];
54 |
55 | // Permission granted?
56 | if (actual[3] == Mode.HighSpeedPrepare + Mode.Response)
57 | {
58 | return new HighSpeedPermissionResult() { IsValid = true, DeviceId = moduleId, PermissionGranted = true };
59 | }
60 |
61 | if ((actual[3] == Mode.Rejected) || (actual[3] == 0x7F))
62 | {
63 | return new HighSpeedPermissionResult() { IsValid = true, DeviceId = moduleId, PermissionGranted = false };
64 | }
65 |
66 | return new HighSpeedPermissionResult() { IsValid = false };
67 | }
68 |
69 | public Response ParseHighSpeedRefusal(Message message)
70 | {
71 | byte[] actual = message.GetBytes();
72 | byte[] refusal = new byte[] { Priority.Physical0, DeviceId.Tool, DeviceId.Broadcast, Mode.HighSpeedPrepare + Mode.Response };
73 |
74 | // Priority
75 | if (actual[0] != refusal[0])
76 | {
77 | return Response.Create(ResponseStatus.UnexpectedResponse, false);
78 | }
79 |
80 | // Destination
81 | if (actual[1] != refusal[1])
82 | {
83 | return Response.Create(ResponseStatus.UnexpectedResponse, false);
84 | }
85 |
86 | // Source
87 | byte moduleId = refusal[2];
88 |
89 | if ((actual[3] == Mode.Rejected) || (actual[3] == 0x7F))
90 | {
91 | if (actual[4] == Mode.HighSpeed)
92 | {
93 | return Response.Create(ResponseStatus.Success, true);
94 | }
95 | }
96 |
97 | return Response.Create(ResponseStatus.UnexpectedResponse, false);
98 | }
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/IPCLibrary/Devices/MockDevice.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace PcmHacking
9 | {
10 | ///
11 | /// This class provides a way to test most of the app without any interface hardware.
12 | ///
13 | public class MockDevice : Device
14 | {
15 | ///
16 | /// Device ID string to use in the Device Picker form, and in interal device-type comparisons.
17 | ///
18 | public const string DeviceType = "Mock Serial Device";
19 |
20 | ///
21 | /// The mock port.
22 | ///
23 | private IPort port;
24 |
25 | ///
26 | /// Constructor.
27 | ///
28 | public MockDevice(IPort port, ILogger logger) : base(logger)
29 | {
30 | this.port = port;
31 | }
32 |
33 | ///
34 | /// Not actually necessary for this device type, but since we need to implement IDisposable...
35 | ///
36 | protected override void Dispose(bool disposing)
37 | {
38 | }
39 |
40 | ///
41 | /// Initialize the device. It's just a no-op for this device type.
42 | ///
43 | public override Task Initialize()
44 | {
45 | return Task.FromResult(true);
46 | }
47 |
48 | ///
49 | /// Not needed.
50 | ///
51 | public override Task SetTimeout(TimeoutScenario scenario)
52 | {
53 | return Task.FromResult(this.currentTimeoutScenario);
54 | }
55 |
56 | ///
57 | /// Send a message, do not expect a response.
58 | ///
59 | public override Task SendMessage(Message message)
60 | {
61 | StringBuilder builder = new StringBuilder();
62 | this.Logger.AddDebugMessage("Sending message " + message.GetBytes().ToHex());
63 | this.port.Send(message.GetBytes());
64 | return Task.FromResult(true);
65 | }
66 |
67 | ///
68 | /// Try to read an incoming message from the device.
69 | ///
70 | ///
71 | protected async override Task Receive()
72 | {
73 | //List incoming = new List(5000);
74 | byte[] incoming = new byte[5000];
75 | int count = await this.port.Receive(incoming, 0, incoming.Length);
76 | if(count > 0)
77 | {
78 | byte[] sized = new byte[count];
79 | Buffer.BlockCopy(incoming, 0, sized, 0, count);
80 | base.Enqueue(new Message(sized));
81 | }
82 |
83 | return;
84 | }
85 |
86 | ///
87 | /// Set the interface to low (false) or high (true) speed
88 | ///
89 | ///
90 | /// The caller must also tell the PCM to switch speeds
91 | ///
92 | protected override Task SetVpwSpeedInternal(VpwSpeed newSpeed)
93 | {
94 | if (newSpeed == VpwSpeed.Standard)
95 | {
96 | this.Logger.AddDebugMessage("Setting VPW 1X");
97 | }
98 | else
99 | {
100 | this.Logger.AddDebugMessage("Setting VPW 4X");
101 | }
102 |
103 | return Task.FromResult(true);
104 | }
105 |
106 | ///
107 | /// Purse any messages in the incoming-message buffer.
108 | ///
109 | public override void ClearMessageBuffer()
110 | {
111 | this.port.DiscardBuffers();
112 | }
113 | }
114 | }
115 |
--------------------------------------------------------------------------------
/IPCLibrary/Ports/MockAvt852.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace PcmHacking
8 | {
9 | ///
10 | /// This class is just here to enable testing without any actual interface hardware.
11 | ///
12 | ///
13 | /// Eventually the Receive method should return simulated VPW responses.
14 | ///
15 | class MockAvt852 : IPort
16 | {
17 | public const string PortName = "Mock AVT 852";
18 |
19 | private byte[] responseBuffer;
20 |
21 | private int sentSoFar;
22 |
23 | private ILogger logger;
24 |
25 | public MockAvt852(ILogger logger)
26 | {
27 | // this.pcm = new MockPcm(logger);
28 | this.logger = logger;
29 | }
30 |
31 | ///
32 | /// This returns the string that appears in the drop-down list.
33 | ///
34 | public override string ToString()
35 | {
36 | return PortName;
37 | }
38 |
39 | ///
40 | /// Pretend to open a port.
41 | ///
42 | Task IPort.OpenAsync(PortConfiguration configuration)
43 | {
44 | return Task.CompletedTask;
45 | }
46 |
47 | ///
48 | /// Pretend to close a port.
49 | ///
50 | public void Dispose()
51 | {
52 | }
53 |
54 | ///
55 | /// Send bytes to the mock PCM.
56 | ///
57 | Task IPort.Send(byte[] buffer)
58 | {
59 | this.logger.AddDebugMessage("MockAvt852 received: " + buffer.ToHex());
60 |
61 | if (Utility.CompareArrays(buffer, AvtDevice.AVT_RESET.GetBytes()))
62 | {
63 | responseBuffer = AvtDevice.AVT_852_IDLE.GetBytes();
64 | }
65 | else if(Utility.CompareArrays(buffer, AvtDevice.AVT_REQUEST_MODEL.GetBytes()))
66 | {
67 | responseBuffer = new byte[] { 0x93, 0x28, 0x08, 0x52 };
68 | }
69 | else if(Utility.CompareArrays(buffer, AvtDevice.AVT_REQUEST_FIRMWARE.GetBytes()))
70 | {
71 | responseBuffer = new byte[] { 0x92, 0x04, 0x15 };
72 | }
73 | else if(Utility.CompareArrays(buffer, AvtDevice.AVT_ENTER_VPW_MODE.GetBytes()))
74 | {
75 | responseBuffer = AvtDevice.AVT_VPW.GetBytes();
76 | }
77 |
78 | this.sentSoFar = 0;
79 |
80 | return Task.CompletedTask;
81 | }
82 |
83 | ///
84 | /// Receive bytes from the mock PCM.
85 | ///
86 | Task IPort.Receive(byte[] buffer, int offset, int count)
87 | {
88 | int sent = 0;
89 | for (int index = 0; index < count; index++)
90 | {
91 | buffer[offset+index] = this.responseBuffer[this.sentSoFar];
92 | this.sentSoFar++;
93 | sent++;
94 | }
95 |
96 | this.logger.AddDebugMessage("MockAvt852 sending: " + this.responseBuffer.ToHex());
97 |
98 | return Task.FromResult(sent);
99 | }
100 |
101 | ///
102 | /// Discard anything in the input and output buffers.
103 | ///
104 | public Task DiscardBuffers()
105 | {
106 | return Task.FromResult(0);
107 | }
108 |
109 | ///
110 | /// Sets the read timeout.
111 | ///
112 | public void SetTimeout(int milliseconds)
113 | {
114 | }
115 |
116 | ///
117 | /// Indicates the number of bytes waiting in the queue.
118 | ///
119 | Task IPort.GetReceiveQueueSize()
120 | {
121 | // return Task.FromResult(0);
122 | throw new NotImplementedException();
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/IPCLibraryWindowsForms/PcmLibraryWindowsForms.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {4ADB5D87-D4D5-4D12-8681-A9E2D4C52DF6}
8 | Library
9 | Properties
10 | IPCLibraryWindowsForms
11 | PcmLibraryWindowsForms
12 | v4.8
13 | 512
14 | true
15 |
16 |
17 |
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 |
36 | False
37 | Devices\J2534.dll
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | Form
59 |
60 |
61 | DevicePicker.cs
62 |
63 |
64 | Form
65 |
66 |
67 | MainFormBase.cs
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | DevicePicker.cs
81 |
82 |
83 |
84 |
85 | {0b317c5a-e078-4a96-8e7a-00601bca1429}
86 | IPCLibrary
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/IPCLibrary/Misc/Response.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Text;
5 | using System.Threading.Tasks;
6 |
7 | namespace PcmHacking
8 | {
9 | ///
10 | /// These values indicate what went wrong when we were trying to recevie a response from the ECU.
11 | ///
12 | public enum ResponseStatus
13 | {
14 | ///
15 | /// Unspecified error type - try to avoid using this.
16 | ///
17 | Error = 0,
18 |
19 | ///
20 | /// Successful response.
21 | ///
22 | Success = 1,
23 |
24 | ///
25 | /// Response was shorter than expected.
26 | ///
27 | Truncated = 2,
28 |
29 | ///
30 | /// Response contained data that differs from what was expected.
31 | ///
32 | UnexpectedResponse = 3,
33 |
34 | ///
35 | /// No response was received before the timeout expired.
36 | ///
37 | Timeout = 4,
38 |
39 | ///
40 | /// The operation was cancelled by the user.
41 | ///
42 | Cancelled = 5,
43 |
44 | ///
45 | /// The request was refused.
46 | ///
47 | Refused = 6,
48 | }
49 |
50 | ///
51 | /// See the Response[T] class below. This one just contains Response-
52 | /// related methods that can be called without requiring explicit
53 | /// generic parameters.
54 | ///
55 | public class Response
56 | {
57 | ///
58 | /// Create a response with the given status and value.
59 | ///
60 | ///
61 | /// This just makes the calling code simpler because you don't have to specify T explicitly.
62 | ///
63 | public static Response Create(ResponseStatus status, T value, int retryCount = -1)
64 | {
65 | return new Response(status, value, retryCount);
66 | }
67 | }
68 |
69 | ///
70 | /// Response objects contain response data, or an error status and placeholder data.
71 | ///
72 | ///
73 | /// The idea here is to make it easy to communicate values and errors from
74 | /// low-level code up to the UI, using a single object.
75 | ///
76 | public class Response
77 | {
78 | ///
79 | /// Indicates success or gives us some idea of what went wrong.
80 | ///
81 | public ResponseStatus Status { get; private set; }
82 |
83 | ///
84 | /// Indicates how many times the operation had to be retried.
85 | ///
86 | public int RetryCount { get; private set; }
87 |
88 | ///
89 | /// The value that came from the PCM.
90 | ///
91 | ///
92 | /// Lower-level code operates on byte arrays, but higher level code can
93 | /// operate on strings or integers or other data types.
94 | ///
95 | /// If the Status property is not 'Success' then the value of this
96 | /// property should be null, zero, empty string, etc.
97 | ///
98 | public T Value { get; private set; }
99 |
100 | ///
101 | /// Create a Response object with the given status and value.
102 | ///
103 | public Response(ResponseStatus status, T value, int retryCount = -1)
104 | {
105 | this.Status = status;
106 | this.Value = value;
107 | this.RetryCount = retryCount;
108 | }
109 |
110 | ///
111 | /// This is the string that appears when you hover the mouse over something in the debugger.
112 | ///
113 | public override string ToString()
114 | {
115 | return string.Format("{0} {1}", this.Status, this.Value?.ToString());
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/IPCLogger/OldProfiles/Test.profile:
--------------------------------------------------------------------------------
1 | {
2 | "ParameterGroups": [
3 | {
4 | "Dpid": "0xFE",
5 | "Parameters": [
6 | {
7 | "Conversion": {
8 | "Name": "RPM",
9 | "Expression": "x*.25"
10 | },
11 | "Name": "Engine Speed",
12 | "DefineBy": 1,
13 | "ByteCount": 2,
14 | "Address": "0xC"
15 | },
16 | {
17 | "Conversion": {
18 | "Name": "g\/s",
19 | "Expression": "x\/100"
20 | },
21 | "Name": "Mass Air Flow",
22 | "DefineBy": 1,
23 | "ByteCount": 2,
24 | "Address": "0x10"
25 | },
26 | {
27 | "Conversion": {
28 | "Name": "C",
29 | "Expression": "x-40"
30 | },
31 | "Name": "Coolant Temperature",
32 | "DefineBy": 1,
33 | "ByteCount": 1,
34 | "Address": "0x5"
35 | },
36 | {
37 | "Conversion": {
38 | "Name": "C",
39 | "Expression": "x-40"
40 | },
41 | "Name": "Intake Air Temperature",
42 | "DefineBy": 1,
43 | "ByteCount": 1,
44 | "Address": "0xF"
45 | }
46 | ],
47 | "TotalBytes": 6
48 | },
49 | {
50 | "Dpid": "0xFD",
51 | "Parameters": [
52 | {
53 | "Conversion": {
54 | "Name": "psi",
55 | "Expression": "x"
56 | },
57 | "Name": "Engine Oil Pressure",
58 | "DefineBy": 1,
59 | "ByteCount": 1,
60 | "Address": "0x115C"
61 | },
62 | {
63 | "Conversion": {
64 | "Name": "RPM",
65 | "Expression": "x*12.5"
66 | },
67 | "Name": "Target idle speed",
68 | "DefineBy": 1,
69 | "ByteCount": 1,
70 | "Address": "0x1192"
71 | },
72 | {
73 | "Conversion": {
74 | "Name": "percent",
75 | "Expression": "x/2.56"
76 | },
77 | "Name": "target throttle position - fail",
78 | "DefineBy": 1,
79 | "ByteCount": 1,
80 | "Address": "0x1464"
81 | },
82 | {
83 | "Conversion": {
84 | "Name": "%",
85 | "Expression": "x/2.56"
86 | },
87 | "Name": "EGR DC",
88 | "DefineBy": 1,
89 | "ByteCount": 1,
90 | "Address": "0x1172"
91 | },
92 | {
93 | "Conversion": {
94 | "Name": "Seconds",
95 | "Expression": "x"
96 | },
97 | "Name": "Engine Off Time - fail",
98 | "DefineBy": 1,
99 | "ByteCount": 1,
100 | "Address": "0x13B5"
101 | },
102 | {
103 | "Conversion": {
104 | "Name": "C",
105 | "Expression": "(x+40)*(256/192)"
106 | },
107 | "Name": "Transmission Oil Temp",
108 | "DefineBy": 1,
109 | "ByteCount": 1,
110 | "Address": "0x1949"
111 | },
112 | ],
113 | "TotalBytes": 6
114 | }
115 | ]
116 | }
--------------------------------------------------------------------------------
/IPCLogger/General.json.profile:
--------------------------------------------------------------------------------
1 | {
2 | "ParameterGroups": [
3 | {
4 | "Dpid": "0xFE",
5 | "Parameters": [
6 | {
7 | "Conversion": {
8 | "Name": "RPM",
9 | "Expression": "x*.25"
10 | },
11 | "Name": "Engine Speed",
12 | "DefineBy": 1,
13 | "ByteCount": 2,
14 | "Address": "0xC"
15 | },
16 | {
17 | "Conversion": {
18 | "Name": "g\/s",
19 | "Expression": "x\/100"
20 | },
21 | "Name": "Mass Air Flow",
22 | "DefineBy": 1,
23 | "ByteCount": 2,
24 | "Address": "0x10"
25 | },
26 | {
27 | "Conversion": {
28 | "Name": "kpa",
29 | "Expression": "x"
30 | },
31 | "Name": "Manifold Absolute Pressure",
32 | "DefineBy": 1,
33 | "ByteCount": 1,
34 | "Address": "0xB"
35 | },
36 | {
37 | "Conversion": {
38 | "Name": "%",
39 | "Expression": "x\/2.56"
40 | },
41 | "Name": "Throttle Position Sensor",
42 | "DefineBy": 1,
43 | "ByteCount": 1,
44 | "Address": "0x11"
45 | }
46 | ],
47 | "TotalBytes": 6
48 | },
49 | {
50 | "Dpid": "0xFD",
51 | "Parameters": [
52 | {
53 | "Conversion": {
54 | "Name": "C",
55 | "Expression": "x-40"
56 | },
57 | "Name": "Intake Air Temperature",
58 | "DefineBy": 1,
59 | "ByteCount": 1,
60 | "Address": "0xF"
61 | },
62 | {
63 | "Conversion": {
64 | "Name": "C",
65 | "Expression": "x-40"
66 | },
67 | "Name": "Engine Coolant Temperature",
68 | "DefineBy": 1,
69 | "ByteCount": 1,
70 | "Address": "0x5"
71 | },
72 | {
73 | "Conversion": {
74 | "Name": "%",
75 | "Expression": "(x-128)\/1.28"
76 | },
77 | "Name": "Left Long Term Fuel Trim",
78 | "DefineBy": 1,
79 | "ByteCount": 1,
80 | "Address": "0x7"
81 | },
82 | {
83 | "Conversion": {
84 | "Name": "%",
85 | "Expression": "(x-128)\/1.28"
86 | },
87 | "Name": "Right Long Term Fuel Trim",
88 | "DefineBy": 1,
89 | "ByteCount": 1,
90 | "Address": "0x9"
91 | },
92 | {
93 | "Conversion": {
94 | "Name": "Degrees",
95 | "Expression": "(x*256)\/22.5"
96 | },
97 | "Name": "Knock Retard",
98 | "DefineBy": 1,
99 | "ByteCount": 1,
100 | "Address": "0x11A6"
101 | },
102 | {
103 | "Conversion": {
104 | "Name": "AFR",
105 | "Expression": "x*10"
106 | },
107 | "Name": "Target AFR",
108 | "DefineBy": 1,
109 | "ByteCount": 1,
110 | "Address": "0x119E"
111 | }
112 | ],
113 | "TotalBytes": 6
114 | }
115 | ]
116 | }
--------------------------------------------------------------------------------
/VpwExplorer/VpwExplorer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {2B57ABC7-9994-4DB3-9403-B22471A0DDA1}
8 | WinExe
9 | PcmExplorer
10 | PcmExplorer
11 | v4.8
12 | 512
13 | true
14 | true
15 |
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 | Form
54 |
55 |
56 | VpwExplorerMainForm.cs
57 |
58 |
59 | ResXFileCodeGenerator
60 | Resources.Designer.cs
61 | Designer
62 |
63 |
64 | True
65 | Resources.resx
66 | True
67 |
68 |
69 | VpwExplorerMainForm.cs
70 |
71 |
72 | SettingsSingleFileGenerator
73 | Settings.Designer.cs
74 |
75 |
76 | True
77 | Settings.settings
78 | True
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | {4adb5d87-d4d5-4d12-8681-a9e2d4c52df6}
87 | PcmLibraryWindowsForms
88 |
89 |
90 | {0b317c5a-e078-4a96-8e7a-00601bca1429}
91 | PcmLibrary
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/IPCLogger/ParameterDatabase.json:
--------------------------------------------------------------------------------
1 | {
2 | "Parameters": [
3 | {
4 | "Name": "Engine Speed",
5 | "DefineBy": "PID",
6 | "ByteCount": "2",
7 | "Address": "0x000C",
8 | "Conversions": [
9 | {
10 | "Name": "RPM",
11 | "Expression": "x"
12 | }
13 | ]
14 | },
15 | {
16 | "Name": "Mass Air Flow",
17 | "DefineBy": "PID",
18 | "ByteCount": "2",
19 | "Address": "0x0010",
20 | "Conversions": [
21 | {
22 | "Name": "g/a",
23 | "Expression": "x"
24 | }
25 | ]
26 | },
27 | {
28 | "Name": "Manifold Absolute Pressure",
29 | "DefineBy": "PID",
30 | "ByteCount": "1",
31 | "Address": "0x000B",
32 | "Conversions": [
33 | {
34 | "Name": "kpa",
35 | "Expression": "x"
36 | }
37 | ]
38 | },
39 | {
40 | "Name": "Throttle Position Sensor",
41 | "DefineBy": "PID",
42 | "ByteCount": "1",
43 | "Address": "0x0011",
44 | "Conversions": [
45 | {
46 | "Name": "Percent",
47 | "Expression": "x"
48 | }
49 | ]
50 | },
51 | {
52 | "Name": "Intake Air Temperature",
53 | "DefineBy": "PID",
54 | "ByteCount": "1",
55 | "Address": "0x000C",
56 | "Conversions": [
57 | {
58 | "Name": "F",
59 | "Expression": "x"
60 | }
61 | ]
62 | },
63 | {
64 | "Name": "Engine Coolant Temperature",
65 | "DefineBy": "PID",
66 | "ByteCount": "1",
67 | "Address": "0x0005",
68 | "Conversions": [
69 | {
70 | "Name": "F",
71 | "Expression": "x"
72 | }
73 | ]
74 | },
75 | {
76 | "Name": "Transmission Temperature Sensor",
77 | "DefineBy": "PID",
78 | "ByteCount": "1",
79 | "Address": "0x19AD",
80 | "Conversions": [
81 | {
82 | "Name": "v",
83 | "Expression": "x"
84 | }
85 | ]
86 | },
87 | {
88 | "Name": "Vehicle Speed",
89 | "DefineBy": "PID",
90 | "ByteCount": "1",
91 | "Address": "0x000D",
92 | "Conversions": [
93 | {
94 | "Name": "kph",
95 | "Expression": "x"
96 | }
97 | ]
98 | },
99 | {
100 | "Name": "Knock",
101 | "DefineBy": "PID",
102 | "ByteCount": "1",
103 | "Address": "0x11A6",
104 | "Conversions": [
105 | {
106 | "Name": "Count",
107 | "Expression": "x"
108 | }
109 | ]
110 | },
111 | {
112 | "Name": "Fueling Status",
113 | "DefineBy": "PID",
114 | "ByteCount": "1",
115 | "Address": "0x1105",
116 | "Conversions": [
117 | {
118 | "Name": "Status",
119 | "Expression": "x"
120 | }
121 | ]
122 | },
123 | {
124 | "Name": "Left Long Term Fuel Trie",
125 | "DefineBy": "PID",
126 | "ByteCount": "1",
127 | "Address": "0x0007",
128 | "Conversions": [
129 | {
130 | "Name": "%",
131 | "Expression": "x"
132 | }
133 | ]
134 | },
135 | {
136 | "Name": "Right Long Term Fuel Trim",
137 | "DefineBy": "PID",
138 | "ByteCount": "1",
139 | "Address": "0x0009",
140 | "Conversions": [
141 | {
142 | "Name": "%",
143 | "Expression": "x"
144 | }
145 | ]
146 | },
147 | {
148 | "Name": "Target AFR",
149 | "DefineBy": "PID",
150 | "ByteCount": "1",
151 | "Address": "0x119E",
152 | "Conversions": [
153 | {
154 | "Name": "AFR",
155 | "Expression": "x"
156 | }
157 | ]
158 | },
159 | {
160 | "Name": "Battery Voltage",
161 | "DefineBy": "PID",
162 | "ByteCount": "1",
163 | "Address": "0x1141",
164 | "Conversions": [
165 | {
166 | "Name": "Volts",
167 | "Expression": "x"
168 | }
169 | ]
170 | },
171 | {
172 | "Name": "TBD",
173 | "DefineBy": "PID",
174 | "ByteCount": "1",
175 | "Address": "0x1190",
176 | "Conversions": [
177 | {
178 | "Name": "x",
179 | "Expression": "x"
180 | }
181 | ]
182 | },
183 | {
184 | "Name": "Normalized Throttle Position Sensor",
185 | "DefineBy": "PID",
186 | "ByteCount": "1",
187 | "Address": "0x1151",
188 | "Conversions": [
189 | {
190 | "Name": "%",
191 | "Expression": "x"
192 | }
193 | ]
194 | }
195 |
196 | ]
197 | }
198 |
--------------------------------------------------------------------------------
/IPCLogger/O2SensorsAndTrims.json.profile:
--------------------------------------------------------------------------------
1 | {
2 | "ParameterGroups": [
3 | {
4 | "Dpid": "0xFE",
5 | "Parameters": [
6 | {
7 | "Conversion": {
8 | "Name": "RPM",
9 | "Expression": "x*.25"
10 | },
11 | "Name": "Engine Speed",
12 | "DefineBy": 1,
13 | "ByteCount": 2,
14 | "Address": "0xC"
15 | },
16 | {
17 | "Conversion": {
18 | "Name": "g\/s",
19 | "Expression": "x\/100"
20 | },
21 | "Name": "Mass Air Flow",
22 | "DefineBy": 1,
23 | "ByteCount": 2,
24 | "Address": "0x10"
25 | },
26 | {
27 | "Conversion": {
28 | "Name": "Mode",
29 | "Expression": "x"
30 | },
31 | "Name": "Fueling Mode",
32 | "DefineBy": 1,
33 | "ByteCount": 2,
34 | "Address": "0x3"
35 | },
36 | ],
37 | "TotalBytes": 6
38 | },
39 | {
40 | "Dpid": "0xFD",
41 | "Parameters": [
42 | {
43 | "Conversion": {
44 | "Name": "TBD",
45 | "Expression": "x"
46 | },
47 | "Name": "Left Front O2 Sensor Voltage",
48 | "DefineBy": 1,
49 | "ByteCount": 2,
50 | "Address": "0x14"
51 | },
52 |
53 | {
54 | "Conversion": {
55 | "Name": "TBD",
56 | "Expression": "x"
57 | },
58 | "Name": "Right Front O2 Sensor Voltage",
59 | "DefineBy": 1,
60 | "ByteCount": 2,
61 | "Address": "0x16"
62 | },
63 |
64 | {
65 | "Conversion": {
66 | "Name": "Degrees",
67 | "Expression": "x*(100.0/255.0)"
68 | },
69 | "Name": "Throttle Position",
70 | "DefineBy": 1,
71 | "ByteCount": 1,
72 | "Address": "0x11"
73 | },
74 | {
75 | "Conversion": {
76 | "Name": "Degrees",
77 | "Expression": "(x\/2.0) - 64"
78 | },
79 | "Name": "Ignition Timing",
80 | "DefineBy": 1,
81 | "ByteCount": 1,
82 | "Address": "0xE"
83 | },
84 | ],
85 | "TotalBytes": 6
86 | },
87 | {
88 | "Dpid": "0xFC",
89 | "Parameters": [
90 | {
91 | "Conversion": {
92 | "Name": "%",
93 | "Expression": "(x-128)\/1.28"
94 | },
95 | "Name": "Left Long Term Fuel Trim",
96 | "DefineBy": 1,
97 | "ByteCount": 1,
98 | "Address": "0x7"
99 | },
100 | {
101 | "Conversion": {
102 | "Name": "%",
103 | "Expression": "(x-128)\/1.28"
104 | },
105 | "Name": "Left Short Term Fuel Trim",
106 | "DefineBy": 1,
107 | "ByteCount": 1,
108 | "Address": "0x6"
109 | },
110 | {
111 | "Conversion": {
112 | "Name": "C",
113 | "Expression": "x-40"
114 | },
115 | "Name": "Engine Coolant Temperature",
116 | "DefineBy": 1,
117 | "ByteCount": 1,
118 | "Address": "0x5"
119 | },
120 | {
121 | "Conversion": {
122 | "Name": "C",
123 | "Expression": "x-40"
124 | },
125 | "Name": "Intake Air Temperature",
126 | "DefineBy": 1,
127 | "ByteCount": 1,
128 | "Address": "0xF"
129 | },
130 | ],
131 | "TotalBytes": 6
132 | }
133 | ]
134 | }
--------------------------------------------------------------------------------
/IPCHammer/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace PcmHacking.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// A strongly-typed resource class, for looking up localized strings, etc.
17 | ///
18 | // This class was auto-generated by the StronglyTypedResourceBuilder
19 | // class via a tool like ResGen or Visual Studio.
20 | // To add or remove a member, edit your .ResX file then rerun ResGen
21 | // with the /str option, or rebuild your VS project.
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// Returns the cached ResourceManager instance used by this class.
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PcmHacking.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// Overrides the current thread's CurrentUICulture property for all
51 | /// resource lookups using this strongly typed resource class.
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 |
63 | ///
64 | /// Looks up a localized string similar to <?xml version='1.0' encoding='utf-8'?>
65 | ///<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
66 | /// <Profiles>
67 | /// <Profile Name="(Default)" />
68 | /// </Profiles>
69 | /// <Settings />
70 | ///</SettingsFile>
71 | ///.
72 | ///
73 | internal static string Settings {
74 | get {
75 | return ResourceManager.GetString("Settings", resourceCulture);
76 | }
77 | }
78 |
79 | ///
80 | /// Looks up a localized string similar to //------------------------------------------------------------------------------
81 | ///// <auto-generated>
82 | ///// This code was generated by a tool.
83 | ///// Runtime Version:4.0.30319.42000
84 | /////
85 | ///// Changes to this file may cause incorrect behavior and will be lost if
86 | ///// the code is regenerated.
87 | ///// </auto-generated>
88 | /////------------------------------------------------------------------------------
89 | ///
90 | ///namespace PcmHacking.Properties {
91 | ///
92 | ///
93 | /// [global::System.Runtime.CompilerServices.CompilerGener [rest of string was truncated]";.
94 | ///
95 | internal static string Settings_Designer {
96 | get {
97 | return ResourceManager.GetString("Settings_Designer", resourceCulture);
98 | }
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/IPCLibrary/Logging/MathValueProcessor.cs:
--------------------------------------------------------------------------------
1 | using DynamicExpresso;
2 | using System;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Text;
6 |
7 | namespace PcmHacking
8 | {
9 | public class MathValueAndDependencies
10 | {
11 | public MathValue MathValue { get; private set; }
12 | public ProfileParameter XParameter { get; private set; }
13 | public Conversion XConversion { get; private set; }
14 | public ProfileParameter YParameter { get; private set; }
15 | public Conversion YConversion { get; private set; }
16 |
17 | public MathValueAndDependencies(
18 | MathValue mathValue,
19 | ProfileParameter xParameter,
20 | Conversion xConversion,
21 | ProfileParameter yParameter,
22 | Conversion yConversion)
23 | {
24 | this.MathValue = mathValue;
25 | this.XParameter = xParameter;
26 | this.XConversion = xConversion;
27 | this.YParameter = yParameter;
28 | this.YConversion = yConversion;
29 | }
30 | }
31 |
32 | public class MathValueProcessor
33 | {
34 | private readonly LogProfile profile;
35 | private List mathValues;
36 |
37 | public MathValueProcessor(LogProfile profile, MathValueConfiguration mathValueConfiguration)
38 | {
39 | this.profile = profile;
40 | this.mathValues = new List();
41 |
42 | foreach (MathValue mathValue in mathValueConfiguration.MathValues)
43 | {
44 | ProfileParameter xParameter = null;
45 | Conversion xConversion = null;
46 | ProfileParameter yParameter = null;
47 | Conversion yConversion = null;
48 |
49 | foreach (ProfileParameter parameter in this.profile.AllParameters)
50 | {
51 | // TODO: Find the parameter in a configuration file that contains all parameters and conversions,
52 | // pick the appropriate conversion even if it's not what the user chose for this log profile.
53 | if (parameter.Name == mathValue.XParameter)
54 | {
55 | xParameter = parameter;
56 | xConversion = parameter.Conversion;
57 | }
58 |
59 | if (parameter.Name == mathValue.YParameter)
60 | {
61 | yParameter = parameter;
62 | yConversion = parameter.Conversion;
63 | }
64 | }
65 |
66 | if ((xParameter != null) &&
67 | (xConversion != null) &&
68 | (yParameter != null) &&
69 | (yConversion != null))
70 | {
71 | MathValueAndDependencies valueAndDependencies = new MathValueAndDependencies(
72 | mathValue,
73 | xParameter,
74 | xConversion,
75 | yParameter,
76 | yConversion);
77 |
78 | this.mathValues.Add(valueAndDependencies);
79 | }
80 | }
81 | }
82 |
83 | public IEnumerable GetHeaders()
84 | {
85 | return this.mathValues.Select(x => x.MathValue.Name);
86 | }
87 |
88 | public IEnumerable GetMathValues()
89 | {
90 | return this.mathValues.Select(x => x.MathValue);
91 | }
92 |
93 | public IEnumerable GetMathValues(DpidValues dpidValues)
94 | {
95 | List result = new List();
96 | foreach(MathValueAndDependencies value in this.mathValues)
97 | {
98 | double xParameterValue = dpidValues[value.XParameter].RawValue;
99 | Interpreter xConverter = new Interpreter();
100 | xConverter.SetVariable("x", xParameterValue);
101 | double xConverted = xConverter.Eval(value.XConversion.Expression);
102 |
103 | double yParameterValue = dpidValues[value.YParameter].RawValue;
104 | Interpreter yConverter = new Interpreter();
105 | xConverter.SetVariable("x", yParameterValue);
106 | double YConverted = xConverter.Eval(value.YConversion.Expression);
107 |
108 | Interpreter finalConverter = new Interpreter();
109 | finalConverter.SetVariable("x", xConverted);
110 | finalConverter.SetVariable("y", YConverted);
111 | double converted = finalConverter.Eval(value.MathValue.Formula);
112 | result.Add(converted.ToString(value.MathValue.Format));
113 | }
114 |
115 | return result;
116 | }
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/IPCLibrary/Configuration.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace PcmHacking
9 | {
10 | ///
11 | /// Reads and writes configuration settings.
12 | ///
13 | ///
14 | /// Access to underlying configuration storage is implemented separately,
15 | /// so that it can be ported to different systems or tested easily.
16 | ///
17 | public static class Configuration
18 | {
19 | ///
20 | /// The code that actually reads and writes individual configuration values.
21 | ///
22 | private static ConfigurationAccessor accessor;
23 |
24 | ///
25 | /// Allows abstracting the storage for configuration settings.
26 | ///
27 | public abstract class ConfigurationAccessor
28 | {
29 | public abstract string Read(string keyName);
30 | public abstract void Write(string keyName, string value);
31 | }
32 |
33 | ///
34 | /// Configurations setting key names.
35 | ///
36 | public class Constants
37 | {
38 | public const string DeviceCategory = "DeviceCategory";
39 |
40 | public const string SerialPort = "SerialPort";
41 |
42 | public const string SerialPortDeviceType = "SerialPortDeviceType";
43 |
44 | public const string J2534DeviceType = "J2534DeviceType";
45 |
46 | public const string DeviceCategorySerial = "Serial";
47 |
48 | public const string DeviceCategoryJ2534 = "J2534";
49 |
50 | public const string Enable4xReadWrite = "Enable4xReadWrite";
51 | }
52 |
53 | ///
54 | /// Device category (Serial, J2534, etc)
55 | ///
56 | public static string DeviceCategory
57 | {
58 | get
59 | {
60 | return Read(Constants.DeviceCategory);
61 | }
62 |
63 | set
64 | {
65 | Write(Constants.DeviceCategory, value);
66 | }
67 | }
68 |
69 | ///
70 | /// Serial port name.
71 | ///
72 | public static string SerialPort
73 | {
74 | get
75 | {
76 | return Read(Constants.SerialPort);
77 | }
78 |
79 | set
80 | {
81 | Write(Constants.SerialPort, value);
82 | }
83 | }
84 |
85 | ///
86 | /// Serial device type.
87 | ///
88 | public static string SerialPortDeviceType
89 | {
90 | get
91 | {
92 | return Read(Constants.SerialPortDeviceType);
93 | }
94 |
95 | set
96 | {
97 | Write(Constants.SerialPortDeviceType, value);
98 | }
99 | }
100 |
101 | ///
102 | /// J2534 device type.
103 | ///
104 | public static string J2534DeviceType
105 | {
106 | get
107 | {
108 | return Read(Constants.J2534DeviceType);
109 | }
110 |
111 | set
112 | {
113 | Write(Constants.J2534DeviceType, value);
114 | }
115 | }
116 |
117 | ///
118 | /// J2534 device type.
119 | ///
120 | public static bool Enable4xReadWrite
121 | {
122 | get
123 | {
124 | string raw = Read(Constants.Enable4xReadWrite);
125 | bool result;
126 | if (bool.TryParse(raw, out result))
127 | {
128 | return result;
129 | }
130 |
131 | return true;
132 | }
133 |
134 | set
135 | {
136 | Write(Constants.Enable4xReadWrite, value.ToString());
137 | }
138 | }
139 |
140 | ///
141 | /// Set the configuration accessor to use for this process.
142 | ///
143 | public static void SetAccessor(ConfigurationAccessor accessor)
144 | {
145 | Configuration.accessor = accessor;
146 | }
147 |
148 | ///
149 | /// Read a single configuration setting.
150 | ///
151 | public static string Read(string key)
152 | {
153 | return accessor.Read(key);
154 | }
155 |
156 | ///
157 | /// Write a single configuration setting.
158 | ///
159 | public static void Write(string key, string value)
160 | {
161 | accessor.Write(key, value);
162 | }
163 | }
164 | }
165 |
--------------------------------------------------------------------------------
/IPCLogger/PcmLogger.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {6A473C4F-A1A3-4CFB-8167-13F4064C1639}
8 | WinExe
9 | IPCLogger
10 | PcmLogger
11 | v4.8
12 | 512
13 | true
14 | true
15 |
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 |
27 |
28 | AnyCPU
29 | pdbonly
30 | true
31 | bin\Release\
32 | TRACE
33 | prompt
34 | 4
35 |
36 |
37 |
38 | ..\packages\DynamicExpresso.Core.2.3.1\lib\net461\DynamicExpresso.Core.dll
39 |
40 |
41 | ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | Form
59 |
60 |
61 | MainForm.cs
62 |
63 |
64 |
65 |
66 | MainForm.cs
67 |
68 |
69 | ResXFileCodeGenerator
70 | Resources.Designer.cs
71 | Designer
72 |
73 |
74 | True
75 | Resources.resx
76 | True
77 |
78 |
79 | PreserveNewest
80 |
81 |
82 |
83 | SettingsSingleFileGenerator
84 | Settings.Designer.cs
85 |
86 |
87 | True
88 | Settings.settings
89 | True
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | {4adb5d87-d4d5-4d12-8681-a9e2d4c52df6}
98 | IPCLibraryWindowsForms
99 |
100 |
101 | {0b317c5a-e078-4a96-8e7a-00601bca1429}
102 | IPCLibrary
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/IPCLibrary/Messages/Protocol.Security.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace PcmHacking
6 | {
7 | public partial class Protocol
8 | {
9 | class Security
10 | {
11 | public const byte Denied = 0x33; // Security Access Denied
12 | public const byte Allowed = 0x34; // Security Access Allowed
13 | public const byte Invalid = 0x35; // Invalid Key
14 | public const byte TooMany = 0x36; // Exceed Number of Attempts
15 | public const byte Delay = 0x37; // Required Time Delay Not Expired
16 | }
17 |
18 |
19 | ///
20 | /// Create a request to retrieve a 'seed' value from the PCM
21 | ///
22 | public Message CreateSeedRequest()
23 | {
24 | byte[] Bytes = new byte[] { Priority.Physical0, DeviceId.Pcm, DeviceId.Tool, Mode.Seed, SubMode.GetSeed };
25 | return new Message(Bytes);
26 | }
27 |
28 |
29 | ///
30 | /// Parse the response to a seed request.
31 | ///
32 | public Response ParseSeed(byte[] response)
33 | {
34 | ResponseStatus status;
35 | UInt16 result = 0;
36 |
37 | byte[] unlocked = { Priority.Physical0, 0x70, DeviceId.Pcm, Mode.Seed + Mode.Response, 0x01, 0x37 };
38 | byte[] seed = new byte[] { Priority.Physical0, DeviceId.Tool, DeviceId.Pcm, Mode.Seed + Mode.Response, 0x01, };
39 |
40 | if (TryVerifyInitialBytes(response, unlocked, out status))
41 | {
42 | status = ResponseStatus.Success;
43 | return Response.Create(ResponseStatus.Success, result);
44 | }
45 |
46 | if (!TryVerifyInitialBytes(response, seed, out status))
47 | {
48 | return Response.Create(ResponseStatus.Error, result);
49 | }
50 |
51 | // Let's not reverse endianess
52 | result = (UInt16)((response[5] << 8) | response[6]);
53 |
54 | return Response.Create(ResponseStatus.Success, result);
55 | }
56 |
57 | ///
58 | /// Create a request to send a 'key' value to the PCM
59 | ///
60 | public Message CreateUnlockRequest(UInt16 Key)
61 | {
62 | byte KeyHigh = (byte)((Key & 0xFF00) >> 8);
63 | byte KeyLow = (byte)(Key & 0xFF);
64 | byte[] Bytes = new byte[] { Priority.Physical0, DeviceId.Pcm, DeviceId.Tool, Mode.Seed, SubMode.SendKey, KeyHigh, KeyLow };
65 | return new Message(Bytes);
66 | }
67 |
68 | ///
69 | /// Determine whether we were able to unlock the PCM.
70 | ///
71 | public Response ParseUnlockResponse(byte[] unlockResponse, out string errorMessage)
72 | {
73 | if (unlockResponse.Length < 6)
74 | {
75 | errorMessage = $"Unlock response truncated, expected 6 bytes, got {unlockResponse.Length} bytes.";
76 | return Response.Create(ResponseStatus.UnexpectedResponse, false);
77 | }
78 |
79 | byte unlockCode = unlockResponse[5];
80 |
81 | switch (unlockCode)
82 | {
83 | case Security.Allowed:
84 | errorMessage = null;
85 | return Response.Create(ResponseStatus.Success, true);
86 |
87 | case Security.Denied:
88 | errorMessage = $"The IPC refused to unlock";
89 | return Response.Create(ResponseStatus.Error, false);
90 |
91 | case Security.Invalid:
92 | errorMessage = $"The IPC didn't accept the unlock key value";
93 | return Response.Create(ResponseStatus.Error, false);
94 |
95 | case Security.TooMany:
96 | errorMessage = $"The IPC did not accept the key - too many attempts";
97 | return Response.Create(ResponseStatus.Error, false);
98 |
99 | case Security.Delay:
100 | errorMessage = $"The IPC is enforcing timeout lock";
101 | return Response.Create(ResponseStatus.Timeout, false);
102 |
103 | default:
104 | errorMessage = $"Unknown unlock response code: 0x{unlockCode:X2}";
105 | return Response.Create(ResponseStatus.UnexpectedResponse, false);
106 | }
107 | }
108 |
109 | ///
110 | /// Indicates whether or not the reponse indicates that the PCM is unlocked.
111 | ///
112 | public bool IsUnlocked(byte[] response)
113 | {
114 | ResponseStatus status;
115 | byte[] unlocked = { Priority.Physical0, DeviceId.Tool, DeviceId.Pcm, Mode.Seed + Mode.Response, 0x01, 0x34 };
116 |
117 | if (TryVerifyInitialBytes(response, unlocked, out status))
118 | {
119 | return true;
120 | }
121 |
122 | return false;
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/IPCHammer/DialogBoxes/DelayDialogBox.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace PcmHacking
2 | {
3 | partial class DelayDialogBox
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Windows Form Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DelayDialogBox));
32 | this.explanation = new System.Windows.Forms.Label();
33 | this.continueButton = new System.Windows.Forms.Button();
34 | this.cancelButton = new System.Windows.Forms.Button();
35 | this.countdown = new System.Windows.Forms.Label();
36 | this.SuspendLayout();
37 | //
38 | // explanation
39 | //
40 | this.explanation.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
41 | | System.Windows.Forms.AnchorStyles.Left)
42 | | System.Windows.Forms.AnchorStyles.Right)));
43 | this.explanation.Location = new System.Drawing.Point(12, 9);
44 | this.explanation.Name = "explanation";
45 | this.explanation.Size = new System.Drawing.Size(407, 117);
46 | this.explanation.TabIndex = 0;
47 | this.explanation.Text = resources.GetString("explanation.Text");
48 | //
49 | // continueButton
50 | //
51 | this.continueButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
52 | this.continueButton.Location = new System.Drawing.Point(163, 167);
53 | this.continueButton.Name = "continueButton";
54 | this.continueButton.Size = new System.Drawing.Size(125, 25);
55 | this.continueButton.TabIndex = 1;
56 | this.continueButton.Text = "&Continue";
57 | this.continueButton.UseVisualStyleBackColor = true;
58 | this.continueButton.Click += new System.EventHandler(this.continueButton_Click);
59 | //
60 | // cancelButton
61 | //
62 | this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
63 | this.cancelButton.Location = new System.Drawing.Point(294, 167);
64 | this.cancelButton.Name = "cancelButton";
65 | this.cancelButton.Size = new System.Drawing.Size(125, 25);
66 | this.cancelButton.TabIndex = 2;
67 | this.cancelButton.Text = "&Abort";
68 | this.cancelButton.UseVisualStyleBackColor = true;
69 | this.cancelButton.Click += new System.EventHandler(this.cancelButton_Click);
70 | //
71 | // countdown
72 | //
73 | this.countdown.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
74 | | System.Windows.Forms.AnchorStyles.Right)));
75 | this.countdown.Location = new System.Drawing.Point(12, 126);
76 | this.countdown.Name = "countdown";
77 | this.countdown.Size = new System.Drawing.Size(407, 31);
78 | this.countdown.TabIndex = 3;
79 | this.countdown.Text = "X seconds remaining...";
80 | this.countdown.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
81 | //
82 | // DelayDialogBox
83 | //
84 | this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
85 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
86 | this.ClientSize = new System.Drawing.Size(431, 204);
87 | this.Controls.Add(this.countdown);
88 | this.Controls.Add(this.cancelButton);
89 | this.Controls.Add(this.continueButton);
90 | this.Controls.Add(this.explanation);
91 | this.Name = "DelayDialogBox";
92 | this.Text = "Sorry To Interrupt...";
93 | this.Load += new System.EventHandler(this.DelayDialogBox_Load);
94 | this.ResumeLayout(false);
95 |
96 | }
97 |
98 | #endregion
99 |
100 | private System.Windows.Forms.Label explanation;
101 | private System.Windows.Forms.Button continueButton;
102 | private System.Windows.Forms.Button cancelButton;
103 | private System.Windows.Forms.Label countdown;
104 | }
105 | }
--------------------------------------------------------------------------------
/Tests/Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {0AA6F273-995D-4ADE-8CBB-DB1B6E8A0FCE}
8 | Library
9 | Properties
10 | Tests
11 | Tests
12 | v4.8
13 | 512
14 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
15 | 15.0
16 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
17 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
18 | False
19 | UnitTest
20 |
21 |
22 |
23 |
24 |
25 | true
26 | full
27 | false
28 | bin\Debug\
29 | DEBUG;TRACE
30 | prompt
31 | 4
32 | false
33 |
34 |
35 | pdbonly
36 | true
37 | bin\Release\
38 | TRACE
39 | prompt
40 | 4
41 |
42 |
43 |
44 | ..\packages\DynamicExpresso.Core.2.3.1\lib\net461\DynamicExpresso.Core.dll
45 |
46 |
47 |
48 | ..\packages\MSTest.TestFramework.1.1.18\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll
49 |
50 |
51 | ..\packages\MSTest.TestFramework.1.1.18\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 | {0b317c5a-e078-4a96-8e7a-00601bca1429}
73 | PcmLibrary
74 |
75 |
76 |
77 |
78 |
79 |
80 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
81 |
82 |
83 |
84 |
85 |
86 |
--------------------------------------------------------------------------------
/IPCLibraryWindowsForms/Ports/StandardPort.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO.Ports;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace PcmHacking
9 | {
10 | ///
11 | /// This class is responsible for sending and receiving data over a serial port.
12 | /// I would have called it 'SerialPort' but that name was already taken...
13 | ///
14 | class StandardPort : IPort
15 | {
16 | private string name;
17 | private SerialPort port;
18 |
19 | ///
20 | /// This is an experiment that did not end well the first time, but I still think it should work.
21 | ///
22 | // private Action