private void QueryDTC() { GenericLoader loader = new GenericLoader(); loader.Text = "Querying DTCs"; loader.Show(); Application.DoEvents(); // fetch the base dtc value first DTCContexts = Connection.ConnectionProtocol.ReportDtcsByStatusMask(Connection, Variant); loader.SetProgressMax(DTCContexts.Count); Application.DoEvents(); // query individual dtcs to retrieve the environment context for (int j = 0; j < DTCContexts.Count; j++) { DTCContext dtcCtx = DTCContexts[j]; loader.Text = $"Querying DTC {dtcCtx.DTC.Qualifier} [{j + 1}/{DTCContexts.Count}]"; loader.SetProgressValue(j); Application.DoEvents(); if (!Connection.ConnectionProtocol.GetDtcSnapshot(dtcCtx.DTC, Connection, out byte[] snapshot))
private void StartDownload() { int sumBytesTransferred = 0; int sumBytes = 0; foreach (FlashBlock block in FlashBlocks) { sumBytes += block.Payload.Length; } GenericLoader loader = new GenericLoader(); loader.Text = "Reading from ECU"; loader.TopMost = true; loader.Show(); Application.DoEvents(); foreach (FlashBlock block in FlashBlocks) { byte[] startDownloadCmd = CreateDownloadRequest(block.Address, (uint)block.Payload.Length); byte[] response = connection.SendMessage(startDownloadCmd); // comment this, uncomment below if dryrun //byte[] response = BitUtility.BytesFromHex("74 20 00 03"); if (response.Length < 2) { MessageBox.Show($"Error: ECU sent an incorrectly sized response when initiating download for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } if (response[0] != startDownloadCmd[0] + 0x40) { MessageBox.Show($"Error: ECU sent a non-positive response ({BitUtility.BytesToHex(response)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // read alfid to know memory size description's width byte rxAlfid = response[1]; // we are only expecting a size value if ((rxAlfid & 0xF) > 0) { MessageBox.Show($"Error: Could not understand ECU ALFID response ({BitUtility.BytesToHex(response)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // find out how wide the memory size description is int memSize = rxAlfid >> 4; List <byte> memBytes = response.Skip(2).Take(memSize).ToList(); if (memBytes.Count != memSize) { MessageBox.Show($"Error: Could not understand ECU ALFID response (size mismatch) ({BitUtility.BytesToHex(response)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // parse the memory size desc as a BE integer uint messageSize = 0; for (int i = 0; i < memBytes.Count; i++) { messageSize <<= 8; messageSize |= memBytes[i]; } // debug: uncomment to cap msg size at 0x100, normally 0xF02, blocksize = 0xF00 // messageSize = 0x102; int blockSize = (int)messageSize - 2; int totalBlockCount = (int)(block.Payload.Length / blockSize); int remainderBytes = block.Payload.Length % blockSize; if (remainderBytes != 0) { totalBlockCount++; } // reconfigure connection for block transfer connection.TesterPresentTimer.Enabled = false; RaiseSTMin(); byte[] dataBlock = new byte[messageSize]; loader.SetProgressMax(totalBlockCount); for (int blockCounter = 0; blockCounter < totalBlockCount; blockCounter++) { dataBlock[0] = 0x36; dataBlock[1] = (byte)((blockCounter + 1) & 0xFF); // if this is the last block, and there is a remainder block, write only the remainder if (((blockCounter + 1) == totalBlockCount) && (remainderBytes != 0)) { Array.ConstrainedCopy(block.Payload, blockCounter * blockSize, dataBlock, 2, remainderBytes); dataBlock = dataBlock.Take(2 + remainderBytes).ToArray(); } else { Array.ConstrainedCopy(block.Payload, blockCounter * blockSize, dataBlock, 2, blockSize); } byte[] transferResponse = connection.SendMessage(dataBlock); // comment this, uncomment below if dryrun //byte[] transferResponse = new byte[] { 0x76, 0x00 }; if ((transferResponse.Length > 0) && (transferResponse[0] == 0x76)) { // no need to check block index, if the ecu accepts it, continue } else { MessageBox.Show($"Error: Data transfer rejected by ECU ({BitUtility.BytesToHex(transferResponse)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } // update progress sumBytesTransferred += dataBlock.Length - 2; // loader.Text = $"Writing to ECU : 0x{sumBytesTransferred:X8} of 0x{sumBytes:X8}"; loader.Text = $"Writing to ECU : block {blockCounter} of 0x{totalBlockCount}"; loader.SetProgressValue(blockCounter); Application.DoEvents(); // fixme: show two progressbars, one for the block# and another for the individual block's % } byte[] exitTransferResponse = connection.SendMessage(new byte[] { 0x37 });// ------------------ patch if debugging if (!((exitTransferResponse.Length > 0) && (exitTransferResponse[0] == 0x77))) { MessageBox.Show($"Error: Exit transfer rejected by ECU ({BitUtility.BytesToHex(exitTransferResponse)}) for block {Path.GetFileNameWithoutExtension(block.Path)}"); break; } } // restore prior connection status connection.TesterPresentTimer.Enabled = true; ResetSTMin(); loader.Close(); MessageBox.Show("Download completed"); }
private void btnRead_Click(object sender, EventArgs e) { if (!FetchAndValidateInput(out uint sourceAddress, out uint destinationAddress, out uint bufferSize)) { return; } int strideWidth = decimal.ToInt32(nudIOWidth.Value); int addressWidth = decimal.ToInt32(nudAddressWidth.Value); int ioDigitCount = GetMemoryDigitCount(strideWidth); byte readCmd = decimal.ToByte(nudReadCmd.Value); byte positiveResponse = (byte)(readCmd + 0x40); byte alfid = GetAddressAndLengthFormatIdentifier( addressWidth, ioDigitCount ); GenericLoader loader = new GenericLoader(); loader.Text = "Reading from ECU"; loader.SetProgressMax((int)(destinationAddress - sourceAddress)); loader.SetProgressValue(0); loader.TopMost = true; loader.Show(); Application.DoEvents(); byte[] memoryBuffer = new byte[bufferSize]; uint readCursor = sourceAddress; int bufferCursor = 0; bool hasBadReads = false; while (readCursor < destinationAddress) { loader.Text = $"Reading from ECU : 0x{readCursor:X8}"; loader.SetProgressValue((int)(readCursor - sourceAddress)); Application.DoEvents(); uint remainder = destinationAddress - readCursor; int readSize = strideWidth; if (readSize > remainder) { readSize = (int)remainder; } List <byte> readCommand = CreateReadCommand(readCmd, alfid, readCursor, addressWidth, readSize); byte[] response = Connection.SendMessage(readCommand); if (response[0] == positiveResponse) { Array.ConstrainedCopy(response, 1, memoryBuffer, bufferCursor, readSize); } else { hasBadReads = true; } readCursor += (uint)readSize; bufferCursor += readSize; } loader.Close(); Application.DoEvents(); OriginalBuffer = memoryBuffer; Hexbox.LineInfoOffset = sourceAddress; Hexbox.ByteProvider = new DynamicByteProvider(OriginalBuffer); if (hasBadReads) { MessageBox.Show("One or more read requests were rejected by the ECU, and the empty blocks were substituted with zeros. \r\n\r\n" + "Please check if the memory address is valid to the ECU, and if the ECU has been unlocked if required.\r\n\r\n" + "If the memory region has protected bytes, consider loading a smaller, more specific range with a I/O width of 1 to skip past the protected bytes.", "Warning: Invalid reads"); } }