DS2 protocol implmentation

This commit is contained in:
Dale Schultz 2014-12-22 23:02:37 -05:00
parent b56a0637d1
commit 41b5bc5c9f
9 changed files with 915 additions and 2 deletions

View File

@ -0,0 +1,32 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.io.protocol;
import com.romraider.logger.ecu.definition.Module;
public interface ProtocolDS2 extends Protocol {
byte[] constructReadGroupRequest(Module module, byte[][] addresses);
byte[] constructReadMemoryRequest(
Module module, byte[][] convertToByteAddresses, int length);
}

View File

@ -0,0 +1,36 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.io.protocol.ds2.iso9141;
public final class DS2ChecksumCalculator {
private DS2ChecksumCalculator() {
throw new UnsupportedOperationException();
}
public static byte calculateChecksum(byte[] bytes) {
byte cs = 0;
for (int i = 0; i < (bytes.length - 1); i++) {
cs ^= bytes[i];
}
return cs;
}
}

View File

@ -0,0 +1,235 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.io.protocol.ds2.iso9141;
import static com.romraider.io.protocol.ds2.iso9141.DS2Protocol.RESPONSE_NON_DATA_BYTES;
import static com.romraider.io.protocol.ds2.iso9141.DS2ResponseProcessor.extractResponseData;
import static com.romraider.io.protocol.ds2.iso9141.DS2ResponseProcessor.filterRequestFromResponse;
import static com.romraider.util.HexUtil.asBytes;
import static com.romraider.util.ParamChecker.checkNotNull;
import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
import static java.lang.System.arraycopy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import com.romraider.io.protocol.Protocol;
import com.romraider.io.protocol.ProtocolDS2;
import com.romraider.logger.ecu.comms.io.protocol.LoggerProtocolDS2;
import com.romraider.logger.ecu.comms.manager.PollingState;
import com.romraider.logger.ecu.comms.query.EcuInit;
import com.romraider.logger.ecu.comms.query.EcuInitCallback;
import com.romraider.logger.ecu.comms.query.EcuQuery;
import com.romraider.logger.ecu.definition.EcuData;
import com.romraider.logger.ecu.definition.Module;
public final class DS2LoggerProtocol implements LoggerProtocolDS2 {
private final ProtocolDS2 protocol = new DS2Protocol();
@Override
public byte[] constructEcuInitRequest(Module module) {
return protocol.constructEcuInitRequest(module);
}
@Override
public byte[] constructEcuResetRequest(Module module) {
return protocol.constructEcuResetRequest(module);
}
@Override
public byte[] constructReadAddressRequest(
Module module, Collection<EcuQuery> queries) {
Collection<EcuQuery> filteredQueries = filterDuplicates(queries);
return protocol.constructReadAddressRequest(
module, convertToByteAddresses(filteredQueries));
}
@Override
public byte[] constructReadGroupRequest(
Module module, String group) {
return protocol.constructReadGroupRequest(
module, new byte[][]{asBytes(group)});
}
@Override
public byte[] constructReadMemoryRequest(
Module module, Collection<EcuQuery> queries) {
Collection<EcuQuery> filteredQueries = filterDuplicates(queries);
return protocol.constructReadMemoryRequest(
module, convertToByteAddresses(filteredQueries), getDataLength(filteredQueries));
}
@Override
public byte[] constructReadAddressResponse(Collection<EcuQuery> queries,
PollingState pollState) {
return null;
}
@Override
public byte[] constructReadAddressResponse(
Collection<EcuQuery> queries, int requestSize) {
checkNotNullOrEmpty(queries, "queries");
Collection<EcuQuery> filteredQueries = filterDuplicates(queries);
int numAddresses = 0;
for (EcuQuery ecuQuery : filteredQueries) {
numAddresses += getDataLength(ecuQuery);
}
return new byte[requestSize + RESPONSE_NON_DATA_BYTES + numAddresses];
}
@Override
public byte[] constructReadGroupResponse(
Collection<EcuQuery> queries, int requestSize) {
checkNotNullOrEmpty(queries, "queries");
int size = 0;
for (EcuQuery ecuQuery : queries) {
size = ((EcuData) ecuQuery.getLoggerData()).getGroupSize();
break;
}
return new byte[requestSize + RESPONSE_NON_DATA_BYTES + size];
}
@Override
public byte[] preprocessResponse(byte[] request, byte[] response, PollingState pollState) {
return filterRequestFromResponse(request, response, pollState);
}
@Override
public void processEcuInitResponse(EcuInitCallback callback, byte[] response) {
checkNotNull(callback, "callback");
checkNotNullOrEmpty(response, "response");
protocol.checkValidEcuInitResponse(response);
EcuInit ecuInit = protocol.parseEcuInitResponse(response);
callback.callback(ecuInit);
}
@Override
public void processEcuResetResponse(byte[] response) {
checkNotNullOrEmpty(response, "response");
protocol.checkValidEcuResetResponse(response);
}
// processes the response bytes and sets individual responses on corresponding query objects
@Override
public void processReadAddressResponses(Collection<EcuQuery> queries, byte[] response, PollingState pollState) {
checkNotNullOrEmpty(queries, "queries");
checkNotNullOrEmpty(response, "response");
byte[] responseData = extractResponseData(response);
Collection<EcuQuery> filteredQueries = filterDuplicates(queries);
Map<String, byte[]> addressResults = new HashMap<String, byte[]>();
for (EcuQuery filteredQuery : filteredQueries) {
byte[] bytes = new byte[getDataLength(filteredQuery)];
arraycopy(responseData, filteredQuery.getBytes()[0], bytes, 0, bytes.length);
addressResults.put(filteredQuery.getHex(), bytes);
}
for (EcuQuery query : queries) {
query.setResponse(addressResults.get(query.getHex()));
}
}
@Override
public Protocol getProtocol() {
return protocol;
}
@Override
public byte[] constructWriteAddressRequest(
Module module, byte[] writeAddress, byte value) {
return protocol.constructWriteAddressRequest(module, writeAddress, value);
}
@Override
public void processWriteResponse(byte[] data, byte[] response) {
checkNotNullOrEmpty(data, "data");
checkNotNullOrEmpty(response, "response");
protocol.checkValidWriteResponse(data, response);
}
private Collection<EcuQuery> filterDuplicates(Collection<EcuQuery> queries) {
Collection<EcuQuery> filteredQueries = new ArrayList<EcuQuery>();
for (EcuQuery query : queries) {
if (!filteredQueries.contains(query)) {
filteredQueries.add(query);
}
}
return filteredQueries;
}
private byte[][] convertToByteAddresses(Collection<EcuQuery> queries) {
int byteCount = 0;
int addressSize = 0;
for (EcuQuery query : queries) {
byteCount += query.getAddresses().length;
addressSize = query.getBytes().length;
}
final byte[][] addresses = new byte[byteCount][addressSize];
int i = 0;
for (EcuQuery query : queries) {
final int addrLength = query.getBytes().length;
final byte[] bytes = query.getBytes();
for (int j = 0; j < bytes.length / addrLength; j++) {
arraycopy(bytes, j * addrLength, addresses[i++], 0, addrLength);
}
}
return addresses;
}
private int getDataLength(EcuQuery ecuQuery) {
int dataLength = 1;
final String dataType =
ecuQuery.getLoggerData().getSelectedConvertor().getDataType().toLowerCase();
if (dataType.contains("int16")) {
dataLength = 2;
}
else if (dataType.contains("int32") ||
dataType.contains("float")) {
dataLength = 4;
}
return dataLength;
}
private int getDataLength(Collection<EcuQuery> queries) {
int dataLength = 0;
for (EcuQuery query : queries) {
final String dataType =
query.getLoggerData().getSelectedConvertor().getDataType().toLowerCase();
if (dataType.contains("int16")) {
dataLength += 2;
}
else if (dataType.contains("int32") ||
dataType.contains("float")) {
dataLength += 4;
}
else {
dataLength += 1;
}
}
return dataLength;
}
}

