示例#1
0
        private void treeViewSelectVariantCoding(TreeNode node)
        {
            string domainName  = node.Text;
            string variantName = node.Parent.Text;
            string ecuName     = node.Parent.Parent.Text;

            Console.WriteLine($"Starting VC Dialog for {ecuName} ({variantName}) with domain as {domainName}");
            CaesarContainer container = Containers.Find(x => x.GetECUVariantByName(variantName) != null);

            // prompt the user for vc changes via VCForm
            VCForm vcForm = new VCForm(container, ecuName, variantName, domainName, Connection);

            if (vcForm.ShowDialog() == DialogResult.OK)
            {
                VariantCoding.DoVariantCoding(Connection, vcForm, allowWriteVariantCodingToolStripMenuItem.Checked);
            }
        }
示例#2
0
        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");
            }
        }
示例#3
0
        /*
         *  test: med40
         *
         *  jg: dumping pres
         *  jg: q: SID_RQ pos byte: 0 size bytes: 1 modecfg:323 fieldtype: IntegerType dump: 2E 00 00 00
         *  jg: q: RecordDataIdentifier pos byte: 1 size bytes: 2 modecfg:324 fieldtype: IntegerType dump: 01 10 00 00
         *  jg: q: #0 pos byte: 33 size bytes: 16 modecfg:6430 fieldtype: BitDumpType dump:
         *  jg: q: #1 pos byte: 49 size bytes: 1 modecfg:6423 fieldtype: IntegerType dump:
         *  jg: q: #2 pos byte: 50 size bytes: 1 modecfg:6423 fieldtype: IntegerType dump:
         *  jg: q: #3 pos byte: 51 size bytes: 1 modecfg:6423 fieldtype: IntegerType dump:
         *  jg: q: #4 pos byte: 52 size bytes: 1 modecfg:6423 fieldtype: IntegerType dump:
         *  jg: q: #5 pos byte: 3 size bytes: 50 modecfg:6410 fieldtype: ExtendedBitDumpType dump:
         *  jg: done dumping pres
         *
         */


        public static void DoVariantCoding(ECUConnection connection, VCForm vcForm, bool writesEnabled)
        {
            Console.WriteLine($"Operator requesting for VC: {BitUtility.BytesToHex(vcForm.VCValue, true)}");

            RunDiagForm runDiagForm = new RunDiagForm(vcForm.WriteService);

            // construct a write command from presentations: fill up the VC value first, fill up all available dumps, then inherit the last values (fingerprints, scn) from the read command
            byte[] vcParameter      = vcForm.VCValue;
            byte[] writeCommand     = vcForm.WriteService.RequestBytes;
            byte[] priorReadCommand = vcForm.UnfilteredReadValue;


            // start with a list of all values that we will have to fill
            List <DiagPreparation> preparationsToProcess = new List <DiagPreparation>(vcForm.WriteService.InputPreparations);

            // fill up vc, which pretty much always uses the ExtendedBitDumpType type
            DiagPreparation vcPrep = preparationsToProcess.Find(x => x.FieldType == DiagPreparation.InferredDataType.ExtendedBitDumpType);

            if (vcPrep is null)
            {
                MessageBox.Show("VC: Could not find the VC ExtendedBitDump prep, stopping early to save your ECU.", "VC Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            int vcPrepSizeInBytes  = vcPrep.SizeInBits / 8;
            int vcPrepBytePosition = vcPrep.BitPosition / 8;

            if (vcPrepSizeInBytes < vcParameter.Length)
            {
                MessageBox.Show("VC: VC string is longer than the parameter can fit, stopping early to save your ECU.", "VC Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            // zero out the destination buffer for the param that we intend to write since there's a possibility that our param is shorter than the actual prep's size
            for (int i = vcPrepBytePosition; i < (vcPrepBytePosition + vcPrepSizeInBytes); i++)
            {
                writeCommand[i] = 0;
            }
            // copy the parameter in
            Array.ConstrainedCopy(vcParameter, 0, writeCommand, vcPrepBytePosition, vcParameter.Length);
            preparationsToProcess.Remove(vcPrep);
            // done with vc prep


            // merge prefilled constants such as the (SID_RQ, id..)
            List <DiagPreparation> prefilledValues = new List <DiagPreparation>();

            foreach (DiagPreparation prep in preparationsToProcess)
            {
                if (prep.Dump.Length > 0)
                {
                    prefilledValues.Add(prep);
                    if (prep.FieldType == DiagPreparation.InferredDataType.IntegerType)
                    {
                        byte[] fixedDump = prep.Dump.Take(prep.SizeInBits / 8).Reverse().ToArray();
                        Array.ConstrainedCopy(vcParameter, 0, writeCommand, vcPrepBytePosition, vcParameter.Length);
                    }
                    else
                    {
                        Console.WriteLine($"Skipping prefill for {prep.Qualifier} as the data type {prep.FieldType} is unsupported.");
                    }
                }
            }
            // "mark" the constants as done
            foreach (DiagPreparation prep in prefilledValues)
            {
                preparationsToProcess.Remove(prep);
            }

            // isolate the SCN if it exists
            foreach (DiagPreparation prep in preparationsToProcess)
            {
                int bytePosition = prep.BitPosition / 8;
                int byteLength   = prep.SizeInBits / 8;
                // SCN is always 16-bytes
                if (byteLength != 16)
                {
                    continue;
                }
                byte[] originalValue = new byte[byteLength];
                Array.ConstrainedCopy(priorReadCommand, bytePosition, originalValue, 0, byteLength);

                // SCN values are ASCII numerals (between 0x30 - 0x39)
                bool isValidSCN = true;
                foreach (byte b in originalValue)
                {
                    if ((b > 0x39) || (b < 0x30))
                    {
                        isValidSCN = false;
                        break;
                    }
                }
                if (!isValidSCN)
                {
                    continue;
                }

                Console.WriteLine($"Found SCN value: {Encoding.ASCII.GetString(originalValue)}");

                // check if operator is using vediamo-style variant-coding, where the SCN is set to 0000000000000000 when writing VC
                // otherwise, we can reuse the last value as read from the ECU
                bool useVediamoBehaviorZeroSCN = Preferences.GetValue(Preferences.PreferenceKey.EnableSCNZero) == "true";
                if (useVediamoBehaviorZeroSCN)
                {
                    for (int i = 0; i < originalValue.Length; i++)
                    {
                        originalValue[i] = 0x30;
                    }
                }

                Console.WriteLine($"Using {Encoding.ASCII.GetString(originalValue)} as new SCN value");

                // write-back the recognized (and optionally, modified) SCN
                Array.ConstrainedCopy(originalValue, 0, writeCommand, bytePosition, byteLength);
                preparationsToProcess.Remove(prep);
                break;
            }

            // isolate the fingerprint if it exists
            // normally fingerprint is appended at the tail of the VC command
            List <int> tailIndices = new List <int>()
            {
                writeCommand.Length - 1, writeCommand.Length - 2, writeCommand.Length - 3, writeCommand.Length - 4
            };
            List <DiagPreparation> possibleFingerprintFields = new List <DiagPreparation>();

            foreach (DiagPreparation prep in preparationsToProcess)
            {
                int bytePosition = prep.BitPosition / 8;
                int byteLength   = prep.SizeInBits / 8;

                if ((prep.FieldType == DiagPreparation.InferredDataType.IntegerType) && (byteLength == 1) && (tailIndices.Contains(bytePosition)))
                {
                    tailIndices.Remove(bytePosition);
                    possibleFingerprintFields.Add(prep);
                }
            }
            if (possibleFingerprintFields.Count == 4)
            {
                // copy in the fingerprint, and "mark" the constants as done
                byte[] fingerprint = priorReadCommand.Skip(priorReadCommand.Length - 4).ToArray();
                Console.WriteLine($"Found original fingerprint as {BitUtility.BytesToHex(fingerprint)}");

                // default behavior is to clone last fingerprint, else use stored fingerprint
                if (Preferences.GetValue(Preferences.PreferenceKey.EnableFingerprintClone) == "false")
                {
                    uint altFingerprintValue = uint.Parse(Preferences.GetValue(Preferences.PreferenceKey.FingerprintValue));
                    fingerprint[3]        = (byte)(altFingerprintValue & 0xFF);
                    altFingerprintValue >>= 8;
                    fingerprint[2]        = (byte)(altFingerprintValue & 0xFF);
                    altFingerprintValue >>= 8;
                    fingerprint[1]        = (byte)(altFingerprintValue & 0xFF);
                    altFingerprintValue >>= 8;
                    fingerprint[0]        = (byte)(altFingerprintValue & 0xFF);
                }

                Console.WriteLine($"Using {BitUtility.BytesToHex(fingerprint)} as new fingerprint value.");

                Array.ConstrainedCopy(fingerprint, 0, writeCommand, writeCommand.Length - 4, 4);

                foreach (DiagPreparation prep in possibleFingerprintFields)
                {
                    preparationsToProcess.Remove(prep);
                }
            }


            // at this point, whatever that's left in preparationsToProcess are stuff that are variable, but should be copied verbatim from the original read request (e.g. fingerprints, scn)
            // log the assumptions, show it the operator just in case
            StringBuilder assumptionsMade = new StringBuilder();

            if (preparationsToProcess.Count > 0)
            {
                if (writeCommand.Length != priorReadCommand.Length)
                {
                    MessageBox.Show("There are some preparations that do not have a default value. \r\n" +
                                    "The input and output values do not have matching lengths, which means that the automatic assumption may be wrong. \r\n" +
                                    "Please be very careful when proceeding.", "Warning");
                }

                foreach (DiagPreparation prep in preparationsToProcess)
                {
                    int bytePosition = prep.BitPosition / 8;
                    int byteLength   = prep.SizeInBits / 8;
                    Array.ConstrainedCopy(priorReadCommand, bytePosition, writeCommand, bytePosition, byteLength);
                    assumptionsMade.Append($"{prep.Qualifier} : {BitUtility.BytesToHex(priorReadCommand.Skip(bytePosition).Take(byteLength).ToArray(), true)}\r\n");
                }
            }

            /*
             * // lazy me dumping the values
             * for (int i = 0; i < vcForm.WriteService.InputPreparations.Count; i++)
             * {
             *  DiagPreparation prep = vcForm.WriteService.InputPreparations[i];
             *  Console.WriteLine($"debug: q: {prep.Qualifier} pos byte: {(prep.BitPosition / 8)} size bytes: {(prep.SizeInBits / 8)} modecfg:{prep.ModeConfig:X} fieldtype: {prep.FieldType} dump: {BitUtility.BytesToHex(prep.Dump, true)}");
             * }
             */

            // we are done preparing the command, if we are confident we can send the command straight to the ECU, else, let the user review
            if (assumptionsMade.Length > 0)
            {
                if (MessageBox.Show("Some assumptions were made when preparing the write parameters. \r\n\r\n" +
                                    "You may wish to review them by selecting Cancel, or select OK to execute the write command immediately.\r\n\r\n" + assumptionsMade.ToString(),
                                    "Review assumptions", MessageBoxButtons.OKCancel, MessageBoxIcon.Information) == DialogResult.OK)
                {
                    ExecVCWrite(writeCommand, vcForm.WriteService, connection, writesEnabled);
                }
                else
                {
                    runDiagForm.Result = writeCommand;
                    if (runDiagForm.ShowDialog() == DialogResult.OK)
                    {
                        ExecVCWrite(runDiagForm.Result, vcForm.WriteService, connection, writesEnabled);
                    }
                }
            }
            else
            {
                // everything accounted for, immediately write
                ExecVCWrite(writeCommand, vcForm.WriteService, connection, writesEnabled);
            }
        }