//----------------------------------------------------------------------- // // 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; } } }