├── .gitattributes ├── .gitignore ├── IPCApps.sln ├── IPCHammer ├── 0411_256px.ico ├── 0411_256pxold.ico ├── App.config ├── DialogBoxes │ ├── A7k140mphForm.cs │ ├── A7k140mphForm.designer.cs │ ├── A7k140mphForm.resx │ ├── DelayDialogBox.Designer.cs │ ├── DelayDialogBox.cs │ ├── DelayDialogBox.resx │ ├── MileageForm.Designer.cs │ ├── MileageForm.cs │ ├── MileageForm.resx │ ├── OptionsForm.Designer.cs │ ├── OptionsForm.cs │ ├── OptionsForm.resx │ ├── StepperForm.Designer.cs │ ├── StepperForm.cs │ ├── StepperForm.resx │ ├── VinForm.Designer.cs │ ├── VinForm.cs │ └── VinForm.resx ├── IpcHammer.csproj ├── J2534.dll ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── credits.html ├── help.html ├── packages.config └── start.txt ├── IPCLibrary ├── CKernelReader.cs ├── CKernelVerifier.cs ├── CKernelWriter.cs ├── CKernelWriterIpc.cs ├── Configuration.cs ├── Devices │ ├── AllProDeviceImplementation.cs │ ├── AvtDevice.cs │ ├── AvtDevice2.cs │ ├── Device.cs │ ├── ElmDevice.cs │ ├── ElmDeviceImplementation.cs │ ├── MockDevice.cs │ ├── OBDXProDevice.cs │ ├── ScanToolDeviceImplementation.cs │ └── SerialDevice.cs ├── Logging │ ├── LogFileWriter.cs │ ├── LogProfile.cs │ ├── LogProfileReader.cs │ ├── LogProfileWriter.cs │ ├── LogProfileXmlReader.cs │ ├── LogProfileXmlWriter.cs │ ├── LogRowParser.cs │ ├── Logger.cs │ ├── MathValueConfiguration.cs │ ├── MathValueProcessor.cs │ └── ProfileAndMath.cs ├── Messages │ ├── BlockId.cs │ ├── Message.cs │ ├── Protocol.Kernel.cs │ ├── Protocol.Logging.cs │ ├── Protocol.Misc.cs │ ├── Protocol.Properties.cs │ ├── Protocol.ReadWrite.cs │ ├── Protocol.Security.cs │ ├── Protocol.Speed.cs │ ├── Protocol.Utility.cs │ ├── Protocol.cs │ └── VPW.cs ├── Misc │ ├── AwayMode.cs │ ├── Crc.cs │ ├── Exceptions.cs │ ├── FileValidator.cs │ ├── FileValidator1.cs │ ├── FlashChip.cs │ ├── HttpServer.cs │ ├── ILogger.cs │ ├── KeyAlgorithm.cs │ ├── MockPcm.cs │ ├── OsInfo.cs │ ├── PcmInfo.cs │ ├── Query.cs │ ├── Response.cs │ ├── ToolPresentNotifier.cs │ └── Utility.cs ├── PcmLibrary.csproj ├── Ports │ ├── IPort.cs │ ├── MockAvt852.cs │ └── MockPort.cs ├── Properties │ └── launchSettings.json ├── Vehicle.Kernel.cs ├── Vehicle.Logging.cs ├── Vehicle.Properties.cs ├── Vehicle.TestKernel.cs └── Vehicle.cs ├── IPCLibraryWindowsForms ├── ContentLoader.cs ├── Devices │ ├── DeviceFactory.cs │ ├── J2534.dll │ ├── J2534Device.cs │ └── J2534DeviceFinder.cs ├── DialogBoxes │ ├── DevicePicker.Designer.cs │ ├── DevicePicker.cs │ └── DevicePicker.resx ├── MainFormBase.Designer.cs ├── MainFormBase.cs ├── PcmLibraryWindowsForms.csproj ├── Ports │ ├── HttpPort.cs │ ├── PortDiscovery.cs │ └── StandardPort.cs ├── Properties │ └── AssemblyInfo.cs └── WinFormsConfigurationAccessor.cs ├── IPCLogger ├── App.config ├── Example1.xml.profile ├── Example2.xml.profile ├── Example3.xml.profile ├── Failed.json ├── General.json.profile ├── General.xml.profile ├── Idle.json.profile ├── Idle.xml.profile ├── IdleAir.xml.profile ├── IdlePID.xml.profile ├── LoggerConfiguration.cs ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── MathValues.configuration ├── Memory.json.profile ├── Memory.xml.profile ├── O2SensorsAndTrims.json.profile ├── O2SensorsAndTrims.xml.profile ├── OldProfiles │ ├── Idle2.profile │ └── Test.profile ├── ParameterDatabase.json ├── Parameters.12593358.xml ├── Parameters.SAE.xml ├── PcmLogger.csproj ├── Program.cs ├── Properties │ ├── AssemblyInfo.cs │ ├── Resources.Designer.cs │ ├── Resources.resx │ ├── Settings.Designer.cs │ └── Settings.settings ├── clusterram.xml.profile ├── clusterram.xml.profile.txt └── packages.config ├── README.md ├── Tests ├── AvtTests.cs ├── MathTests.cs ├── MockLogger.cs ├── Properties │ └── AssemblyInfo.cs ├── ScanToolTests.cs ├── TestLogger.cs ├── TestPort.cs ├── TestScenarios.cs ├── Tests.csproj ├── UtilityTests.cs └── packages.config └── VpwExplorer ├── App.config ├── Program.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs └── Settings.settings ├── VpwExplorer.csproj ├── VpwExplorerMainForm.Designer.cs ├── VpwExplorerMainForm.cs └── VpwExplorerMainForm.resx /.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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /IPCHammer/0411_256px.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikebb203/IPC-Hammer/5e637eda58719271c5707a588a7cd8978085d21c/IPCHammer/0411_256px.ico -------------------------------------------------------------------------------- /IPCHammer/0411_256pxold.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikebb203/IPC-Hammer/5e637eda58719271c5707a588a7cd8978085d21c/IPCHammer/0411_256pxold.ico -------------------------------------------------------------------------------- /IPCHammer/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /IPCHammer/J2534.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikebb203/IPC-Hammer/5e637eda58719271c5707a588a7cd8978085d21c/IPCHammer/J2534.dll -------------------------------------------------------------------------------- /IPCHammer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace PcmHacking 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Configuration.SetAccessor(new WinFormsConfigurationAccessor()); 18 | 19 | Application.EnableVisualStyles(); 20 | Application.SetCompatibleTextRenderingDefault(false); 21 | Application.Run(new MainForm()); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /IPCHammer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("IPC Hammer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("IPC Hammer")] 13 | [assembly: AssemblyCopyright("Copyright © 2021")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a6b28831-a16f-48f3-8c48-9b02cf0b6678")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /IPCHammer/Properties/Settings.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 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /IPCHammer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /IPCHammer/credits.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | 12 |

