//----------------------------------------------------------------------- // // 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 DynamicApiLoading.Api.Dynamic.RP1210 { using System; using System.Runtime.InteropServices; using System.Text; /// /// RP1210 Native API methods. /// public class NativeMethods : IDisposable { /// /// This function is called by the client application seeking connection with a DLL. /// This connection corresponds to the implementation of the API for the VDA being selected. /// Inside the API DLL, the function allocates and initializes any client data structures, /// and loads, initializes, or activates any device drivers (virtual or otherwise) to communicate /// with the hardware and sets all client appliation variables to their defaults (EchoMode,FilterStates, etc.). /// If the connection is successful, the function shall return a unique identifier, /// corresponding to the ID of the client application, as assigned by the API DLL. /// /// This parameter is no longer necessary and is unused (Windows 3.1). /// The value should be set to NULL (0x00) if an application is not developed for Windows 3.1. /// The device to which the client application is requesting connection. /// Pointer to a null-terminated string of the protocol name /// to be used by the device designated in the previous parameter. /// (See Protocol Connect String section for protocol strings and variations.) /// A long integer for the requested size (in bytes) of the client transmit /// buffer to be allocated by the API for the queuing of messages sought to be ransmitted by the client /// application. /// /// Should be passed as 0 if the application does not want to dictate the buffer size and /// the API DLL default of 8K is acceptable. /// A long integer for the requested size (in bytes) of the /// client receive buffer to be allocated by the API for the queuing of messages meant /// to be received by the client application. /// Should be passed as 0 if the application does not want to dictate the buffer /// size and the API DLL default of 8K is acceptable. /// A flag that is relevant only for J1939. /// Should be set to zero if the application wants the lower-level components to /// perform the tasks of fragmenting the message into packets and return complete /// messages assembled from packets received. /// Should be set to 1 in the rare case where the application itself will /// perform the packetizing of message fragments. /// If the connection is successful, then the function returns a value between 0 and 127, /// corresponding to the client identifier that the application program is assigned by the API DLL. /// The application program must save this return value in order to conduct future transactions with the DLL. /// If the connection is unsuccessful, then an error code is returned that corresponds to a number greater than 127. /// The typical error codes are described below. /// More descriptive or proprietary codes may be returned by individual vendor implementations as /// long as the numerical equivalents of these return values are greater /// than 192 and are clearly documented by the vendor. /// /// Mnemonic (Return Codes) Description /// ERR_CLIENT_ALREADY_CONNECTED A client is already connected to the specified device. /// ERR_CLIENT_AREA_FULL The maximum number of connections has been reached. /// ERR_CONNECT_NOT_ALLOWED Only one connection is allowed in the requested Mode. /// ERR_DEVICE_IN_USE The specified device is already in use and does not have the ability to maintain connections with multiple clients simultaneously. /// ERR_DLL_NOT_INITIALIZED The API DLL was not initialized. /// ERR_HARDWARE_NOT_RESPONDING The device is not responding. /// ERR_INVALID_DEVICE The specified device ID is invalid. /// ERR_INVALID_PROTOCOL The specified protocol is invalid or unsupported or /// the extended connect string (fpchProtocol) was incorrect or unsupported. /// ERR_NOT_ENOUGH_MEMORY The API DLL could not allocate enough memory to create the client. /// ERR_J1708_BAUD_SET_NONSTANDARD See RP1210_ClientConnect Notes. /// ERR_J1939_BAUD_SET_NONSTANDARD See RP1210_ClientConnect Notes. /// ERR_CAN_BAUD_SET_NONSTANDARD See RP1210_ClientConnect Notes. /// ERR_MULTIPLE_CONNECTIONS_NOT_ALLOWED_NOW See RP1210_ClientConnect Notes. /// /// [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate int TRP1210ClientConnect(IntPtr hwndClient, short nDeviceId, StringBuilder fpchProtocol, int lSendBuffer, int lReceiveBuffer, short nIsAppPacketizingIncomingMsgs); /// /// RP1210 Client Disconnect /// /// Client ID (return value from TRP1210ClientConnect in range 0 to 127) /// Status of operation. [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate short TRP1210ClientDisconnect(short nClientID); /// /// RP1210 Send Message. /// /// Client ID (return value from TRP1210ClientConnect in range 0 to 127) /// Message to send. /// Size of message. /// Windows 3.1 legacy parameter. /// Flag indicate if method shall block on sending. /// Status of operation. [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate short TRP1210SendMessage(short nClientID, byte[] fpchClientMessage, short nMessageSize, short nNotifyStatusOnTx, short nBlockOnSend); /// /// RP1210 Read Message. /// /// Client ID (return value from TRP1210ClientConnect in range 0 to 127) /// Buffer to receive message to. /// Size of buffer. /// Flag to indicate if the method shall block until message is read. /// 0 at no message, <192 for message size, > 192 for error code. [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate short TRP1210ReadMessage(short nClientID, byte[] fpchAPIMessage, short nBufferSize, short nBlockOnRead); /// /// RP1210 Send Command. /// /// RP1210 Command Number /// Client ID (return value from TRP1210ClientConnect in range 0 to 127) /// Pointer to buffer. /// Size of buffer. /// Status of operation. [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate short TRP1210SendCommand(short nCommandNumber, short nClientID, StringBuilder fpchClientCommand, short nMessageSize); /// /// RP1210 Read Version. /// /// DLL Major version. /// DLL Minor version. /// API Major version. /// API Minor version. [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate void TRP1210ReadVersion(StringBuilder fpchDLLMajorVersion, StringBuilder fpchDLLMinorVersion, StringBuilder fpchAPIMajorVersion, StringBuilder fpchAPIMinorVersion); /// /// RP1210 This function is called by the client application seeking to get detailed information about the vendor API and/or firmware of the device to which it is connected. /// /// Client ID (return value from TRP1210ClientConnect in range 0 to 127) /// API version info. /// Pointer to a buffer that is 17 bytes long. /// The API may return up to 16 bytes in this field (with NULL terminator) to describe the version of the API interface. /// /// DLL version info. /// Pointer to a buffer that is 17 bytes long. /// The API may return up to 16 bytes in this field (with NULL terminator) to describe the version of the DLL. /// Firmware version info. /// Pointer to a buffer that is 17 bytes long. /// The API may return up to 16 bytes in this field (with NULL terminator) to describe the version of /// the firmware that is present in the device. /// A NULL string is also a valid return if the VDA does not have associated firmware. /// Status of operation. [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate short TRP1210ReadDetailedVersion(short nClientID, StringBuilder fpchAPIVersionInfo, StringBuilder fpchDLLVersionInfo, StringBuilder fpchFWVersionInfo); /// /// RP1210 Get Hardware Status /// /// Client ID (return value from TRP1210ClientConnect in range 0 to 127) /// A pointer to the buffer (allocated by the client application) where hardware status information is to be placed. /// Always set to 18 bytes. /// A flag to indicate whether the function must block on requesting the hardware status or not. /// Status of operation. [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate short TRP1210GetHardwareStatus(short nClientID, StringBuilder fpchClientInfo, short nInfoSize, short nBlockOnRequest); /// /// Type declaration for dynamically loaded RP1210 API. /// /// Numerical value for the last error which occurred. /// A pointer to the buffer (allocated by the client application) of 80 bytes, used to return the error message associated with the error code. /// Status of operation. [UnmanagedFunctionPointer(CallingConvention.StdCall)] internal delegate short TRP1210GetErrorMsg(short err_code, StringBuilder fpchMessage); /// /// Gets RP1210_ClientConnect method instance. /// internal TRP1210ClientConnect RP1210_ClientConnect { get; private set; } /// /// Gets RP1210_ClientDisconnect method instance. /// internal TRP1210ClientDisconnect RP1210_ClientDisconnect { get; private set; } /// /// Gets RP1210_SendMessage method instance. /// internal TRP1210SendMessage RP1210_SendMessage { get; private set; } /// /// Gets RP1210_ReadMessage method instance. /// internal TRP1210ReadMessage RP1210_ReadMessage { get; private set; } /// /// Gets RP1210_SendCommand method instance. /// internal TRP1210SendCommand RP1210_SendCommand { get; private set; } /// /// Gets RP1210_ReadVersion method instance. /// internal TRP1210ReadVersion RP1210_ReadVersion { get; private set; } /// /// Gets RP1210_ReadDetailedVersion method instance. /// internal TRP1210ReadDetailedVersion RP1210_ReadDetailedVersion { get; private set; } /// /// Gets RP1210_GetHardwareStatus method instance. /// internal TRP1210GetHardwareStatus RP1210_GetHardwareStatus { get; private set; } /// /// Gets RP1210_GetErrorMsg method instance. /// internal TRP1210GetErrorMsg RP1210_GetErrorMsg { get; private set; } /// /// DLL instance handle. /// private SafeLibraryHandle safeLibraryHandle; /// /// Name of DLL. /// private string library; /// /// Initializes a new instance of the class. /// /// Name of DLL. public NativeMethods(string library) { this.library = library; this.safeLibraryHandle = SafeLibraryHandle.LoadLibraryW(library); if (this.safeLibraryHandle.IsInvalid) { throw new DynamicLoaderException("LoadLibrary('" + library + "') failed!"); } this.RP1210_ClientConnect = (TRP1210ClientConnect)Marshal.GetDelegateForFunctionPointer(this.getProcedureAddress("RP1210_ClientConnect"), typeof(TRP1210ClientConnect)); this.RP1210_ClientDisconnect = (TRP1210ClientDisconnect)Marshal.GetDelegateForFunctionPointer(this.getProcedureAddress("RP1210_ClientDisconnect"), typeof(TRP1210ClientDisconnect)); this.RP1210_SendMessage = (TRP1210SendMessage)Marshal.GetDelegateForFunctionPointer(this.getProcedureAddress("RP1210SendMessage"), typeof(TRP1210SendMessage)); this.RP1210_ReadMessage = (TRP1210ReadMessage)Marshal.GetDelegateForFunctionPointer(this.getProcedureAddress("RP1210_ReadMessage"), typeof(TRP1210ReadMessage)); this.RP1210_SendCommand = (TRP1210SendCommand)Marshal.GetDelegateForFunctionPointer(this.getProcedureAddress("RP1210_SendCommand"), typeof(TRP1210SendCommand)); this.RP1210_ReadVersion = (TRP1210ReadVersion)Marshal.GetDelegateForFunctionPointer(this.getProcedureAddress("RP1210_ReadVersion"), typeof(TRP1210ReadVersion)); this.RP1210_ReadDetailedVersion = (TRP1210ReadDetailedVersion)Marshal.GetDelegateForFunctionPointer(this.getProcedureAddress("RP1210_ReadDetailedVersion"), typeof(TRP1210ReadDetailedVersion)); this.RP1210_GetHardwareStatus = (TRP1210GetHardwareStatus)Marshal.GetDelegateForFunctionPointer(this.getProcedureAddress("RP1210_GetHardwareStatus"), typeof(TRP1210GetHardwareStatus)); this.RP1210_GetErrorMsg = (TRP1210GetErrorMsg)Marshal.GetDelegateForFunctionPointer(this.getProcedureAddress("RP1210_GetErrorMsg"), typeof(TRP1210GetErrorMsg)); } /// /// Dispose instance. /// public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } /// /// Dispose instance. /// /// 'true' if call to Dispose() was made, 'false' if the class was finalized. protected virtual void Dispose(bool disposing) { this.safeLibraryHandle.Dispose(); } /// /// Finalizes an instance of the class. /// ~NativeMethods() { this.Dispose(false); } /// /// Gets the address of the given procedure, throws Exception when failing. /// /// Name of procedure to locate. /// Pointer to function /// Thrown when unable to get address to function. private IntPtr getProcedureAddress(string functionName) { IntPtr pAddress = this.safeLibraryHandle.GetProcAddress(functionName); if (pAddress == IntPtr.Zero) { throw new DynamicLoaderException("GetProcAddress('" + functionName + "'), library '" + this.library + "' failed!"); } return pAddress; } } }