View File

@ -0,0 +1,231 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.io.protocol.ds2.iso9141;
import static com.romraider.io.protocol.ds2.iso9141.DS2ChecksumCalculator.calculateChecksum;
import static com.romraider.util.ByteUtil.asByte;
import static com.romraider.util.HexUtil.asHex;
import static com.romraider.util.ParamChecker.checkGreaterThanZero;
import static com.romraider.util.ParamChecker.checkNotNull;
import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import com.romraider.io.connection.ConnectionProperties;
import com.romraider.io.protocol.ProtocolDS2;
import com.romraider.logger.ecu.comms.manager.PollingState;
import com.romraider.logger.ecu.comms.query.DS2EcuInit;
import com.romraider.logger.ecu.comms.query.EcuInit;
import com.romraider.logger.ecu.definition.Module;
import com.romraider.logger.ecu.exception.InvalidResponseException;
import com.romraider.logger.ecu.exception.UnsupportedProtocolException;
public final class DS2Protocol implements ProtocolDS2 {
public static final byte[] READ_MEMORY_COMMAND = new byte[]{0x06, 0x00};
public static final byte[] READ_ADDRESS_COMMAND = new byte[]{0x0B, 0x02, 0x0e};
public static final byte[] WRITE_MEMORY_COMMAND = new byte[]{(byte) 0xB0};
public static final byte[] WRITE_MEMORY_RESPONSE = new byte[]{(byte) 0xF0};
public static final byte[] WRITE_ADDRESS_COMMAND = new byte[]{(byte) 0xB8};
public static final byte[] WRITE_ADDRESS_RESPONSE = new byte[]{(byte) 0xF8};
public static final byte[] ECU_INIT_COMMAND = new byte[]{0x00};
public static final byte VALID_RESPONSE = (byte) 0xA0;
public static final int ADDRESS_SIZE = 3;
public static final int DATA_SIZE = 1;
public static final int RESPONSE_NON_DATA_BYTES = 4;
public static Module module;
private final ByteArrayOutputStream bb = new ByteArrayOutputStream(255);
@Override
public byte[] constructEcuInitRequest(Module module) {
checkNotNull(module, "module");
DS2Protocol.module = module;
// 0x12 0x04 0x00 0x16
return buildRequest(ECU_INIT_COMMAND, new byte[0], new byte[0]);
}
@Override
public byte[] constructWriteMemoryRequest(
Module module, byte[] address, byte[] values) {
throw new UnsupportedProtocolException(
"Write memory command is not supported on DS2 for address: " +
asHex(address));
}
@Override
public byte[] constructWriteAddressRequest(
Module module, byte[] address, byte value) {
throw new UnsupportedProtocolException(
"Write Address command is not supported on DS2 for address: " +
asHex(address));
}
@Override
public byte[] constructReadMemoryRequest(
Module module, byte[] address, int numBytes) {
return constructReadMemoryRequest(
module, new byte[][]{address}, numBytes);
}
@Override
public byte[] constructReadMemoryRequest(
Module module, byte[][] address, int numBytes) {
checkNotNull(module, "module");
checkNotNullOrEmpty(address, "address");
checkGreaterThanZero(numBytes, "numBytes");
// 0x12 0x09 0x06 <seg> <from_address> <num_bytes>
return buildRequest(
READ_MEMORY_COMMAND, new byte[]{asByte(numBytes)}, address);
}
@Override
public byte[] constructReadAddressRequest(
Module module, byte[][] addresses) {
checkNotNull(module, "module");
checkNotNullOrEmpty(addresses, "addresses");
// 0x12 data_length group subgroup [address] checksum
return buildRequest(READ_ADDRESS_COMMAND, new byte[0], addresses);
}
public byte[] constructReadGroupRequest(
Module module, byte[][] addresses) {
checkNotNull(module, "module");
checkNotNullOrEmpty(addresses, "addresses");
// 0x12 data_length group subgroup checksum
return buildRequest(new byte[0], new byte[0], addresses);
}
@Override
public byte[] preprocessResponse(byte[] request, byte[] response, PollingState pollState) {
return DS2ResponseProcessor.filterRequestFromResponse(request, response, pollState);
}
@Override
public byte[] parseResponseData(byte[] processedResponse) {
checkNotNullOrEmpty(processedResponse, "processedResponse");
return DS2ResponseProcessor.extractResponseData(processedResponse);
}
@Override
public void checkValidEcuInitResponse(byte[] processedResponse) {
// 12 2e a0 31343337383036 3131303133303231323239363030303031313538353236303030393632313432353634 9c
checkNotNullOrEmpty(processedResponse, "processedResponse");
DS2ResponseProcessor.validateResponse(processedResponse);
}
@Override
public EcuInit parseEcuInitResponse(byte[] processedResponse) {
return new DS2EcuInit(parseResponseData(processedResponse));
}
@Override
public final byte[] constructEcuResetRequest(Module module) {
// 80 10 F0 05 B8 00 00 60 40 DD
checkNotNull(module, "module");
final byte[] resetAddress = new byte[]{
(byte) 0x00, (byte) 0x00, (byte) 0x60};
final byte reset = 0x40;
return constructWriteAddressRequest(module, resetAddress, reset);
}
@Override
public void checkValidEcuResetResponse(byte[] processedResponse) {
// 80 F0 10 02 F8 40 BA
checkNotNullOrEmpty(processedResponse, "processedResponse");
DS2ResponseProcessor.validateResponse(processedResponse);
byte responseType = processedResponse[4];
if (responseType != WRITE_ADDRESS_RESPONSE[0] || processedResponse[5] != (byte) 0x40) {
throw new InvalidResponseException("Unexpected " + module.getName() +
" Reset response: " + asHex(processedResponse));
}
}
@Override
public void checkValidWriteResponse(byte[] data, byte[] processedResponse) {
}
@Override
public ConnectionProperties getDefaultConnectionProperties() {
return new ConnectionProperties() {
public int getBaudRate() {
return 9600;
}
public void setBaudRate(int b) {
}
public int getDataBits() {
return 8;
}
public int getStopBits() {
return 1;
}
public int getParity() {
return 2;
}
public int getConnectTimeout() {
return 2000;
}
public int getSendTimeout() {
return 55;
}
};
}
private final byte[] buildRequest(
byte[] command, byte[] readLen, byte[]... content) {
byte[] request = new byte[0];
try {
int length = 3;
for (byte[] tmp : content) {
length += tmp.length;
}
length += command.length;
length += readLen.length;
bb.reset();
bb.write(module.getAddress());
bb.write((byte) length);
bb.write(command);
for (byte[] tmp : content) {
bb.write(tmp);
}
if (readLen.length > 0) {
bb.write(readLen);
}
bb.write((byte) 0x00);
request = bb.toByteArray();
final byte cs = calculateChecksum(request);
request[request.length - 1] = cs;
} catch (IOException e) {
e.printStackTrace();
}
return request;
}
}

