//----------------------------------------------------------------------- // // 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 Protocol { using global::DeviceApi; using global::SharedObjects; using global::SharedObjects.Api; using global::SharedObjects.GUI; using global::SharedObjects.Misc; using global::SharedObjects.Protocol; /// /// Implementation of the ISO15765 protocol. /// public class Protocol_ISO15765 : Protocol_Common, IProtocolHandler, IMsgCallback { /// /// Possible address bits for protocol. /// private readonly string[] possibleAddressbits = { "11", "29" }; /// /// Set if 29-bit addressing is active. /// private bool is29bitFlag; /// /// Initializes a new instance of the class. /// /// Logging interface. /// Current protocol. /// Current message handler instance. /// Source address. /// Checksum flag. /// Indicates if 29 bit addressing shall be used. /// Callback interface for enabling the buttons when a protocol is fully initialized. public Protocol_ISO15765( ILogging iLogging, Protocols protocol, MessageHandler messageHandler, uint srcAddr, bool checksum, bool is29bit, IEnableButtons iEnableButtons) : base(iLogging, protocol, messageHandler, srcAddr, checksum, iEnableButtons) { this.is29bitFlag = is29bit; // Register this protocol handler with the message handler. this.messageHandler.setProtocolCallback(this); } /// /// Indicate if protocol currently is 29 bit. /// /// 'true' if 29 bit active. public bool is29bit() { return this.is29bitFlag; } /// /// Get current address alternatives for protocol. /// /// Array of alternatives. public string[] addressBitAlternatives() { return this.possibleAddressbits; } /// /// Initialize protocol. /// /// TX Flags for any messages that are created during initialization. public void init(int txFlags) { // No init needed for this protocol. this.iEnableButtons.enableButtons(); } /// /// Start protocol. /// public void start() { // No start needed for this protocol. } /// /// Stop protocol. /// public void stopProtocol() { // No stop needed for this protocol. } /// /// Receive one message and dispatch it to receivers. /// /// Message to receive. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Reviewed.")] public void receiveMessage(IPassThruMsg rxmsg) { if (rxmsg.DataSize >= 4) { if (rxmsg.DataSize >= 5) { byte[] payload = extractPayload(rxmsg, 4); uint srcAddress = 0; for (int i = 0; i < 4; i++) { srcAddress = (uint)(srcAddress << 8) | rxmsg.Data[i]; } this.dispatchMessage(rxmsg, payload, srcAddress, 0); } } else { this.iLogging.appendText("Message too short! rxmsg.Datasize=" + rxmsg.DataSize + "\r\n"); } } /// /// Get payload part of message. /// /// Message to get payload from. /// Byte array with payload. public override byte[] getPayload(IPassThruMsg msg) { byte[] payload = extractPayload(msg, 4); return payload; } /// /// Set additional header data in addition to the address. /// /// Message to add data to. /// Size of message. /// 'true' if the destination address is functional address. public void setHeader(ref IPassThruMsg txmsg, uint size, bool functionalTargetAddressing) { // Nothing to do here - this protocol does not have any // other info to add. } /// /// Set the address(es) of the message. /// /// Message to set data in. /// Source Address. /// Destination Address. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Reviewed.")] public void setAddress(ref IPassThruMsg txmsg, uint sourceAddress, uint destinationAddress) { if (this.is29bit()) { txmsg.Data[0] = (byte)((destinationAddress >> 24) & 0xff); txmsg.Data[1] = (byte)((destinationAddress >> 16) & 0xff); txmsg.Data[2] = (byte)((destinationAddress >> 8) & 0xff); txmsg.Data[3] = (byte)((sourceAddress) & 0xff); } else { txmsg.Data[0] = (byte)((destinationAddress >> 24) & 0xff); txmsg.Data[1] = (byte)((destinationAddress >> 16) & 0xff); txmsg.Data[2] = (byte)((destinationAddress >> 8) & 0xff); txmsg.Data[3] = (byte)((destinationAddress) & 0xff); } txmsg.DataSize = 4; } /// /// Set the address(es) of the message. /// /// Message to set data in. /// Combined Address. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods", MessageId = "0", Justification = "Reviewed.")] public void setAddress(ref IPassThruMsg txmsg, uint address) { txmsg.Data[0] = (byte)((address >> 24) & 0xff); txmsg.Data[1] = (byte)((address >> 16) & 0xff); txmsg.Data[2] = (byte)((address >> 8) & 0xff); txmsg.Data[3] = (byte)((address) & 0xff); txmsg.DataSize = 4; } /// /// Send one probe message. /// /// Source address (address of tester). /// Tx Flags /// Message Payload which includes address data. public void sendProbeMessage(uint srcAddr, int txFlags, byte[] payload) { if (this.is29bitFlag) { this.sendMessage(srcAddr, 0x18db3300, txFlags, payload); } else { this.sendMessage(0x00, 0x7df, txFlags, payload); } } /// /// Send one message to the given receiver address. /// /// Source address. /// Destination address. /// TX Flags. /// Payload data. /// Error message in case of a problem. public string sendMessage(uint sourceAddress, uint destinationAddress, int txFlags, byte[] payload) { IPassThruMsg txmsg = PassThruMsg.getMaskedMsg(this.protocol); // Add Address. this.setAddress(ref txmsg, sourceAddress, destinationAddress); string dataStr = addPayload(payload, ref txmsg); // Add a checksum if so requested, even though this protocol // normally doesn't need one. Just in case we encounter an odd // implementation. this.addChecksum(ref txmsg); PassThruConstants.resultCode res = this.sendMessage(txFlags, txmsg); // Check if error. string errtext = string.Empty; if (!this.messageHandler.errTestConnection(res, out errtext)) { this.iLogging.dispMsg("Err", txmsg, string.Format("0x{0:x8}", destinationAddress), dataStr + ", " + errtext); } return errtext; } /// /// Add the payload to the message. /// /// Byte array of payload to send. /// Message to update with payload. /// Hex string with message, to be used for logging. private static string addPayload(byte[] payload, ref IPassThruMsg txmsg) { string dataStr = string.Empty; for (int i = 0; i < payload.Length; i++) { txmsg.Data[txmsg.DataSize++] = payload[i]; dataStr += string.Format("{0:x2} ", payload[i]); } return dataStr; } /// /// Call the message handler and send the formatted message structure. /// /// TX Flags. /// Message to send. /// Status code, 0=success. private PassThruConstants.resultCode sendMessage(int txFlags, IPassThruMsg txmsg) { // Set message flags. txmsg.TxFlags = txFlags; return this.messageHandler.sendMessage(txmsg); } /// /// Add checksum if requested. /// Notice that CAN and ISO 15765 doesn't need a checksum. /// But it's up to the user to decide, so we just check /// if the checkbox is checked. /// /// Message to add checksum to. private void addChecksum(ref IPassThruMsg txmsg) { if (this.checksum) { int cs = Utils.getChecksum(txmsg.Data, 0, txmsg.DataSize); txmsg.Data[txmsg.DataSize++] = (byte)(cs & 0xff); } } } }