private void TreeViewDoubleClickCheckIfVariantDiag(TreeNode node) { string validNodePrefix = $"Exec{nameof(DiagService)}:"; if (node.Parent is null) { return; } if (node.Parent.Tag.ToString().StartsWith(validNodePrefix)) { string variantName = node.Parent.Tag.ToString().Substring(validNodePrefix.Length); ECUVariant foundVariant = null; foreach (CaesarContainer container in Containers) { foreach (ECU ecu in container.CaesarECUs) { foreach (ECUVariant variant in ecu.ECUVariants) { if (variant.Qualifier == variantName) { foundVariant = variant; } } } } // variant found, exec the diag service if (foundVariant != null) { DiagService ds = foundVariant.DiagServices[int.Parse(node.Tag.ToString())]; bool connectionSupportsUnlocking = Connection?.ConnectionProtocol?.SupportsUnlocking() ?? false; // can we help to skip the modal if the ds doesn't require additional user input? common for data, stored data if ((ds.DataClass_ServiceType == (int)DiagService.ServiceType.StoredData) || (ds.DataClass_ServiceType == (int)DiagService.ServiceType.Data)) { Connection?.ExecUserDiagJob(ds.RequestBytes, ds); } else if (connectionSupportsUnlocking && (ds.RequestBytes.Length == 2) && (ds.RequestBytes[0] == 0x27)) { // request seed, no need to prompt Connection?.ExecUserDiagJob(ds.RequestBytes, ds); } else { PresentRunDiagDialog(ds); } } } }
private void diagnosticTroubleCodesDTCToolStripMenuItem_Click(object sender, EventArgs e) { if (Connection.ConnectionProtocol is null) { MessageBox.Show("Please initiate contact with a target first."); return; } if (Connection.ConnectionProtocol.GetProtocolName() != "UDS") { MessageBox.Show("Sorry, only UDS is supported at this time."); // return was removed from here, to allow for kw2c3pe debugging } if (!(Connection?.VariantIsAvailable ?? false)) { MessageBox.Show("DTCs require the variant to be identified first"); return; } ECUVariant currentVariant = GetCurrentVariantInstance(); DTCForm dtcForm = new DTCForm(Connection, currentVariant); dtcForm.ShowDialog(); }
public VCForm(CaesarContainer container, string ecuName, string variantName, string vcDomain, ECUConnection connection) { InitializeComponent(); ECUName = ecuName; VariantName = variantName; VCDomainName = vcDomain; SelectedECU = container.GetECUByName(ecuName); ECUVariant = container.GetECUVariantByName(variantName); VariantCodingDomain = ECUVariant.GetVCDomainByName(VCDomainName); ReadService = ECUVariant.GetDiagServiceByName(VariantCodingDomain.ReadServiceName); WriteService = ECUVariant.GetDiagServiceByName(VariantCodingDomain.WriteServiceName); if ((ReadService is null) || (WriteService is null)) { Console.WriteLine("VC Dialog: Unable to proceed - could not find referenced diagnostic services"); this.Close(); } //Console.WriteLine(ReadService.Qualifier); //Console.WriteLine(WriteService.Qualifier); VCValue = new byte[VariantCodingDomain.DumpSize]; UnfilteredReadValue = new byte[] { }; foreach (Tuple <string, byte[]> row in VariantCodingDomain.DefaultData) { if (row.Item1.ToLower() == "default" && (row.Item2.Length == VariantCodingDomain.DumpSize)) { VCValue = row.Item2; Console.WriteLine("Default CBF variant coding data is available"); break; } } if (connection.State >= ECUConnection.ConnectionState.ChannelConnectedPendingEcuContact) { // Console.WriteLine($"Requesting variant coding read: {ReadService.Qualifier} : ({BitUtility.BytesToHex(ReadService.RequestBytes)})"); byte[] response = connection.SendDiagRequest(ReadService); DiagPreparation largestPrep = GetLargestPreparation(ReadService.OutputPreparations); if (largestPrep.PresPoolIndex > -1) { // DiagPresentation pres = SelectedECU.GlobalPresentations[largestPrep.PresPoolIndex]; // pres.PrintDebug(); } // Console.WriteLine($"Variant coding received: {BitUtility.BytesToHex(response)}"); VCValue = response.Skip(largestPrep.BitPosition / 8).Take(largestPrep.SizeInBits / 8).ToArray(); // store the received VC: when writing back, we might need the previous author's fingerprints UnfilteredReadValue = response; } else { Console.WriteLine("Please check for connectivity to the target ECU (could not read variant coding data)"); MessageBox.Show("Variant Coding dialog will operate as a simulation using default values.", "Unable to read ECU variant coding data", MessageBoxButtons.OK); btnApply.Enabled = false; } // VCSanityCheck(); IntepretVC(); PresentVC(); }
public virtual List <DTCContext> ReportDtcsByStatusMask(ECUConnection connection, ECUVariant variant, byte inMask = 0) { return(new List <DTCContext>()); }
public DTCForm(ECUConnection connection, ECUVariant variant) { Connection = connection; Variant = variant; InitializeComponent(); }
private void tvMain_DoubleClick(object sender, EventArgs e) { TreeNode node = tvMain.SelectedNode; if (node is null) { return; } if (node.Tag.ToString() == nameof(VCDomain)) { // variant coding treeViewSelectVariantCoding(node); } else if (node.Tag.ToString() == "VCBackup") { // variant coding backup VCReport.treeViewSelectVariantCodingBackup(node, Connection, Containers); } else if (node.Tag.ToString().StartsWith(nameof(ECUInterfaceSubtype))) { // initiate contact string connectionProfileName = node.Tag.ToString().Substring(nameof(ECUInterfaceSubtype).Length + 1); string ecuName = node.Parent.Parent.Text; foreach (CaesarContainer container in Containers) { ECU ecu = container.CaesarECUs.Find(x => x.Qualifier == ecuName); if (ecu != null) { ECUInterfaceSubtype subtype = ecu.ECUInterfaceSubtypes.Find(x => x.Qualifier == connectionProfileName); if (subtype != null) { Console.WriteLine($"Attempting to open a connection to ({ecuName}) with profile '{connectionProfileName}'"); ECUConnection.ConnectResponse response = Connection.Connect(subtype, ecu); if (response == ECUConnection.ConnectResponse.OK) { ProtocolPostConnect(); } else if (response == ECUConnection.ConnectResponse.NoValidInterface) { BlinkConnectionMenu(); connectionToolStripMenuItem.ShowDropDown(); j2534InterfacesToolStripMenuItem.ShowDropDown(); } else { // uhoh Console.WriteLine($"ECU connection was unsuccessful : {response}"); } break; } } } } else if (node.Tag.ToString().StartsWith(nameof(DiagService))) { // execute diag service (modal) string diagOrigin = node.Tag.ToString().Substring(nameof(DiagService).Length + 1); string variantName = ""; string ecuName = ""; if (diagOrigin.StartsWith($"{nameof(ECUVariant)}:")) { variantName = node.Parent.Text; ecuName = node.Parent.Parent.Text; } else { ecuName = node.Parent.Text; } foreach (CaesarContainer container in Containers) { ECU ecu = container.CaesarECUs.Find(x => x.Qualifier == ecuName); if (ecu != null) { PickDiagForm picker; ECUVariant variant = ecu.ECUVariants.Find(x => x.Qualifier == variantName); if (variant != null) { //Console.WriteLine($"Starting Diagnostic Service picker modal for variant {variantName}"); picker = new PickDiagForm(variant.DiagServices); } else { //Console.WriteLine($"Starting Diagnostic Service picker modal for root {ecuName}"); picker = new PickDiagForm(ecu.GlobalDiagServices.ToArray()); } if (picker.ShowDialog() == DialogResult.OK) { PresentRunDiagDialog(picker.SelectedDiagService); } break; } } } TreeViewDoubleClickCheckIfSession(node); TreeViewDoubleClickCheckIfVariantDiag(node); }
private void AddDiagServicesToNode(TreeNode parentNode, ECUVariant variant) { string newTag = $"Exec{nameof(DiagService)}:{variant.Qualifier}"; TreeNode diagUnlockingOptions = new TreeNode($"Security Access", 19, 19); diagUnlockingOptions.Tag = newTag; TreeNode diagStoredData = new TreeNode($"Diagnostics: Stored Data", 24, 24); diagStoredData.Tag = newTag; TreeNode diagData = new TreeNode($"Diagnostics: Data", 24, 24); diagData.Tag = newTag; TreeNode diagFunction = new TreeNode($"Diagnostics: Function", 24, 24); diagFunction.Tag = newTag; TreeNode diagRoutine = new TreeNode($"Diagnostics: Routine", 24, 24); diagRoutine.Tag = newTag; TreeNode diagIO = new TreeNode($"Diagnostics: IO", 24, 24); diagIO.Tag = newTag; TreeNode diagDownload = new TreeNode($"Diagnostics: Download", 24, 24); diagDownload.Tag = newTag; for (int i = 0; i < variant.DiagServices.Length; i++) { DiagService currentDiagService = variant.DiagServices[i]; TreeNode diagNode = new TreeNode(currentDiagService.Qualifier, 9, 9); diagNode.Tag = i.ToString(); if ((currentDiagService.RequestBytes.Length > 1) && (currentDiagService.RequestBytes[0] == 0x27)) { diagUnlockingOptions.Nodes.Add(diagNode); continue; } if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.StoredData) { diagStoredData.Nodes.Add(diagNode); } else if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.DiagnosticFunction) { diagFunction.Nodes.Add(diagNode); } else if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.Data) { diagData.Nodes.Add(diagNode); } else if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.Routine) { diagRoutine.Nodes.Add(diagNode); } else if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.IoControl) { diagIO.Nodes.Add(diagNode); } else if (currentDiagService.DataClass_ServiceType == (int)DiagService.ServiceType.Download) { diagDownload.Nodes.Add(diagNode); } } parentNode.Nodes.Add(diagUnlockingOptions); parentNode.Nodes.Add(diagStoredData); parentNode.Nodes.Add(diagData); parentNode.Nodes.Add(diagFunction); parentNode.Nodes.Add(diagRoutine); parentNode.Nodes.Add(diagIO); parentNode.Nodes.Add(diagDownload); }
public static void treeViewSelectVariantCodingBackup(TreeNode node, ECUConnection connection, List <CaesarContainer> containers) { if (connection is null) { return; } Cursor.Current = Cursors.WaitCursor; string variantName = node.Parent.Text; string ecuName = node.Parent.Parent.Text; string reportDate = $"{DateTime.Now.ToShortDateString()} {DateTime.Now.ToLongTimeString()}"; StringBuilder report = new StringBuilder(); CaesarContainer container = containers.Find(x => x.GetECUVariantByName(variantName) != null); ECU ecu = container.GetECUByName(ecuName); ECUVariant variant = container.GetECUVariantByName(variantName); string containerChecksum = container.FileChecksum.ToString("X8"); string dVersion = MainForm.GetVersion(); string cVersion = CaesarContainer.GetCaesarVersionString(); string connectionData = connection is null ? "(Unavailable)" : connection.FriendlyProfileName; string ecuCbfVersion = ecu.EcuXmlVersion; report.Append($"ECU Variant: {variant.Qualifier}\r\n"); StringBuilder tableBuilder = new StringBuilder(); // back up every domain since some have overlaps foreach (VCDomain domain in variant.VCDomains) { report.Append($"\r\nCoding Service: {domain.Qualifier}\r\n"); // find the read service, then execute it as-is DiagService readService = variant.GetDiagServiceByName(domain.ReadServiceName); byte[] response = connection.SendDiagRequest(readService); // isolate the traditional vc string DiagPreparation largestPrep = VCForm.GetLargestPreparation(readService.OutputPreparations); byte[] vcValue = response.Skip(largestPrep.BitPosition / 8).Take(largestPrep.SizeInBits / 8).ToArray(); StringBuilder tableRowBuilder = new StringBuilder(); // explain the vc string's settings for (int i = 0; i < domain.VCFragments.Count; i++) { VCFragment currentFragment = domain.VCFragments[i]; VCSubfragment subfragment = currentFragment.GetSubfragmentConfiguration(vcValue); string fragmentValue = subfragment is null ? "(?)" : subfragment.NameCTFResolved; string fragmentSupplementKey = subfragment is null ? "(?)" : subfragment.SupplementKey; string tableRowBlock = $@" <tr> <td>{currentFragment.Qualifier}</td> <td>{fragmentValue}</td> <td>{fragmentSupplementKey}</td> </tr> "; tableRowBuilder.Append(tableRowBlock); } string tableBlock = $@" <hr> <h2>{domain.Qualifier}</h2> <table class=""coding-data""> <tr> <td class=""fifth"">Coding String (Hex)</td> <td class=""monospace"">{BitUtility.BytesToHex(vcValue, true)}</td> </tr> <tr> <td class=""fifth"">Raw Coding String (Hex)</td> <td class=""monospace"">{BitUtility.BytesToHex(response, true)}</td> </tr> </table> <table> <tr> <th>Fragment</th> <th>Value</th> <th>Supplement Key</th> </tr> {tableRowBuilder} </table> "; tableBuilder.Append(tableBlock); } string document = $@" <!DOCTYPE html> <html lang=""en""> <head> <meta charset=""UTF-8""> <title>{ecuName} : Backup</title> <style> body {{ padding: 10px 20% 15px 15%; font-family: sans-serif; }} .pull-right {{ float: right; }} hr {{ border-bottom: 0; opacity: 0.2; }} table {{ width: 100%; margin: 20px 0; }} #eof {{ text-transform: uppercase; font-weight: bold; opacity: 0.15; letter-spacing: 0.4em; }} .coding-data {{ opacity: 0.8; }} .monospace {{ font-family: monospace; }} .fifth {{ width: 20%; }} th {{ text-align: left; }} </style> </head> <body> <h1 class=""pull-right"">Diogenes</h1> <h1>{ecuName}</h1> <hr> <table> <tr> <td>CBF Checksum</td> <td>{containerChecksum}</td> </tr> <tr> <td>Date</td> <td>{reportDate}</td> </tr> <tr> <td>Client Version</td> <td>Diogenes: {dVersion}, Caesar: {cVersion}</td> </tr> <tr> <td>ECU CBF Version</td> <td>{ecuCbfVersion}</td> </tr> <tr> <td>ECU Variant</td> <td>{variantName}</td> </tr> <tr> <td>Connection Info</td> <td>{connectionData}</td> </tr> </table> {tableBuilder} <hr> <span id=""eof"">End of report</span> </body> </html>"; Cursor.Current = Cursors.Default; SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your new VC backup"; sfd.Filter = "HTML file (*.html)|*.html|All files (*.*)|*.*"; sfd.FileName = $"VC_{variantName}_{DateTime.Now.ToString("yyyyMMdd_HHmm")}.html"; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllText(sfd.FileName, document.ToString()); MessageBox.Show($"Backup successfully saved to {sfd.FileName}", "Export complete"); } }
public static void CreateDTCReport(List <DTCContext> dtcContexts, ECUConnection connection, ECUVariant variant) { Cursor.Current = Cursors.WaitCursor; string reportDate = $"{DateTime.Now.ToShortDateString()} {DateTime.Now.ToLongTimeString()}"; string containerChecksum = variant.ParentECU.ParentContainer.FileChecksum.ToString("X8"); string dVersion = MainForm.GetVersion(); string cVersion = CaesarContainer.GetCaesarVersionString(); string connectionData = connection is null ? "(Unavailable)" : connection.FriendlyProfileName; string ecuCbfVersion = variant.ParentECU.EcuXmlVersion; StringBuilder tableBuilder = new StringBuilder(); // back up every domain since some have overlaps foreach (DTCContext dtcCtx in dtcContexts) { StringBuilder tableRowBuilder = new StringBuilder(); // env, description for (int i = 0; i < dtcCtx.EnvironmentContext.Count; i++) { string tableRowBlock = $@" <tr> <td>{dtcCtx.EnvironmentContext[i][0]}</td> <td>{dtcCtx.EnvironmentContext[i][1]}</td> </tr> "; tableRowBuilder.Append(tableRowBlock); } string tableBlock = $@" <hr> <h2>{dtcCtx.DTC.Qualifier}</h2> <p>{dtcCtx.DTC.Description}</p> <table> <tr> <th>Environment</th> <th>Description</th> </tr> {tableRowBuilder} </table> "; tableBuilder.Append(tableBlock); } string document = $@" <!DOCTYPE html> <html lang=""en""> <head> <meta charset=""UTF-8""> <title>{variant.ParentECU.Qualifier} : DTC Report</title> <style> body {{ padding: 10px 20% 15px 15%; font-family: sans-serif; }} .pull-right {{ float: right; }} hr {{ border-bottom: 0; opacity: 0.2; }} table {{ width: 100%; margin: 20px 0; }} #eof {{ text-transform: uppercase; font-weight: bold; opacity: 0.15; letter-spacing: 0.4em; }} .coding-data {{ opacity: 0.8; }} .monospace {{ font-family: monospace; }} .fifth {{ width: 20%; }} th {{ text-align: left; }} </style> </head> <body> <h1 class=""pull-right"">Diogenes</h1> <h1>{variant.ParentECU.Qualifier}</h1> <hr> <table> <tr> <td>CBF Checksum</td> <td>{containerChecksum}</td> </tr> <tr> <td>Date</td> <td>{reportDate}</td> </tr> <tr> <td>Client Version</td> <td>Diogenes: {dVersion}, Caesar: {cVersion}</td> </tr> <tr> <td>ECU CBF Version</td> <td>{ecuCbfVersion}</td> </tr> <tr> <td>ECU Variant</td> <td>{variant.Qualifier}</td> </tr> <tr> <td>Connection Info</td> <td>{connectionData}</td> </tr> </table> {connection.ConnectionProtocol.QueryECUMetadata(connection).GetHtmlTable(connection)} {tableBuilder} <hr> <span id=""eof"">End of report</span> </body> </html>"; Cursor.Current = Cursors.Default; SaveFileDialog sfd = new SaveFileDialog(); sfd.Title = "Specify a location to save your new DTC report"; sfd.Filter = "HTML file (*.html)|*.html|All files (*.*)|*.*"; sfd.FileName = $"DTC_{variant.Qualifier}_{DateTime.Now.ToString("yyyyMMdd_HHmm")}.html"; if (sfd.ShowDialog() == DialogResult.OK) { File.WriteAllText(sfd.FileName, document.ToString()); MessageBox.Show($"Report successfully saved to {sfd.FileName}", "Export complete"); } }
public override List <DTCContext> ReportDtcsByStatusMask(ECUConnection connection, ECUVariant variant, byte inMask = 0) { List <DTCContext> dtcCtx = new List <DTCContext>(); byte mask = (byte)(DTCStatusByte.TestFailedAtRequestTime | DTCStatusByte.TestFailedAtCurrentCycle | DTCStatusByte.PendingDTC | DTCStatusByte.ConfirmedDTC | DTCStatusByte.TestFailedSinceLastClear); byte[] request = new byte[] { 0x19, 0x02, inMask == 0 ? mask : inMask }; byte[] expectedResponse = new byte[] { 0x59, 0x02 }; byte[] response = connection.SendMessage(request); if (!response.Take(expectedResponse.Length).SequenceEqual(expectedResponse)) { return(new List <DTCContext>()); } for (int i = 3; i < response.Length; i += 4) { byte[] dtcRow = new byte[4]; Array.ConstrainedCopy(response, i, dtcRow, 0, 4); string dtcIdentifier = BitUtility.BytesToHex(dtcRow.Take(3).ToArray(), false); DTC foundDtc = DTC.FindDTCById(dtcIdentifier, variant); if (foundDtc is null) { Console.WriteLine($"DTC: No matching DTC available for {dtcIdentifier}"); } dtcCtx.Add(new DTCContext() { DTC = foundDtc, StatusByte = dtcRow[3], EnvironmentContext = new List <string[]>() }); } return(dtcCtx); }
public override List <DTCContext> ReportDtcsByStatusMask(ECUConnection connection, ECUVariant variant, byte inMask = 0) { // FIXME : KW2C3PE probably uses a different set of commands at 0x18 return(base.ReportDtcsByStatusMask(connection, variant, inMask)); }