View File

@ -0,0 +1,87 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.io.protocol.ds2.iso9141;
import static com.romraider.io.protocol.ds2.iso9141.DS2ChecksumCalculator.calculateChecksum;
import static com.romraider.io.protocol.ds2.iso9141.DS2Protocol.RESPONSE_NON_DATA_BYTES;
import static com.romraider.io.protocol.ds2.iso9141.DS2Protocol.VALID_RESPONSE;
import static com.romraider.io.protocol.ds2.iso9141.DS2Protocol.module;
import static com.romraider.util.ByteUtil.asByte;
import static com.romraider.util.HexUtil.asHex;
import static com.romraider.util.ParamChecker.checkNotNull;
import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
import com.romraider.logger.ecu.comms.manager.PollingState;
import com.romraider.logger.ecu.exception.InvalidResponseException;
public final class DS2ResponseProcessor {
private DS2ResponseProcessor() {
throw new UnsupportedOperationException();
}
public static byte[] filterRequestFromResponse(byte[] request, byte[] response, PollingState pollState) {
checkNotNull(request, "request");
checkNotNullOrEmpty(response, "response");
checkNotNull(pollState, "pollState");
byte[] filteredResponse = new byte[0];
if (pollState.getCurrentState() == 0) {
filteredResponse = new byte[response.length - request.length];
System.arraycopy(response, request.length, filteredResponse, 0, filteredResponse.length);
}
if (pollState.getCurrentState() == 1) {
filteredResponse = new byte[response.length];
System.arraycopy(response, 0, filteredResponse, 0, filteredResponse.length);
}
return filteredResponse;
}
public static void validateResponse(byte[] response) {
int i = 0;
assertTrue(response.length > RESPONSE_NON_DATA_BYTES, "Invalid response length");
assertEquals(module.getAddress()[0], response[i++], "Invalid " + module.getName() + " id");
assertEquals(asByte(response.length), response[i++], "Invalid response packet length");
assertEquals(VALID_RESPONSE, response[i], "Invalid response");
assertEquals(calculateChecksum(response), response[response.length - 1], "Invalid checksum");
}
public static byte[] extractResponseData(byte[] response) {
checkNotNullOrEmpty(response, "response");
// 12 <length> a0 <bytes> <checksum>
validateResponse(response);
byte[] data = new byte[response.length - RESPONSE_NON_DATA_BYTES];
System.arraycopy(response, (RESPONSE_NON_DATA_BYTES - 1), data, 0, data.length);
return data;
}
private static void assertTrue(boolean condition, String msg) {
if (!condition) {
throw new InvalidResponseException(msg);
}
}
private static void assertEquals(byte expected, byte actual, String msg) {
if (actual != expected) {
throw new InvalidResponseException(msg + ". Expected: " + asHex(new byte[]{expected}) + ". Actual: " + asHex(new byte[]{actual}) + ".");
}
}
}

