diff --git a/src/enginuity/io/protocol/Protocol.java b/src/enginuity/io/protocol/Protocol.java index 1ae5b073..457f375d 100644 --- a/src/enginuity/io/protocol/Protocol.java +++ b/src/enginuity/io/protocol/Protocol.java @@ -39,9 +39,11 @@ public interface Protocol { byte[] preprocessResponse(byte[] request, byte[] response); - void checkValidEcuInitResponse(byte[] bytes) throws InvalidResponseException; + byte[] parseResponseData(byte[] processedResponse); - EcuInit parseEcuInitResponse(byte[] response); + void checkValidEcuInitResponse(byte[] processedResponse) throws InvalidResponseException; + + EcuInit parseEcuInitResponse(byte[] processedResponse); ConnectionProperties getDefaultConnectionProperties(); } diff --git a/src/enginuity/io/protocol/SSMProtocol.java b/src/enginuity/io/protocol/SSMProtocol.java index 6d452d11..467d9deb 100644 --- a/src/enginuity/io/protocol/SSMProtocol.java +++ b/src/enginuity/io/protocol/SSMProtocol.java @@ -91,21 +91,24 @@ public final class SSMProtocol implements Protocol { return filterRequestFromResponse(request, response); } - public void checkValidEcuInitResponse(byte[] response) throws InvalidResponseException { + public byte[] parseResponseData(byte[] processedResponse) { + checkNotNullOrEmpty(processedResponse, "processedResponse"); + return extractResponseData(processedResponse); + } + + public void checkValidEcuInitResponse(byte[] processedResponse) throws InvalidResponseException { // response_header 3_unknown_bytes 5_ecu_id_bytes readable_params_switches... checksum // 80F01039FF A21011315258400673FACB842B83FEA800000060CED4FDB060000F200000000000DC0000551E30C0F222000040FB00E10000000000000000 59 - checkNotNullOrEmpty(response, "response"); - validateResponse(response); - byte responseType = response[4]; + checkNotNullOrEmpty(processedResponse, "processedResponse"); + validateResponse(processedResponse); + byte responseType = processedResponse[4]; if (responseType != ECU_INIT_RESPONSE) { throw new InvalidResponseException("Unexpected ECU Init response type: " + asHex(new byte[]{responseType})); } } - public EcuInit parseEcuInitResponse(byte[] response) { - checkNotNullOrEmpty(response, "response"); - byte[] responseData = extractResponseData(response); - return new SSMEcuInit(responseData); + public EcuInit parseEcuInitResponse(byte[] processedResponse) { + return new SSMEcuInit(parseResponseData(processedResponse)); } public ConnectionProperties getDefaultConnectionProperties() { diff --git a/src/enginuity/ramtune/test/RamTuneTestApp.java b/src/enginuity/ramtune/test/RamTuneTestApp.java index d36a3581..ff43dcc1 100644 --- a/src/enginuity/ramtune/test/RamTuneTestApp.java +++ b/src/enginuity/ramtune/test/RamTuneTestApp.java @@ -56,6 +56,7 @@ import java.awt.event.WindowListener; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; +import java.util.List; /* * This is a test app! Use at your own risk!! @@ -203,14 +204,15 @@ public final class RamTuneTestApp extends JFrame implements WindowListener { button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { - CommandExecutor commandExecutor = new CommandExecutorImpl(protocol.getDefaultConnectionProperties(), - (String) portsComboBox.getSelectedItem()); + CommandExecutor commandExecutor = new CommandExecutorImpl(protocol, (String) portsComboBox.getSelectedItem()); CommandGenerator commandGenerator = (CommandGenerator) commandComboBox.getSelectedItem(); if (validateInput(commandGenerator) && confirmCommandExecution(commandGenerator)) { - byte[] command = commandGenerator.createCommand(getAddress(), getData(), getLength()); - responseField.append("SND [" + commandGenerator + "]:\t" + asHex(command) + "\n"); - byte[] result = commandExecutor.executeCommand(command); - responseField.append("RCV [" + commandGenerator + "]:\t" + asHex(result) + "\n"); + List commands = commandGenerator.createCommands(getData(), getAddress(), getLength()); + for (byte[] command : commands) { + responseField.append("SND [" + commandGenerator + "]:\t" + asHex(command) + "\n"); + byte[] result = commandExecutor.executeCommand(command); + responseField.append("RCV [" + commandGenerator + "]:\t" + asHex(result) + "\n"); + } } } catch (Exception ex) { reportError(ex); diff --git a/src/enginuity/ramtune/test/command/executor/CommandExecutorImpl.java b/src/enginuity/ramtune/test/command/executor/CommandExecutorImpl.java index 1a46cc63..9171068a 100644 --- a/src/enginuity/ramtune/test/command/executor/CommandExecutorImpl.java +++ b/src/enginuity/ramtune/test/command/executor/CommandExecutorImpl.java @@ -1,41 +1,30 @@ package enginuity.ramtune.test.command.executor; -import enginuity.io.connection.ConnectionProperties; import enginuity.io.connection.EcuConnection; import enginuity.io.connection.EcuConnectionImpl; -import static enginuity.util.HexUtil.asBytes; -import static enginuity.util.HexUtil.asHex; +import enginuity.io.protocol.Protocol; import static enginuity.util.ParamChecker.checkNotNull; import static enginuity.util.ParamChecker.checkNotNullOrEmpty; public final class CommandExecutorImpl implements CommandExecutor { - private final ConnectionProperties connectionProperties; + private final Protocol protocol; private final String port; - public CommandExecutorImpl(ConnectionProperties connectionProperties, String port) { - checkNotNull(connectionProperties); + public CommandExecutorImpl(Protocol protocol, String port) { + checkNotNull(protocol); checkNotNullOrEmpty(port, "port"); - this.connectionProperties = connectionProperties; + this.protocol = protocol; this.port = port; } public byte[] executeCommand(byte[] command) { - EcuConnection ecuConnection = new EcuConnectionImpl(connectionProperties, port); + EcuConnection ecuConnection = new EcuConnectionImpl(protocol.getDefaultConnectionProperties(), port); try { - byte[] result = ecuConnection.send(command); - return stripCommandHeader(result, command); + byte[] response = ecuConnection.send(command); + return protocol.parseResponseData(protocol.preprocessResponse(command, response)); } finally { ecuConnection.close(); } } - private byte[] stripCommandHeader(byte[] result, byte[] command) { - String resultHex = asHex(result); - String commandHex = asHex(command); - if (resultHex.startsWith(commandHex)) { - return asBytes(resultHex.replaceFirst(commandHex, "")); - } else { - return result; - } - } } diff --git a/src/enginuity/ramtune/test/command/generator/CommandGenerator.java b/src/enginuity/ramtune/test/command/generator/CommandGenerator.java index 7148ebb8..1fa47214 100644 --- a/src/enginuity/ramtune/test/command/generator/CommandGenerator.java +++ b/src/enginuity/ramtune/test/command/generator/CommandGenerator.java @@ -1,7 +1,9 @@ package enginuity.ramtune.test.command.generator; +import java.util.List; + public interface CommandGenerator { - byte[] createCommand(byte[] address, byte[] data, int length); + List createCommands(byte[] data, byte[] address, int length); } diff --git a/src/enginuity/ramtune/test/command/generator/EcuInitCommandGenerator.java b/src/enginuity/ramtune/test/command/generator/EcuInitCommandGenerator.java index 2df01b6a..3924c106 100644 --- a/src/enginuity/ramtune/test/command/generator/EcuInitCommandGenerator.java +++ b/src/enginuity/ramtune/test/command/generator/EcuInitCommandGenerator.java @@ -2,14 +2,17 @@ package enginuity.ramtune.test.command.generator; import enginuity.io.protocol.Protocol; +import static java.util.Arrays.asList; +import java.util.List; + public final class EcuInitCommandGenerator extends AbstractCommandGenerator { public EcuInitCommandGenerator(Protocol protocol) { super(protocol); } - public byte[] createCommand(byte[] address, byte[] data, int length) { - return protocol.constructEcuInitRequest(); + public List createCommands(byte[] data, byte[] address, int length) { + return asList(protocol.constructEcuInitRequest()); } public String toString() { diff --git a/src/enginuity/ramtune/test/command/generator/ReadCommandGenerator.java b/src/enginuity/ramtune/test/command/generator/ReadCommandGenerator.java index 9b36034a..a7eb4ad7 100644 --- a/src/enginuity/ramtune/test/command/generator/ReadCommandGenerator.java +++ b/src/enginuity/ramtune/test/command/generator/ReadCommandGenerator.java @@ -4,16 +4,57 @@ import enginuity.io.protocol.Protocol; import static enginuity.util.ParamChecker.checkGreaterThanZero; import static enginuity.util.ParamChecker.checkNotNullOrEmpty; +import java.math.BigInteger; +import java.util.ArrayList; +import static java.util.Arrays.asList; +import java.util.List; + public final class ReadCommandGenerator extends AbstractCommandGenerator { + private static final int INCREMENT_SIZE = 32; public ReadCommandGenerator(Protocol protocol) { super(protocol); } - public byte[] createCommand(byte[] address, byte[] data, int length) { + public List createCommands(byte[] data, byte[] address, int length) { checkNotNullOrEmpty(address, "address"); checkGreaterThanZero(length, "length"); - return length == 1 ? protocol.constructReadAddressRequest(new byte[][]{address}) : protocol.constructReadMemoryRequest(address, length); + if (length == 1) { + return asList(createCommandForAddress(address)); + } else { + return createCommandsForRange(address, length); + } + } + + private byte[] createCommandForAddress(byte[] address) { + return protocol.constructReadAddressRequest(new byte[][]{address}); + } + + private List createCommandsForRange(byte[] address, int length) { + List commands = new ArrayList(); + byte[] readAddress = copy(address); + int i = 0; + while (i < length) { + int readLength = (length - i) > INCREMENT_SIZE ? INCREMENT_SIZE : length - i; + if (readLength == 1) { + commands.add(createCommandForAddress(readAddress)); + } else { + commands.add(protocol.constructReadMemoryRequest(readAddress, readLength)); + } + i += INCREMENT_SIZE; + System.arraycopy(incrementAddress(readAddress, readLength), 0, readAddress, 0, readAddress.length); + } + return commands; + } + + private byte[] copy(byte[] bytes) { + byte[] bytes2 = new byte[bytes.length]; + System.arraycopy(bytes, 0, bytes2, 0, bytes2.length); + return bytes2; + } + + private byte[] incrementAddress(byte[] address, int increment) { + return new BigInteger(address).add(new BigInteger(String.valueOf(increment))).toByteArray(); } public String toString() { diff --git a/src/enginuity/ramtune/test/command/generator/WriteCommandGenerator.java b/src/enginuity/ramtune/test/command/generator/WriteCommandGenerator.java index 60e853f7..7eb20c7d 100644 --- a/src/enginuity/ramtune/test/command/generator/WriteCommandGenerator.java +++ b/src/enginuity/ramtune/test/command/generator/WriteCommandGenerator.java @@ -3,16 +3,19 @@ package enginuity.ramtune.test.command.generator; import enginuity.io.protocol.Protocol; import static enginuity.util.ParamChecker.checkNotNullOrEmpty; +import static java.util.Arrays.asList; +import java.util.List; + public final class WriteCommandGenerator extends AbstractCommandGenerator { public WriteCommandGenerator(Protocol protocol) { super(protocol); } - public byte[] createCommand(byte[] address, byte[] data, int length) { + public List createCommands(byte[] data, byte[] address, int length) { checkNotNullOrEmpty(address, "address"); checkNotNullOrEmpty(data, "data"); - return protocol.constructWriteMemoryRequest(address, data); + return asList(protocol.constructWriteMemoryRequest(address, data)); } public String toString() { diff --git a/src/enginuity/util/ByteUtil.java b/src/enginuity/util/ByteUtil.java index 9bff5834..80f980a6 100644 --- a/src/enginuity/util/ByteUtil.java +++ b/src/enginuity/util/ByteUtil.java @@ -22,12 +22,14 @@ package enginuity.util; import enginuity.newmaps.ecumetadata.Scale; + import java.nio.ByteBuffer; @SuppressWarnings({"UnnecessaryBoxing"}) public final class ByteUtil { private ByteUtil() { + throw new UnsupportedOperationException(); } public static int asUnsignedInt(byte[] bytes, int endian) {