/*
* RomRaider Open-Source Tuning, Logging and Reflashing
* Copyright (C) 2006-2015 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.Map;
import org.apache.log4j.Logger;
import com.romraider.Settings;
import com.romraider.util.SettingsManager;
import com.romraider.io.connection.ConnectionManager;
import com.romraider.io.protocol.ProtocolFactory;
import com.romraider.logger.ecu.comms.io.protocol.LoggerProtocolOBD;
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.Module;
public final class OBDLoggerConnection implements LoggerConnection {
private static final Logger LOGGER = getLogger(OBDLoggerConnection.class);
private final LoggerProtocolOBD protocol;
private final ConnectionManager manager;
private Collection<EcuQuery> obdQueries = new ArrayList<EcuQuery>();
public OBDLoggerConnection(ConnectionManager manager) {
checkNotNull(manager, "manager");
this.manager = manager;
final Settings settings = SettingsManager.getSettings();
this.protocol = (LoggerProtocolOBD) ProtocolFactory.getProtocol(
settings.getLoggerProtocol(),
settings.getTransportProtocol());
}
@Override
public void ecuReset(Module module, int resetCode) {
byte[] request = protocol.constructEcuResetRequest(module, resetCode);
LOGGER.debug(String.format("%s Reset Request ---> %s",
module, asHex(request)));
byte[] response = manager.send(request);
byte[] processedResponse = protocol.preprocessResponse(
request, response, new PollingStateImpl());
LOGGER.debug(String.format("%s Reset Response <--- %s",
module, asHex(processedResponse)));
protocol.processEcuResetResponse(processedResponse);
}
@Override
// Build an init string similar to the SSM version so the logger definition
// can reference supported parameters with ecubyte/bit attributes.
public void ecuInit(EcuInitCallback callback, Module module) {
final byte[] processedResponse = new byte[46];
final byte[] request = protocol.constructEcuInitRequest(module);
LOGGER.debug(String.format("%s Calibration ID Request ---> %s",
module, asHex(request)));
final byte[] tmp = manager.send(request);
final byte[] response = protocol.preprocessResponse(
request, tmp, new PollingStateImpl());
LOGGER.debug(String.format("%s Calibration ID Response <--- %s",
module, asHex(response)));
System.arraycopy(response, 0, processedResponse, 0, response.length);
int j = 7;
while (response[j] != 0 && j < response.length) { j++; }
final byte[] calIdStr = new byte[j - 7];
System.arraycopy(response, 7, calIdStr, 0, j - 7);
System.arraycopy(calIdStr, 0, processedResponse, 5, 8);
LOGGER.info(String.format("%s Calibration ID: %s", module, new String(calIdStr)));
final byte[] supportedPidsPid = {
(byte) 0x00, (byte) 0x20, (byte) 0x40, (byte) 0x60,
(byte) 0x80, (byte) 0xA0, (byte) 0xC0, (byte) 0xE0};
int i = 13;
for (byte pid : supportedPidsPid) {
final byte[] pidRequest = protocol.constructReadPidRequest(
module, new byte[]{pid});
LOGGER.debug(String.format("%s PID Group %02X Request ---> %s",
module, pid, asHex(pidRequest)));
final byte[] pidtmp = manager.send(pidRequest);
final byte[] pidPpResponse = protocol.preprocessResponse(
pidRequest, pidtmp, new PollingStateImpl());
LOGGER.debug(String.format("%s PID Group %02X Response <--- %s",
module, pid, asHex(pidPpResponse)));
System.arraycopy(pidPpResponse, 6, processedResponse, i, 4);
i = i + 4;
if ((pidPpResponse[pidPpResponse.length - 1] & 0x01) == 0) break;
}
// Check if PID 0x65 is supported and if so read it to obtain the Aux
// Input support bits. Map the first byte into the init string. This
// byte can be referenced as byte 40 by the ecubyte/bit attributes in
// the logger definition to indicate supported switches.
if ((processedResponse[25] & 0x08) > 0) {
final byte[] aiRequest = protocol.constructReadPidRequest(
module, new byte[]{0x65});
LOGGER.debug(String.format(
"%s Auxiliary Inputs Support Request ---> %s",
module, asHex(aiRequest)));
final byte[] aiResponse = manager.send(aiRequest);
final byte[] aiPpResponse = protocol.preprocessResponse(
aiRequest, aiResponse, new PollingStateImpl());
LOGGER.debug(String.format(
"%s Auxiliary Inputs Support Response <--- %s",
module, asHex(aiPpResponse)));
System.arraycopy(aiPpResponse, 6, processedResponse, 45, 1);
}
LOGGER.debug(String.format("%s Init Response <--- %s",
module, asHex(processedResponse))); // contains CALID not ECUID
protocol.processEcuInitResponse(callback, processedResponse);
}
@Override
public final void sendAddressReads(
Collection<EcuQuery> queries,
Module module,
PollingState pollState) {
final int obdQueryListLength = queries.size();
for (int i = 0; i < obdQueryListLength; i += 6) {
for (int j = i; (j < i + 6) && (j < obdQueryListLength); j++) {
obdQueries.add(((ArrayList<EcuQuery>) queries).get(j));
}
final byte[] request = protocol.constructReadAddressRequest(
module, obdQueries);
LOGGER.debug(String.format("Mode:%d %s Request ---> %s",
pollState.getCurrentState(), module, asHex(request)));
final byte[] response = protocol.constructReadAddressResponse(
obdQueries, pollState);
manager.send(request, response, pollState);
final byte[] processedResponse = protocol.preprocessResponse(
request, response, pollState);
LOGGER.debug(String.format("Mode:%d %s Response <--- %s",
pollState.getCurrentState(), module, asHex(processedResponse)));
protocol.processReadAddressResponses(
obdQueries, processedResponse, pollState);
obdQueries.clear();
}
}
@Override
public void clearLine() {
manager.clearLine();
}
@Override
public void close() {
manager.close();
}
@Override
public void sendAddressWrites(Map<EcuQuery, byte[]> writeQueries, Module module) {
throw new UnsupportedOperationException();
}
}