View File

@ -0,0 +1,205 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.ecu.comms.io.connection;
import static com.romraider.util.HexUtil.asHex;
import static com.romraider.util.ParamChecker.checkNotNull;
import static org.apache.log4j.Logger.getLogger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import org.apache.log4j.Logger;
import com.romraider.Settings;
import com.romraider.io.connection.ConnectionManager;
import com.romraider.io.protocol.ProtocolFactory;
import com.romraider.logger.ecu.comms.io.protocol.LoggerProtocolDS2;
import com.romraider.logger.ecu.comms.manager.PollingState;
import com.romraider.logger.ecu.comms.manager.PollingStateImpl;
import com.romraider.logger.ecu.comms.query.EcuInitCallback;
import com.romraider.logger.ecu.comms.query.EcuQuery;
import com.romraider.logger.ecu.definition.EcuData;
import com.romraider.logger.ecu.definition.Module;
import com.romraider.util.SettingsManager;
public final class DS2LoggerConnection implements LoggerConnection {
private static final Logger LOGGER = getLogger(DS2LoggerConnection.class);
private final LoggerProtocolDS2 protocol;
private final ConnectionManager manager;
Settings settings = SettingsManager.getSettings();
public DS2LoggerConnection(ConnectionManager manager) {
checkNotNull(manager, "manager");
this.manager = manager;
this.protocol = (LoggerProtocolDS2) ProtocolFactory.getProtocol(
settings.getLoggerProtocol(),
settings.getTransportProtocol());
}
@Override
public void ecuReset(Module module) {
byte[] request = protocol.constructEcuResetRequest(module);
LOGGER.debug("ECU Reset Request ---> " + asHex(request));
byte[] response = manager.send(request);
byte[] processedResponse = protocol.preprocessResponse(request, response, new PollingStateImpl());
LOGGER.debug("ECU Reset Response <--- " + asHex(processedResponse));
protocol.processEcuResetResponse(processedResponse);
}
@Override
public void ecuInit(EcuInitCallback callback, Module module) {
byte[] request = protocol.constructEcuInitRequest(module);
LOGGER.debug("ECU Init Request ---> " + asHex(request));
byte[] response = manager.send(request);
LOGGER.trace("ECU Init Raw Response <--- " + asHex(response));
byte[] processedResponse = protocol.preprocessResponse(request, response, new PollingStateImpl());
LOGGER.debug("ECU Init Response <--- " + asHex(processedResponse));
protocol.processEcuInitResponse(callback, processedResponse);
}
@Override
public final void sendAddressReads(
Collection<EcuQuery> queries,
Module module,
PollingState pollState) {
final Map<String, Collection<EcuQuery>> groupList = getGroupList(queries);
for (String group : groupList.keySet().toArray(new String[0])) {
final Collection<EcuQuery> querySet = groupList.get(group);
byte[] request = new byte[0];
byte[] response = new byte[0];
if (group.equalsIgnoreCase("0x0b0x020e")) {
for (EcuQuery query : querySet) {
final Collection<EcuQuery> queryList = new ArrayList<EcuQuery>();
queryList.add(query);
request = protocol.constructReadAddressRequest(
module, queryList);
LOGGER.debug("Mode:" + pollState.getCurrentState() +
" ECU Request ---> " + asHex(request));
response = protocol.constructReadAddressResponse(
queryList, request.length);
protocol.processReadAddressResponses(
queryList,
sendRcv(request, response, pollState),
pollState);
}
}
else if (group.equalsIgnoreCase("0x060x00")) {
for (EcuQuery query : querySet) {
final Collection<EcuQuery> queryList = new ArrayList<EcuQuery>();
queryList.add(query);
request = protocol.constructReadMemoryRequest(
module, queryList);
LOGGER.debug("Mode:" + pollState.getCurrentState() +
" ECU Request ---> " + asHex(request));
response = protocol.constructReadAddressResponse(
queryList, request.length);
protocol.processReadAddressResponses(
queryList,
sendRcv(request, response, pollState),
pollState);
}
}
else {
request = protocol.constructReadGroupRequest(
module, group);
LOGGER.debug("Mode:" + pollState.getCurrentState() +
" ECU Request ---> " + asHex(request));
response = protocol.constructReadGroupResponse(
querySet, request.length);
protocol.processReadAddressResponses(
querySet,
sendRcv(request, response, pollState),
pollState);
}
}
}
@Override
public void clearLine() {
manager.clearLine();
}
@Override
public void close() {
manager.close();
}
@Override
public final void sendAddressWrites(
Map<EcuQuery, byte[]> writeQueries, Module module) {
for (EcuQuery writeKey : writeQueries.keySet()) {
if (writeKey.getBytes().length == 3) {
final byte[] request =
protocol.constructWriteAddressRequest(
module,
writeKey.getBytes(),
writeQueries.get(writeKey)[0]);
LOGGER.debug("ECU Write Request ---> " + asHex(request));
final byte[] response = manager.send(request);
byte[] processedResponse =
protocol.preprocessResponse(
request,
response,
new PollingStateImpl());
LOGGER.debug("ECU Write Response <--- " + asHex(processedResponse));
protocol.processWriteResponse(
writeQueries.get(writeKey), processedResponse);
}
}
}
// Create a map of groups each with a value of a list of queries having the same group
private Map<String, Collection<EcuQuery>> getGroupList(Collection<EcuQuery> queries) {
final Map<String, Collection<EcuQuery>> groups = new HashMap<String, Collection<EcuQuery>>();
String group;
String subGroup;
for (EcuQuery query : queries) {
group = ((EcuData) query.getLoggerData()).getGroup();
subGroup = ((EcuData) query.getLoggerData()).getSubgroup();
group = group + (subGroup == null ? "" : subGroup);
if (!groups.containsKey(group)) {
final Collection<EcuQuery> queryList = new ArrayList<EcuQuery>();
queryList.add(query);
groups.put(group, queryList);
}
else {
groups.get(group).add(query);
}
}
return groups;
}
private byte[] sendRcv(byte[] request, byte[] response, PollingState pollState) {
manager.send(request, response, pollState);
LOGGER.trace("ECU Read Raw Response <--- " + asHex(response));
final byte[] processedResponse = protocol.preprocessResponse(
request, response, pollState);
LOGGER.debug("Mode:" + pollState.getCurrentState() +
" ECU Response <--- " + asHex(processedResponse));
return processedResponse;
}
}

