//----------------------------------------------------------------------- // // 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 System; using System.Collections.Generic; using System.Windows.Forms; using global::DeviceApi; using global::SharedObjects; using global::SharedObjects.Api; using global::SharedObjects.Misc; using global::SharedObjects.Protocol; /// /// Class that handles the filters used. /// /// Notice that Flow Control filters are only for physical addressing. /// Functional addressing doesn't support Flow Control and is Single Frame only. /// /// public class FilterHandler : IFilterHandler { /// /// Logger instance. /// private ILogging iLogging; /// /// Current connection instance. /// private IPassThruConnection passThruConnection; /// /// Current protocol handler instance. /// private IProtocolHandler protocolHandler; /// /// Current array of ECU:s. /// private XmlClass.vehicle.ecuData[] ecuArr; /// /// Current TX flags. /// private uint txFlags; /// /// Current list of filters. /// private SortedDictionary filterList = new SortedDictionary(); /// /// Protocol item wrapper. /// private ProtocolItemWrapper protocolItemWrapper; /// /// Gets Filter list. /// public ICollection filters { get { return new List(this.filterList.Values); } } /// /// Initializes a new instance of the class. /// /// Logger instance. /// Current connection instance. /// Current protocol handler instance. /// Current array of ECU:s. /// Current TX flags. /// Protocol item wrapper instance. public FilterHandler( ILogging iLogging, IPassThruConnection passThruConnection, IProtocolHandler protocolHandler, XmlClass.vehicle.ecuData[] ecuArr, uint txFlags, ProtocolItemWrapper protocolItemWrapper) { this.iLogging = iLogging; this.passThruConnection = passThruConnection; this.protocolHandler = protocolHandler; this.ecuArr = ecuArr; this.txFlags = txFlags; this.protocolItemWrapper = protocolItemWrapper; this.setDefaultLoggerFilter(); } /// /// Set default logger filter depending on protocol. /// public void setDefaultLoggerFilter() { if (this.protocolHandler != null && this.protocolHandler.protocol != null) { switch (this.protocolHandler.protocol.id) { case Protocols.J1850VPW: break; case Protocols.J1850PWM: break; case Protocols.ISO9141: this.setDefaultISO9141LoggerFilter(); break; case Protocols.ISO14230: this.setDefaultISO9141LoggerFilter(); break; case Protocols.CAN: break; case Protocols.ISO15765: this.setDefaultISO15765LoggerFilter(); break; case Protocols.SCI_A_ENGINE: break; case Protocols.SCI_A_TRANS: break; case Protocols.SCI_B_ENGINE: break; case Protocols.SCI_B_TRANS: break; default: this.iLogging.appendText("Unknown protocol: 0x" + this.protocolHandler.protocol.id.ToString("x2") + "\r\n"); break; } } } /// /// Set a filter according to the given parameters. /// /// Type of filter. /// Protocol for filter. /// Filter mask. /// Filter pattern. /// Filter Flow pattern. /// Data Size /// 'true' on success. public bool setISO15765LoggerFilter(uint filterType, Protocols protocol, uint mask, uint pattern, uint flow, int datasize) { bool success = false; IPassThruMsg msgMask = PassThruMsg.getMaskedMsg(protocol); IPassThruMsg msgPattern = PassThruMsg.getMaskedMsg(protocol); IPassThruMsg msgFlow = PassThruMsg.getMaskedMsg(protocol); this.protocolHandler.setAddress(ref msgMask, mask); this.protocolHandler.setAddress(ref msgPattern, pattern); this.protocolHandler.setAddress(ref msgFlow, flow); msgMask.DataSize = datasize; msgPattern.DataSize = datasize; msgFlow.DataSize = datasize; msgMask.TxFlags = (int)this.txFlags; msgPattern.TxFlags = (int)this.txFlags; msgFlow.TxFlags = (int)this.txFlags; int msgId = 0; PassThruConstants.resultCode status = this.passThruConnection.Gl_PassThruStartMsgFilter( filterType, msgMask, msgPattern, msgFlow, out msgId); string errtext; if (!this.iLogging.errTestConnection(this.passThruConnection, status, out errtext)) { this.iLogging.appendText("StartMsgFilter res=" + status + ", errtxt=" + errtext + "\r\n"); MessageBox.Show( "StartMsgFilter Failed!\r\n" + errtext, "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); } else { FilterItem filterItem = new FilterItem( msgId, filterType, datasize, mask, pattern, flow, this.txFlags, protocol); this.filterList.Add(msgId, filterItem); this.iLogging.appendText("Filter " + filterItem.filterId + ", data: " + filterItem.ToString() + " Activated.\r\n"); success = true; } return success; } /// /// Remove all known filters from the connection. /// public void removeAllFilters() { this.passThruConnection.IoctlClearTxBuffer(); this.passThruConnection.IoctlClearRxBuffer(); this.passThruConnection.IoctlClearMsgFilters(); this.filterList.Clear(); } /// /// Set the filter for the data we want to receive. /// public void setRawLoggerFilter() { IPassThruMsg msgMask = PassThruMsg.getMaskedMsg(Protocols.CAN); IPassThruMsg msgPattern = PassThruMsg.getMaskedMsg(Protocols.CAN); int msgId; msgMask.DataSize = 4; msgMask.TxFlags = PassThruConstants.txflags.ISO15765_FRAME_PAD; msgPattern.DataSize = 4; msgPattern.TxFlags = PassThruConstants.txflags.ISO15765_FRAME_PAD; PassThruConstants.resultCode status = this.passThruConnection.Gl_PassThruStartMsgFilter( PassThruConstants.filters.PASS_FILTER, msgMask, msgPattern, null, out msgId); string errtext; if (!this.iLogging.errTestConnection(this.passThruConnection, status, out errtext)) { this.iLogging.appendText("StartMsgFilter res=" + status + ", errtxt=" + errtext + "\r\n"); MessageBox.Show( "StartMsgFilter Failed!\r\n" + errtext, "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); } else { this.iLogging.appendText("Filter msgId=" + msgId + " added.\r\n"); } } /// /// Stop selected filter. /// /// ID of filter to stop. /// 'true' if successful. public bool stopFilter(int msgId) { bool success = false; PassThruConstants.resultCode status = this.passThruConnection.Gl_PassThruStopMsgFilter(msgId); string errtext; if (!this.iLogging.errTestConnection(this.passThruConnection, status, out errtext)) { this.iLogging.appendText("StopMsgFilter res=" + status + ", errtxt=" + errtext + "\r\n"); MessageBox.Show( "StopMsgFilter Failed!\r\n" + errtext, "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); } else { this.filterList.Remove(msgId); success = true; this.iLogging.appendText("Filter " + msgId + " Removed.\r\n"); } return success; } /// /// Set logger filter for ISO9141 protocol. /// private void setDefaultISO9141LoggerFilter() { Protocols protocol = this.protocolHandler.protocol; IPassThruMsg msgMask = PassThruMsg.getMaskedMsg(Protocols.ISO9141); IPassThruMsg msgPattern = PassThruMsg.getMaskedMsg(Protocols.ISO9141); msgMask.Data[0] = 0x00; //// msgMask.Data[0] = 0x14; //// msgMask.Data[1] = 0xfe; msgPattern.Data[0] = 0x00; //// msgPattern.Data[1] = 0x6a; msgMask.DataSize = 1; msgPattern.DataSize = 1; //// msgMask.TxFlags = (int)this.txFlags; //// msgPattern.TxFlags = (int)this.txFlags; int msgId = 0; PassThruConstants.resultCode status = this.passThruConnection.Gl_PassThruStartMsgFilter( PassThruConstants.filters.PASS_FILTER, msgMask, msgPattern, null, out msgId); string errtext; if (!this.iLogging.errTestConnection(this.passThruConnection, status, out errtext)) { this.iLogging.appendText("StartMsgFilter res=" + status + ", errtxt=" + errtext + "\r\n"); MessageBox.Show( "StartMsgFilter Failed!\r\n" + errtext, "Error", MessageBoxButtons.OK, MessageBoxIcon.Stop); } else { FilterItem filterItem = new FilterItem( msgId, PassThruConstants.filters.PASS_FILTER, 2, 0x14fe, 0x006a, 0, this.txFlags, protocol); this.filterList.Add(msgId, filterItem); this.iLogging.appendText("Filter " + filterItem.filterId + ", data: " + filterItem.ToString() + " Activated.\r\n"); } } /// /// Set logger filter for ISO15765 protocol. /// private void setDefaultISO15765LoggerFilter() { this.iLogging.appendText("29-bit=" + this.protocolHandler.is29bit() + "\r\n"); if (this.protocolHandler.is29bit()) { bool flag = false; if (flag && this.ecuArr.Length > 0) { uint testerAddr = this.protocolHandler.srcAddr; uint baseFlowAddress = Utils.hexParse(this.protocolItemWrapper.addressData.baseDestinationAddress); uint basePatternAddress = Utils.hexParse(this.protocolItemWrapper.addressData.baseSourceAddress); for (int i = 0; i < this.ecuArr.Length; i++) { XmlClass.vehicle.ecuData ecu = this.ecuArr[i]; try { uint ecuId = Utils.hexParse(ecu.id); uint flowAddress = baseFlowAddress; uint patternAddress = basePatternAddress; flowAddress |= ((ecuId << 8) & 0xff00); flowAddress |= (testerAddr & 0xff); patternAddress |= ((testerAddr << 8) & 0xff00); patternAddress |= (ecuId & 0xff); if (!this.setISO15765LoggerFilter(PassThruConstants.filters.FLOW_CONTROL_FILTER, this.protocolHandler.protocol, 0xffffffff, patternAddress, flowAddress, 4)) { break; } } catch (Exception ex) { this.iLogging.appendText("setDefaultISO15765LoggerFilter: ecuid='" + ecu.id + "', " + ex.Message + "\r\n"); } } } else { uint testerAddr = this.protocolHandler.srcAddr; uint baseFlowAddress = Utils.hexParse(this.protocolItemWrapper.addressData.baseDestinationAddress); uint basePatternAddress = Utils.hexParse(this.protocolItemWrapper.addressData.baseSourceAddress); // Hard-coded default range. for (uint i = 0x10; i < 0x18; i++) { uint flowAddress = baseFlowAddress; uint patternAddress = basePatternAddress; flowAddress |= ((i << 8) & 0xff00); flowAddress |= (testerAddr & 0xff); patternAddress |= ((testerAddr << 8) & 0xff00); patternAddress |= (i & 0xff); if (!this.setISO15765LoggerFilter(PassThruConstants.filters.FLOW_CONTROL_FILTER, this.protocolHandler.protocol, 0xffffffff, patternAddress, flowAddress, 4)) { break; } } /* this.setISO15765LoggerFilter2( PassThruConstants.filters.PASS_FILTER, this.protocolHandler.protocol, 0xffff0000, 0x18DA0000, 4); */ } } else { for (int i = 0; i < 8; i++) { if (!this.setISO15765LoggerFilter(PassThruConstants.filters.FLOW_CONTROL_FILTER, this.protocolHandler.protocol, 0xffffffff, (uint)(0x07e8 + i), (uint)(0x07e0 + i), 4)) { break; } } /* this.setISO15765LoggerFilter2( PassThruConstants.filters.BLOCK_FILTER, this.protocolHandler.protocol, 0xffffffff, 0x07C0, 4); */ } } } }