Who To Thank For What

13 | 14 |

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 | -------------------------------------------------------------------------------- /IPCHammer/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /IPCHammer/start.txt: -------------------------------------------------------------------------------- 1 | Thanks for using IPC Hammer. -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/Devices/SerialDevice.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 | /// Base class for serial-port devices. 11 | /// 12 | public abstract class SerialDevice : Device 13 | { 14 | /// 15 | /// The serial port this device will use. 16 | /// 17 | protected IPort Port { get; private set; } 18 | 19 | /// 20 | /// Constructor. 21 | /// 22 | public SerialDevice(IPort port, ILogger logger) : base(logger) 23 | { 24 | this.Port = port; 25 | } 26 | 27 | /// 28 | /// Disposer. 29 | /// 30 | protected override void Dispose(bool disposing) 31 | { 32 | if (disposing) 33 | { 34 | if (this.Port != null) 35 | { 36 | this.Port.Dispose(); 37 | } 38 | } 39 | } 40 | 41 | /// 42 | /// Save configuration settings to app.config. 43 | /// 44 | public void UpdateAppConfiguration() 45 | { 46 | Configuration.DeviceCategory = Configuration.Constants.DeviceCategorySerial; 47 | Configuration.SerialPort = this.Port.ToString(); 48 | Configuration.SerialPortDeviceType = this.GetDeviceType(); 49 | } 50 | 51 | /// 52 | /// Generate a descriptive string for this device and the port that it is using. 53 | /// 54 | public override string ToString() 55 | { 56 | return this.GetDeviceType() + " on " + this.Port.ToString(); 57 | } 58 | 59 | /// 60 | /// Return a descriptive string for this type of hardware. 61 | /// 62 | public abstract string GetDeviceType(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /IPCLibrary/Logging/LogFileWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace PcmHacking 8 | { 9 | /// 10 | /// Writes .csv files of log data. 11 | /// 12 | public class LogFileWriter 13 | { 14 | private StreamWriter writer; 15 | private DateTime startTime; 16 | 17 | /// 18 | /// Constructor. 19 | /// 20 | public LogFileWriter(StreamWriter writer) 21 | { 22 | this.writer = writer; 23 | } 24 | 25 | /// 26 | /// Call this once to write the file header. 27 | /// 28 | public async Task WriteHeader(IEnumerable columnNames) 29 | { 30 | this.startTime = DateTime.Now; 31 | string text = string.Join(", ", columnNames); 32 | await this.writer.WriteAsync("Clock Time, Elapsed Time, "); 33 | await this.writer.WriteLineAsync(text); 34 | } 35 | 36 | /// 37 | /// Call this to write each new row to the file. 38 | /// 39 | public void WriteLine(IEnumerable values) 40 | { 41 | lock (this.writer) 42 | { 43 | this.writer.Write(DateTime.Now.ToString("u")); 44 | this.writer.Write(", "); 45 | this.writer.Write(DateTime.Now.Subtract(this.startTime).ToString()); 46 | this.writer.Write(", "); 47 | this.writer.WriteLine(string.Join(", ", values)); 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /IPCLibrary/Logging/LogProfileReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Newtonsoft.Json; 7 | 8 | namespace PcmHacking 9 | { 10 | public class LogProfileReader 11 | { 12 | private Stream stream; 13 | 14 | public LogProfileReader(Stream stream) 15 | { 16 | this.stream = stream; 17 | } 18 | 19 | public async Task ReadAsync() 20 | { 21 | using (StreamReader reader = new StreamReader(stream)) 22 | { 23 | string json = await reader.ReadToEndAsync(); 24 | return JsonConvert.DeserializeObject(json, new UnsignedHexValueConverter()); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /IPCLibrary/Logging/LogProfileWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using Newtonsoft.Json; 7 | 8 | namespace PcmHacking 9 | { 10 | public class LogProfileWriter 11 | { 12 | private Stream stream; 13 | 14 | public LogProfileWriter(Stream stream) 15 | { 16 | this.stream = stream; 17 | } 18 | 19 | public async Task WriteAsync(LogProfile profile) 20 | { 21 | using (StreamWriter writer = new StreamWriter(stream)) 22 | { 23 | string json = JsonConvert.SerializeObject(profile, new UnsignedHexValueConverter()); 24 | await writer.WriteLineAsync(json); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /IPCLibrary/Logging/LogProfileXmlReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml.Serialization; 7 | 8 | namespace PcmHacking 9 | { 10 | public class LogProfileXmlReader 11 | { 12 | private Stream stream; 13 | 14 | public LogProfileXmlReader(Stream stream) 15 | { 16 | this.stream = stream; 17 | } 18 | 19 | public LogProfile Read() 20 | { 21 | XmlSerializer serializer = new XmlSerializer(typeof(LogProfile)); 22 | return (LogProfile) serializer.Deserialize(this.stream); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /IPCLibrary/Logging/LogProfileXmlWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using System.Xml.Serialization; 7 | using Newtonsoft.Json; 8 | 9 | namespace PcmHacking 10 | { 11 | public class LogProfileXmlWriter 12 | { 13 | private Stream stream; 14 | 15 | public LogProfileXmlWriter(Stream stream) 16 | { 17 | this.stream = stream; 18 | } 19 | 20 | public void Write(LogProfile profile) 21 | { 22 | XmlSerializer serializer = new XmlSerializer(typeof(LogProfile)); 23 | serializer.Serialize(stream, profile); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/Logging/ProfileAndMath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace PcmHacking 7 | { 8 | public class LogProfileAndMath 9 | { 10 | private readonly LogProfile profile; 11 | private readonly MathValueConfiguration mathValueConfiguration; 12 | private readonly MathValueProcessor mathValueProcessor; 13 | 14 | public LogProfile Profile 15 | { 16 | get 17 | { 18 | return this.profile; 19 | } 20 | } 21 | 22 | public MathValueProcessor MathValueProcessor 23 | { 24 | get 25 | { 26 | return this.mathValueProcessor; 27 | } 28 | } 29 | 30 | public LogProfileAndMath(LogProfile profile, MathValueConfiguration mathValueConfiguration) 31 | { 32 | this.profile = profile; 33 | this.mathValueConfiguration = mathValueConfiguration; 34 | this.mathValueProcessor = new MathValueProcessor( 35 | this.profile, 36 | this.mathValueConfiguration); 37 | } 38 | 39 | public IEnumerable GetColumnNames() 40 | { 41 | return this.profile.GetParameterNames().Concat(this.mathValueProcessor.GetHeaders()); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/Messages/Protocol.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PcmHacking 6 | { 7 | /// 8 | /// This class is responsible for generating and parsing the messages that the app exchanges with the PCM. 9 | /// 10 | /// 11 | /// The messages generated by this class are byte-for-byte exactly what the PCM 12 | /// receives, with the exception of the CRC byte at the end. CRC bytes must be 13 | /// added by the currently-selected Device class if the actual device doesn't add 14 | /// the CRC byte automatically. 15 | /// 16 | /// Some devices will require these messages to be translated according to the specific 17 | /// device's protocol - that too is the job of the currently-selected Device class. 18 | /// 19 | public partial class Protocol 20 | { 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /IPCLibrary/Misc/Exceptions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace PcmHacking 6 | { 7 | public class DataTruncatedException : Exception 8 | { 9 | public DataTruncatedException(string message = "Data Truncated"): base (message) 10 | { 11 | } 12 | } 13 | 14 | public class UnsupportedFormatException: Exception 15 | { 16 | public UnsupportedFormatException(string message = "Data format not supported."): base(message) 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /IPCLibrary/Misc/ILogger.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 interface allows other classes to send user-friendly status messages and 11 | /// developer-oriented debug messages to the UI. 12 | /// 13 | public interface ILogger 14 | { 15 | /// 16 | /// Add a message to the 'results' pane of the UI. 17 | /// 18 | /// 19 | /// These messages should be things that end users will understand. 20 | /// They should describe major operations, not sequences of bytes. 21 | /// 22 | void AddUserMessage(string message); 23 | 24 | /// 25 | /// Add a message to the 'debug' pane of the UI. 26 | /// 27 | /// These should be things that we can use to diagnose errors. 28 | /// Feel free to include raw sequences of bytes. 29 | void AddDebugMessage(string message); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/PcmLibrary.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | PcmHacking 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /IPCLibrary/Ports/IPort.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 | /// The IPort implementations encapsulate the differences between serial 12 | /// ports, J2534 passthrough devices, and whatever else we end up using. 13 | /// 14 | public interface IPort : IDisposable 15 | { 16 | /// 17 | /// Open the port. 18 | /// 19 | Task OpenAsync(PortConfiguration configuration); 20 | 21 | /// 22 | /// Send a sequence of bytes. 23 | /// 24 | Task Send(byte[] buffer); 25 | 26 | /// 27 | /// Receive a buffer of bytes. 28 | /// 29 | Task Receive(byte[] buffer, int offset, int count); 30 | 31 | /// 32 | /// Discard anything in the input and output buffers. 33 | /// 34 | Task DiscardBuffers(); 35 | 36 | /// 37 | /// Indicates the number of bytes waiting in the receive queue. 38 | /// 39 | Task GetReceiveQueueSize(); 40 | 41 | /// 42 | /// Sets the timeout for incoming messages; 43 | /// 44 | void SetTimeout(int milliseconds); 45 | } 46 | 47 | public class PortConfiguration 48 | { 49 | } 50 | 51 | public class SerialPortConfiguration : PortConfiguration 52 | { 53 | public int BaudRate { get; set; } 54 | public int Timeout { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "PcmLibrary": { 4 | "commandName": "Project" 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /IPCLibraryWindowsForms/Devices/J2534.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikebb203/IPC-Hammer/5e637eda58719271c5707a588a7cd8978085d21c/IPCLibraryWindowsForms/Devices/J2534.dll -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /IPCLibraryWindowsForms/MainFormBase.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace PcmHacking 2 | { 3 | using System.Windows.Forms; 4 | 5 | partial class MainFormBase : Form 6 | { 7 | /// 8 | /// Required designer variable. 9 | /// 10 | private System.ComponentModel.IContainer components = null; 11 | 12 | /// 13 | /// Clean up any resources being used. 14 | /// 15 | /// true if managed resources should be disposed; otherwise, false. 16 | protected override void Dispose(bool disposing) 17 | { 18 | if (disposing && (components != null)) 19 | { 20 | components.Dispose(); 21 | } 22 | base.Dispose(disposing); 23 | } 24 | 25 | #region Windows Form Designer generated code 26 | 27 | /// 28 | /// Required method for Designer support - do not modify 29 | /// the contents of this method with the code editor. 30 | /// 31 | private void InitializeComponent() 32 | { 33 | this.components = new System.ComponentModel.Container(); 34 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 35 | this.ClientSize = new System.Drawing.Size(800, 450); 36 | this.Text = "MainFormBase"; 37 | } 38 | 39 | #endregion 40 | } 41 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 dataReceivedCallback; 23 | 24 | /// 25 | /// Constructor. 26 | /// 27 | public StandardPort(string name) 28 | { 29 | this.name = name; 30 | } 31 | 32 | /// 33 | /// This returns the string that appears in the drop-down list. 34 | /// 35 | public override string ToString() 36 | { 37 | return this.name; 38 | } 39 | 40 | /// 41 | /// Open the serial port. 42 | /// 43 | Task IPort.OpenAsync(PortConfiguration configuration) 44 | { 45 | // Clean up the existing SerialPort object, if we have one. 46 | if (this.port != null) 47 | { 48 | this.port.Dispose(); 49 | } 50 | SerialPortConfiguration config = configuration as SerialPortConfiguration; 51 | this.port = new SerialPort(this.name); 52 | this.port.BaudRate = config.BaudRate; 53 | this.port.DataBits = 8; 54 | this.port.Parity = Parity.None; 55 | this.port.StopBits = StopBits.One; 56 | if (config.Timeout == 0) config.Timeout = 1000; // default to 1 second but allow override. 57 | this.port.ReadTimeout = config.Timeout; 58 | 59 | if (this.port.IsOpen == true) this.port.Close(); 60 | 61 | /* if (config.DataReceived != null) 62 | { 63 | this.dataReceivedCallback = config.DataReceived; 64 | this.port.DataReceived += this.DataReceived; 65 | } 66 | */ 67 | 68 | this.port.Open(); 69 | 70 | // This line must come AFTER the call to port.Open(). 71 | // Attempting to use the BaseStream member will throw an exception otherwise. 72 | // 73 | // However, even after setting the BaseStream.ReadTimout property, calls to 74 | // BaseStream.ReadAsync will hang indefinitely. It turns out that you have 75 | // to implement the timeout yourself if you use the async approach. 76 | this.port.BaseStream.ReadTimeout = this.port.ReadTimeout; 77 | 78 | return Task.CompletedTask; 79 | } 80 | 81 | /// 82 | /// Close the serial port. 83 | /// 84 | public void Dispose() 85 | { 86 | if (this.port != null) 87 | { 88 | this.port.Dispose(); 89 | this.port = null; 90 | } 91 | } 92 | 93 | /// 94 | /// Send a sequence of bytes over the serial port. 95 | /// 96 | async Task IPort.Send(byte[] buffer) 97 | { 98 | 99 | await this.port.BaseStream.WriteAsync(buffer, 0, buffer.Length).AwaitWithTimeout(TimeSpan.FromSeconds(5)); 100 | 101 | // This flush is probably not strictly necessary, but just in case... 102 | await this.port.BaseStream.FlushAsync().AwaitWithTimeout(TimeSpan.FromSeconds(5)); 103 | } 104 | 105 | /// 106 | /// Receive a sequence of bytes over the serial port. 107 | /// 108 | Task IPort.Receive(byte[] buffer, int offset, int count) 109 | { 110 | // Using the BaseStream causes data to be lost. 111 | return Task.FromResult(this.port.Read(buffer, offset, count)); 112 | } 113 | 114 | /// 115 | /// Discard anything in the input and output buffers. 116 | /// 117 | public Task DiscardBuffers() 118 | { 119 | this.port.DiscardInBuffer(); 120 | this.port.DiscardOutBuffer(); 121 | return Task.FromResult(0); 122 | } 123 | 124 | /// 125 | /// Sets the read timeout. 126 | /// 127 | public void SetTimeout(int milliseconds) 128 | { 129 | this.port.ReadTimeout = milliseconds; 130 | } 131 | 132 | /// 133 | /// Serial data callback. Didn't work the first time, but I still have hopes... 134 | /// 135 | private void DataReceived(object sender, SerialDataReceivedEventArgs args) 136 | { 137 | // this.dataReceivedCallback(sender, args); 138 | } 139 | 140 | /// 141 | /// Indicates the number of bytes waiting in the queue. 142 | /// 143 | Task IPort.GetReceiveQueueSize() 144 | { 145 | return Task.FromResult(this.port.BytesToRead); 146 | } 147 | } 148 | } 149 | 150 | -------------------------------------------------------------------------------- /IPCLibraryWindowsForms/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PcmLibraryWindowsForms")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("PcmLibraryWindowsForms")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("4adb5d87-d4d5-4d12-8681-a9e2d4c52df6")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /IPCLibraryWindowsForms/WinFormsConfigurationAccessor.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 the app.config file, to persist settings between app uses. 12 | /// 13 | public class WinFormsConfigurationAccessor : Configuration.ConfigurationAccessor 14 | { 15 | /// 16 | /// Create a configuration setting. 17 | /// 18 | public override string Read(string key) 19 | { 20 | var configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 21 | var setting = configuration.AppSettings.Settings[key]; 22 | if (setting == null) 23 | { 24 | return string.Empty; 25 | } 26 | 27 | return setting.Value; 28 | } 29 | 30 | /// 31 | /// Write a configuration setting. 32 | /// 33 | public override void Write(string key, string value) 34 | { 35 | var configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 36 | try 37 | { 38 | configuration.AppSettings.Settings.Remove(key); 39 | configuration.AppSettings.Settings.Add(key, value); 40 | configuration.Save(); 41 | } 42 | catch (Exception e) 43 | { 44 | System.Diagnostics.Debug.WriteLine("Could not save configuration: '{0}'", e); 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /IPCLogger/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /IPCLogger/Example2.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 | -------------------------------------------------------------------------------- /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/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 | }, -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /IPCLogger/General.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 | -------------------------------------------------------------------------------- /IPCLogger/Idle.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": "Raw", 39 | "Expression": "x" 40 | }, 41 | "Name": "PID 1105; 128=DFCO", 42 | "DefineBy": 1, 43 | "ByteCount": 1, 44 | "Address": "0x1105" 45 | }, 46 | ], 47 | "TotalBytes": 6 48 | }, 49 | { 50 | "Dpid": "0xFD", 51 | "Parameters": [ 52 | { 53 | "Conversion": { 54 | "Name": "g/s", 55 | "Expression": "x*0.00009765625" 56 | }, 57 | "Name": "Desired Idle Airflow", 58 | "DefineBy": 1, 59 | "ByteCount": 2, 60 | "Address": "0x1617" 61 | }, 62 | { 63 | "Conversion": { 64 | "Name": "%", 65 | "Expression": "x*0.00390625" 66 | }, 67 | "Name": "Target throttle position", 68 | "DefineBy": 1, 69 | "ByteCount": 2, 70 | "Address": "0x131E" 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 | "TotalBytes": 6 94 | }, 95 | { 96 | "Dpid": "0xFC", 97 | "Parameters": [ 98 | { 99 | "Conversion": { 100 | "Name": "Mode", 101 | "Expression": "x" 102 | }, 103 | "Name": "Fueling Mode", 104 | "DefineBy": 1, 105 | "ByteCount": 2, 106 | "Address": "0x3" 107 | }, 108 | { 109 | "Conversion": { 110 | "Name": "F", 111 | "Expression": "((x-40)*1.8)+32" 112 | }, 113 | "Name": "Intake Air Temperature", 114 | "DefineBy": 1, 115 | "ByteCount": 1, 116 | "Address": "0xF" 117 | }, 118 | { 119 | "Conversion": { 120 | "Name": "F", 121 | "Expression": "((x-40)*1.8)+32" 122 | }, 123 | "Name": "Engine Coolant Temperature", 124 | "DefineBy": 1, 125 | "ByteCount": 1, 126 | "Address": "0x5" 127 | }, 128 | { 129 | "Conversion": { 130 | "Name": "Degrees", 131 | "Expression": "(x\/256)*22.5" 132 | }, 133 | "Name": "Knock Retard", 134 | "DefineBy": 1, 135 | "ByteCount": 1, 136 | "Address": "0x11A6" 137 | }, 138 | { 139 | "Conversion": { 140 | "Name": "AFR", 141 | "Expression": "x\/10" 142 | }, 143 | "Name": "Target AFR", 144 | "DefineBy": 1, 145 | "ByteCount": 1, 146 | "Address": "0x119E" 147 | } 148 | ], 149 | "TotalBytes": 6 150 | } 151 | ] 152 | } -------------------------------------------------------------------------------- /IPCLogger/Idle.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 | -------------------------------------------------------------------------------- /IPCLogger/IdleAir.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 | -------------------------------------------------------------------------------- /IPCLogger/IdlePID.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 | -------------------------------------------------------------------------------- /IPCLogger/LoggerConfiguration.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 LoggerConfiguration 10 | { 11 | public class LoggerConstants 12 | { 13 | public const string ProfilePath = "ProfilePath"; 14 | public const string LogDirectory = "LogDirectory"; 15 | } 16 | 17 | /// 18 | /// Path of the most recent log profile. 19 | /// 20 | public static string ProfilePath 21 | { 22 | get 23 | { 24 | return Configuration.Read(LoggerConstants.ProfilePath); 25 | } 26 | 27 | set 28 | { 29 | Configuration.Write(LoggerConstants.ProfilePath, value); 30 | } 31 | } 32 | 33 | /// 34 | /// Directory to store log files. 35 | /// 36 | public static string LogDirectory 37 | { 38 | get 39 | { 40 | return Configuration.Read(LoggerConstants.LogDirectory); 41 | } 42 | 43 | set 44 | { 45 | Configuration.Write(LoggerConstants.LogDirectory, value); 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /IPCLogger/MathValues.configuration: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /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/Memory.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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /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/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/Parameters.12593358.xml: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /IPCLogger/Parameters.SAE.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /IPCLogger/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace PcmHacking 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Configuration.SetAccessor(new WinFormsConfigurationAccessor()); 18 | 19 | Application.EnableVisualStyles(); 20 | Application.SetCompatibleTextRenderingDefault(false); 21 | Application.Run(new MainForm()); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /IPCLogger/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("IPCLogger")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("IPCLogger")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("6a473c4f-a1a3-4cfb-8167-13f4064c1639")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /IPCLogger/Properties/Settings.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 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /IPCLogger/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /IPCLogger/clusterram.xml.profile: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /IPCLogger/clusterram.xml.profile.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /IPCLogger/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # IPC-Hammer 2 | Modified version of PCM Hammer. Used to program calibration and OS or just the calibration section of 03-06 and 07 classic GMT800 instrument clusters. 3 | 4 | 5 | Link 6 | Facebook group 7 | https://www.facebook.com/groups/2088445401343415 8 | -------------------------------------------------------------------------------- /Tests/AvtTests.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 AvtTests 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 | AvtDevice device = new AvtDevice(port, logger); 20 | 21 | // Specify the sequence of bytes that we would expect to get back from the serial port. 22 | port.EnqueueBytes(new byte[] { 0x11, 0x0C, 0x00, 0x6c, 0xF0, 0x10, 0x7C, 0x01, 0x00, 0x31, 0x47, 0x31, 0x59, 0x59, 0xC3 }); 23 | port.BytesToReceive.Position = 0; 24 | 25 | // Send a message. 26 | Message message = new Message(new byte[] { 0x6c, 0x10, 0xF0, 0x3C, 0x01 }); 27 | bool sendSuccess = await device.SendMessage(message); 28 | 29 | // Confirm success. 30 | Assert.IsTrue(sendSuccess, "Send success"); 31 | 32 | // Confirm that the device sent the bytes we expect it to send. 33 | // The 00 00 00 stuff is just placeholders for real data. 34 | Assert.AreEqual("05", port.MessagesSent[0].ToHex(), "First command"); 35 | Assert.AreEqual(message.GetBytes().ToHex(), port.MessagesSent[1].ToHex(), "Second command"); 36 | 37 | // Confirm that the device interpreted the response as expected. 38 | Message response = await device.ReceiveMessage(); 39 | 40 | Assert.IsNotNull(response, "Response should not be null."); 41 | Assert.AreEqual("6C F0 10 7C 01 00 31 47 31 59 59", response.GetBytes().ToHex(), "Response message"); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Tests/MockLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using PcmHacking; 7 | 8 | namespace Tests 9 | { 10 | class MockLogger : ILogger 11 | { 12 | public void AddDebugMessage(string message) 13 | { 14 | } 15 | 16 | public void AddUserMessage(string message) 17 | { 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("Tests")] 6 | [assembly: AssemblyDescription("")] 7 | [assembly: AssemblyConfiguration("")] 8 | [assembly: AssemblyCompany("")] 9 | [assembly: AssemblyProduct("Tests")] 10 | [assembly: AssemblyCopyright("Copyright © 2018")] 11 | [assembly: AssemblyTrademark("")] 12 | [assembly: AssemblyCulture("")] 13 | 14 | [assembly: ComVisible(false)] 15 | 16 | [assembly: Guid("0aa6f273-995d-4ade-8cbb-db1b6e8a0fce")] 17 | 18 | // [assembly: AssemblyVersion("1.0.*")] 19 | [assembly: AssemblyVersion("1.0.0.0")] 20 | [assembly: AssemblyFileVersion("1.0.0.0")] 21 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Tests/TestLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | using PcmHacking; 8 | 9 | namespace Tests 10 | { 11 | class TestLogger : ILogger 12 | { 13 | public StringBuilder UserMessages { get; private set; } 14 | public StringBuilder DebugMessages { get; private set; } 15 | 16 | public TestLogger() 17 | { 18 | this.UserMessages = new StringBuilder(); 19 | this.DebugMessages = new StringBuilder(); 20 | } 21 | 22 | public void AddDebugMessage(string message) 23 | { 24 | this.DebugMessages.AppendLine(message); 25 | } 26 | 27 | public void AddUserMessage(string message) 28 | { 29 | this.UserMessages.AppendLine(message); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /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/TestScenarios.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using PcmHacking; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | public class TestScenarios 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Tests/UtilityTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using PcmHacking; 3 | using Microsoft.VisualStudio.TestTools.UnitTesting; 4 | 5 | namespace Tests 6 | { 7 | [TestClass] 8 | public class UtilityTests 9 | { 10 | [TestMethod] 11 | public void ToHex() 12 | { 13 | Assert.AreEqual("", new byte[0].ToHex(), "Zero length"); 14 | Assert.AreEqual("01", new byte[] { 0x01 }.ToHex(), "One byte"); 15 | Assert.AreEqual("01 FF", new byte[] { 0x01, 0xFF }.ToHex(), "Two bytes"); 16 | Assert.AreEqual("00 01 99 AA FF", new byte[] { 0x00, 0x01, 0x99, 0xAA, 0xFF }.ToHex(), "Five bytes"); 17 | } 18 | 19 | [TestMethod] 20 | public void ToHexWithCount() 21 | { 22 | Assert.AreEqual("", new byte[0].ToHex(0), "Zero length, count=0"); 23 | Assert.AreEqual("01", new byte[] { 0x01 }.ToHex(2), "One byte, count=2"); 24 | Assert.AreEqual("01", new byte[] { 0x01, 0xFF }.ToHex(1), "Two bytes, count=1"); 25 | Assert.AreEqual("00 01", new byte[] { 0x00, 0x01, 0x99, 0xAA, 0xFF }.ToHex(2), "Five bytes, count=2"); 26 | } 27 | 28 | [TestMethod] 29 | public void CompareArrays() 30 | { 31 | Assert.IsTrue(Utility.CompareArrays(new byte[0], new byte[0]), "Zero length"); 32 | Assert.IsTrue(Utility.CompareArrays(new byte[] { 0x01 }, new byte[] { 0x01 }), "One byte"); 33 | Assert.IsTrue(Utility.CompareArrays(new byte[] { 0x01, 0x02, 0x03 }, new byte[] { 0x01, 0x02, 0x03 }), "Three bytes"); 34 | Assert.IsFalse(Utility.CompareArrays(new byte[] { 0x01, 0x02, 0x03 }, new byte[] { 0x01, 0x02 }), "2nd array too short"); 35 | Assert.IsFalse(Utility.CompareArrays(new byte[] { 0x01, 0x02 }, new byte[] { 0x01, 0x02, 0x03 }), "2nd array too long"); 36 | Assert.IsFalse(Utility.CompareArrays(new byte[] { 0x01, 0x02, 0x03 }, new byte[] { 0x01, 0x02, 0xFF }), "Mismatched byte"); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Tests/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /VpwExplorer/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /VpwExplorer/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace PcmHacking 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | 20 | Configuration.SetAccessor(new WinFormsConfigurationAccessor()); 21 | Application.Run(new PcmExplorerMainForm()); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /VpwExplorer/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("PcmExplorer")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("PcmExplorer")] 13 | [assembly: AssemblyCopyright("Copyright © 2019")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("2b57abc7-9994-4db3-9403-b22471a0dda1")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /VpwExplorer/Properties/Settings.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 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.4.0.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /VpwExplorer/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------