View File

@ -0,0 +1,42 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.ecu.comms.io.protocol;
import java.util.Collection;
import com.romraider.logger.ecu.comms.query.EcuQuery;
import com.romraider.logger.ecu.definition.Module;
public interface LoggerProtocolDS2 extends LoggerProtocol {
byte[] constructReadGroupRequest(
Module module, String group);
byte[] constructReadGroupResponse(
Collection<EcuQuery> queries, int requestSize);
byte[] constructReadAddressResponse(
Collection<EcuQuery> queries, int requestSize);
byte[] constructReadMemoryRequest(
Module module, Collection<EcuQuery> queryList);
}

View File

@ -0,0 +1,45 @@
/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2014 RomRaider.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package com.romraider.logger.ecu.comms.query;
import static com.romraider.util.ParamChecker.checkNotNullOrEmpty;
import static java.lang.System.arraycopy;
public final class DS2EcuInit implements EcuInit {
private byte[] ecuInitBytes;
private String ecuId;
public DS2EcuInit(byte[] ecuInitBytes) {
checkNotNullOrEmpty(ecuInitBytes, "ecuInitBytes");
this.ecuInitBytes = ecuInitBytes;
final byte[] ecuIdBytes = new byte[7];
arraycopy(ecuInitBytes, 0, ecuIdBytes, 0, 7);
ecuId = new String(ecuIdBytes);
}
public String getEcuId() {
return ecuId;
}
public byte[] getEcuInitBytes() {
return ecuInitBytes;
}
}

View File

@ -22,9 +22,9 @@ version.major=0
version.minor=5
version.patch=8
version.buildnumber=635
version.extra=RC
version.extra=DS2
version.extra1=1
min.logger.def.version=155
min.logger.def.version=291
# the starting class for the application
class.start=com.romraider.ECUExec