//-----------------------------------------------------------------------
//
// Copyright © 2012 Nils Hammar. All rights reserved.
//
//-----------------------------------------------------------------------
/*
* Software to access vehicle information via the OBD-II connector.
*
* Copyright © 2012 Nils Hammar
*
* 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 3 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, see .
*
* Alternative licensing is possible, see the licensing document.
*
* The above text may not be removed or modified.
*/
namespace DeviceApi.J2534
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using global::DeviceApi.Serial;
using global::SharedObjects;
using global::SharedObjects.Api;
using global::SharedObjects.Misc;
///
/// Handle one J2534 device.
/// It is possible to handle more than one device if needed.
///
public class PassThruDevice : IPassThruDevice
{
///
/// List of supported interfaces by this application.
///
/// Notice: Last interface is the simulator interface useful for testing
/// and replay of raw logs.
///
///
private static IList interfaceList = new List()
{
new SerialAtAgvPassThru(),
new SerialAtElmPassThru(),
#if SIMPLE_SERIAL
new SimpleSerialPassThru(),
#endif
};
/* Instance specific. */
///
/// Current Device ID.
///
private int DeviceIDInt = -1;
///
/// Gets current Device ID.
///
public int DeviceID
{
get { return this.DeviceIDInt; }
}
///
/// Gets Current interface implementation used.
///
public IPassThru passThruInterface { get; private set; }
///
/// Gets Last known error encountered.
///
public string lastError { get; private set; }
///
/// Logging interface.
///
private ILogging iLogging;
///
/// Initializes a new instance of the class.
///
/// Logging interface.
/// The interface implementation to use for the device.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "1", Justification = "Reviewed")]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Reviewed")]
public PassThruDevice(ILogging iLogging, IPassThru passThruInterface)
{
this.iLogging = iLogging;
this.DeviceIDInt = -1;
this.passThruInterface = passThruInterface;
try
{
if (probeDevice(passThruInterface) != 0)
{
MessageBox.Show(
"No device found.",
"Warning",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}
}
catch (BadImageFormatException ex)
{
iLogging.appendText("Incompatible Driver for: " + passThruInterface.name + "\r\n" + ex.Message + "\r\n", LogLevel.LOG_WARN);
}
catch (DllNotFoundException ex)
{
iLogging.appendText("No Driver installed for: " + passThruInterface.name + "\r\n" + ex.Message + "\r\n", LogLevel.LOG_WARN);
}
catch (Exception e)
{
MessageBox.Show(
"No driver found.\r\n\r\n" + e.Message,
"Error",
MessageBoxButtons.OK,
MessageBoxIcon.Stop);
}
}
///
/// Add static interfaces.
///
public static void addStaticInterfaces()
{
/*
interfaceList.Insert(0, new DicePassThru());
interfaceList.Insert(0, new UwaPassThru());
interfaceList.Insert(0, new TactrixPassThru());
*/
}
///
/// Add interface.
///
/// Interface to add.
public static void addDynamicInterface(IPassThru iPassThru)
{
interfaceList.Insert(0, iPassThru);
}
///
/// Close the device.
///
public static void close()
{
}
///
/// Get supported interfaces where a device is connected.
///
/// Logging instance.
/// Array of possible interfaces.
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Intentional since iLogging shall never be 'null'.")]
public static IPassThru[] getInterfaces(ILogging iLogging)
{
List l1 = new List();
foreach (IPassThru interfaceItem in interfaceList)
{
try
{
if (probeDevice(interfaceItem) == 0)
{
l1.Add(interfaceItem);
iLogging.appendText("Found Device: " + interfaceItem.name + "\r\n", LogLevel.LOG_INFO);
}
else
{
iLogging.appendText("Found Driver but no Device: " + interfaceItem.name + "\r\n", LogLevel.LOG_WARN);
}
}
catch (BadImageFormatException ex)
{
iLogging.appendText("Incompatible Driver for: " + interfaceItem.name + "\r\n" + ex.Message + "\r\n", LogLevel.LOG_WARN);
}
catch (DllNotFoundException ex)
{
iLogging.appendText("No Driver installed for: " + interfaceItem.name + "\r\n" + ex.Message + "\r\n", LogLevel.LOG_WARN);
}
}
return l1.ToArray();
}
///
/// Gets the name of the interface.
///
public string name
{
get
{
return this.passThruInterface.name;
}
}
///
/// Check if the interface is declared to have a disconnect bug.
///
/// 'true' if a known disconnect bug exists.
public bool disconnectBug()
{
return this.passThruInterface.disconnectBug();
}
///
/// Execute PassThruOpen on the device.
///
/// Result status, 0=success.
public unsafe PassThruConstants.resultCode Gl_PassThruOpen()
{
PassThruConstants.resultCode ret = 0;
fixed (int* pDeviceID = &this.DeviceIDInt)
{
ret = this.passThruInterface.PassThruOpen(null, pDeviceID);
if (ret != PassThruConstants.resultCode.ERR_SUCCESS)
{
this.lastError = this.Gl_PassThruGetLastError();
}
else
{
this.lastError = PassThruConstants.SUCCESS;
}
}
return ret;
}
///
/// Close the device.
///
/// Result status, 0=success.
public PassThruConstants.resultCode Gl_PassThruClose()
{
PassThruConstants.resultCode ret = this.passThruInterface.PassThruClose(this.DeviceID);
if (ret != PassThruConstants.resultCode.ERR_SUCCESS)
{
this.lastError = this.Gl_PassThruGetLastError();
}
else
{
this.lastError = PassThruConstants.SUCCESS;
}
return ret;
}
///
/// Set programming voltage on the interface.
///
/// Pin to configure.
/// Voltage to set.
/// Result status, 0=success.
public PassThruConstants.resultCode Gl_PassThruSetProgrammingVoltage(int Pin, int Voltage)
{
PassThruConstants.resultCode ret = this.passThruInterface.PassThruSetProgrammingVoltage(this.DeviceID, Pin, Voltage);
if (ret != PassThruConstants.resultCode.ERR_SUCCESS)
{
this.lastError = this.Gl_PassThruGetLastError();
}
else
{
this.lastError = PassThruConstants.SUCCESS;
}
return ret;
}
///
/// Read version of API.
///
/// API Version (out value)
/// DLL Version (out value)
/// Firmware Version (out value)
/// Result status, 0=success.
public unsafe PassThruConstants.resultCode Gl_PassThruReadVersion(out string ApiVersion, out string DllVersion, out string FirmwareVersion)
{
PassThruConstants.resultCode stat = 0;
string xApiVersion = " ";
string xDllVersion = " ";
string xFirmwareVersion = " ";
byte[] aApiVersion = Encoding.UTF8.GetBytes(xApiVersion);
byte[] aDllVersion = Encoding.UTF8.GetBytes(xDllVersion);
byte[] aFirmwareVersion = Encoding.UTF8.GetBytes(xFirmwareVersion);
fixed (byte* pApiVersion = aApiVersion, pDllVersion = aDllVersion, pFirmwareVersion = aFirmwareVersion)
{
stat = this.passThruInterface.PassThruReadVersion(this.DeviceID, pFirmwareVersion, pDllVersion, pApiVersion);
if (stat != PassThruConstants.resultCode.ERR_SUCCESS)
{
this.lastError = this.Gl_PassThruGetLastError();
}
else
{
this.lastError = PassThruConstants.SUCCESS;
}
ApiVersion = Encoding.UTF8.GetString(Encoding.Convert(Encoding.GetEncoding("iso-8859-1"), Encoding.UTF8, aApiVersion), 0, Utils.strlen(aApiVersion));
DllVersion = Encoding.UTF8.GetString(Encoding.Convert(Encoding.GetEncoding("iso-8859-1"), Encoding.UTF8, aDllVersion), 0, Utils.strlen(aDllVersion));
FirmwareVersion = Encoding.UTF8.GetString(Encoding.Convert(Encoding.GetEncoding("iso-8859-1"), Encoding.UTF8, aFirmwareVersion), 0, Utils.strlen(aFirmwareVersion));
}
return stat;
}
///
/// Establish a connection on the device.
///
/// Protocol to use.
/// Connection flags.
/// Baudrate to connect with.
/// Channel ID assigned (out value)
/// Result status, 0=success.
public unsafe PassThruConstants.resultCode Gl_PassThruConnect(int ProtocolID, uint Flags, uint Baudrate, out int channelID)
{
PassThruConstants.resultCode ret = 0;
this.iLogging.appendText("PassThruConnect(" + this.DeviceID + ", " + ProtocolID + ", " + Flags + ", " + Baudrate + ", int *channelId)\r\n");
fixed (int* pChannelID = &channelID)
{
ret = this.passThruInterface.PassThruConnect(this.DeviceID, ProtocolID, Flags, Baudrate, pChannelID);
}
this.iLogging.appendText("ret=" + ret + ", channel=" + channelID + "\r\n");
return ret;
}
///
/// Probe an interface for a device.
///
/// Interface to probe.
/// Result code, 0=success.
private static unsafe PassThruConstants.resultCode probeDevice(IPassThru passThruInterface)
{
PassThruConstants.resultCode ret = 0;
int DeviceID = -1;
int* pDeviceID = &DeviceID;
ret = passThruInterface.PassThruOpen(null, pDeviceID);
passThruInterface.PassThruClose(DeviceID);
return ret;
}
///
/// Get the last error from the interface.
///
/// Result status, 0=success.
private unsafe string Gl_PassThruGetLastError()
{
sbyte[] ca = new sbyte[512];
string str = string.Empty;
fixed (sbyte* p = ca)
{
*p = (sbyte)0;
PassThruConstants.resultCode res = 0;
if ((res = this.passThruInterface.PassThruGetLastError(p)) != 0)
{
str = " * PassThruGetLastError() FAILED with error '" + res + "'! * ";
}
else
{
str = new string(p);
}
}
return str;
}
}
}