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