J2534_WIN: PASS and Block message filters. Related aux features.

master
Jessy Diamond Exum 2017-09-10 05:34:41 -07:00
parent 30615a3774
commit 52922a8e9f
8 changed files with 161 additions and 46 deletions

View File

@ -26,9 +26,13 @@ long J2534Connection::PassThruStartMsgFilter(unsigned long FilterType, PASSTHRU_
PASSTHRU_MSG *pFlowControlMsg, unsigned long *pFilterID) {
for (int i = 0; i < this->filters.size(); i++) {
if (filters[i] == nullptr) {
filters[i].reset(new J2534MessageFilter(FilterType, pMaskMsg, pPatternMsg, pFlowControlMsg));
*pFilterID = i;
return STATUS_NOERROR;
try {
filters[i].reset(new J2534MessageFilter(this, FilterType, pMaskMsg, pPatternMsg, pFlowControlMsg));
*pFilterID = i;
return STATUS_NOERROR;
} catch (int e) {
return e;
}
}
}
return ERR_EXCEEDED_LIMIT;
@ -48,15 +52,15 @@ long J2534Connection::PassThruIoctl(unsigned long IoctlID, void *pInput, void *p
long J2534Connection::init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput) { return STATUS_NOERROR; }
long J2534Connection::initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput) { return STATUS_NOERROR; }
long J2534Connection::clearTXBuff() { return STATUS_NOERROR; }
long J2534Connection::clearRXBuff() { return STATUS_NOERROR; }
long J2534Connection::clearRXBuff() {
this->messages = {};
return STATUS_NOERROR;
}
long J2534Connection::clearPeriodicMsgs() { return STATUS_NOERROR; }
long J2534Connection::clearMsgFilters() {
for (auto& filter : this->filters) filter = nullptr;
return STATUS_NOERROR;
}
long J2534Connection::clearFunctMsgLookupTable(PASSTHRU_MSG* pInput) { return STATUS_NOERROR; }
long J2534Connection::addtoFunctMsgLookupTable(PASSTHRU_MSG* pInput) { return STATUS_NOERROR; }
long J2534Connection::deleteFromFunctMsgLookupTable() { return STATUS_NOERROR; }
long J2534Connection::setBaud(unsigned long baud) {
this->BaudRate = baud;
@ -80,7 +84,28 @@ unsigned long J2534Connection::getPort() {
}
void J2534Connection::processMessage(const PASSTHRU_MSG_INTERNAL& msg) {
EnterCriticalSection(&this->message_access_lock);
this->messages.push(msg);
LeaveCriticalSection(&this->message_access_lock);
FILTER_RESULT filter_res = FILTER_RESULT_NEUTRAL;
for (auto filter : this->filters) {
if (filter == nullptr) continue;
FILTER_RESULT current_check_res = filter->check(msg);
if (current_check_res == FILTER_RESULT_BLOCK) return;
if (current_check_res == FILTER_RESULT_PASS) filter_res = FILTER_RESULT_PASS;
}
// Optionally ignore loopbacks
if ((msg.RxStatus & TX_MSG_TYPE) == TX_MSG_TYPE && !this->loopback) return;
if (filter_res == FILTER_RESULT_PASS) {
EnterCriticalSection(&this->message_access_lock);
this->messages.push(msg);
LeaveCriticalSection(&this->message_access_lock);
}
}
unsigned long J2534Connection::getMinMsgLen() {
return 1;
}
unsigned long J2534Connection::getMaxMsgLen() {
return 4128;
}

View File

@ -3,6 +3,8 @@
#include "J2534_v0404.h"
#include "J2534MessageFilter.h"
class J2534MessageFilter;
class J2534Connection {
public:
J2534Connection(
@ -29,9 +31,6 @@ public:
long clearRXBuff();
long clearPeriodicMsgs();
long clearMsgFilters();
long clearFunctMsgLookupTable(PASSTHRU_MSG* pInput);
long addtoFunctMsgLookupTable(PASSTHRU_MSG* pInput);
long deleteFromFunctMsgLookupTable();
long setBaud(unsigned long baud);
unsigned long getBaud();
@ -44,6 +43,9 @@ public:
void processMessage(const PASSTHRU_MSG_INTERNAL& msg);
virtual unsigned long getMinMsgLen();
virtual unsigned long getMaxMsgLen();
bool loopback = FALSE;
protected:
@ -57,7 +59,7 @@ protected:
std::queue<PASSTHRU_MSG_INTERNAL> messages;
std::array<std::unique_ptr<J2534MessageFilter>, 10> filters;
std::array<std::shared_ptr<J2534MessageFilter>, 10> filters;
CRITICAL_SECTION message_access_lock;
};

View File

@ -41,7 +41,7 @@ long J2534Connection_CAN::PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pN
msg_out->DataSize = msg_in.DataSize;
memcpy(msg_out->Data, msg_in.Data.c_str(), msg_in.DataSize);
msg_out->Timestamp = msg_in.Timestamp;
msg_out->RxStatus = msg_in.RxStatus ? CAN_29BIT_ID : 0;
msg_out->RxStatus = msg_in.RxStatus;
if (msgnum == *pNumMsgs) break;
}
@ -59,7 +59,8 @@ long J2534Connection_CAN::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *p
*pNumMsgs = msgnum;
return ERR_MSG_PROTOCOL_ID;
}
if (msg->DataSize < 4 || msg->DataSize >(8 + 4) || val_is_29bit(msg->TxFlags) != this->_is_29bit()) {
if (msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen() ||
(val_is_29bit(msg->TxFlags) != this->_is_29bit() && (this->Flags & CAN_ID_BOTH) != CAN_ID_BOTH)) {
*pNumMsgs = msgnum;
return ERR_INVALID_MSG;
}
@ -72,3 +73,11 @@ long J2534Connection_CAN::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *p
}
return STATUS_NOERROR;
}
unsigned long J2534Connection_CAN::getMinMsgLen() {
return 4;
}
unsigned long J2534Connection_CAN::getMaxMsgLen() {
return 12;
}

View File

@ -15,6 +15,9 @@ public:
virtual long PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
virtual long PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
virtual unsigned long getMinMsgLen();
virtual unsigned long getMaxMsgLen();
bool _is_29bit() {
return (this->Flags & CAN_29BIT_ID) == CAN_29BIT_ID;
}

View File

@ -2,23 +2,78 @@
#include "J2534MessageFilter.h"
J2534MessageFilter::J2534MessageFilter(
J2534Connection *const conn,
unsigned int filtertype,
PASSTHRU_MSG *pMaskMsg,
PASSTHRU_MSG *pPatternMsg,
PASSTHRU_MSG *pFlowControlMsg
) : filtertype(filtertype) {
if (pMaskMsg)
memcpy(&this->MaskMsg, pMaskMsg, sizeof(PASSTHRU_MSG));
else
memset(&this->MaskMsg, 0, sizeof(PASSTHRU_MSG));
switch (filtertype) {
case PASS_FILTER:
case BLOCK_FILTER:
if (pMaskMsg == NULL || pPatternMsg == NULL)
throw ERR_NULL_PARAMETER;
if (pFlowControlMsg != NULL)
throw ERR_INVALID_MSG;
if (pMaskMsg->DataSize != pPatternMsg->DataSize)
throw ERR_INVALID_MSG;
break;
case FLOW_CONTROL_FILTER:
if (conn->getProtocol() != ISO15765) throw ERR_MSG_PROTOCOL_ID; //CHECK
if (pFlowControlMsg == NULL)
throw ERR_NULL_PARAMETER;
if (pMaskMsg == NULL || pPatternMsg == NULL)
throw ERR_INVALID_MSG;
break;
default:
throw ERR_INVALID_MSG;;
}
if (pPatternMsg)
memcpy(&this->PatternMsg, pPatternMsg, sizeof(PASSTHRU_MSG));
else
memset(&this->PatternMsg, 0, sizeof(PASSTHRU_MSG));
if (pMaskMsg) {
if (!(conn->getMinMsgLen() < pMaskMsg->DataSize || pMaskMsg->DataSize < conn->getMaxMsgLen()))
throw ERR_INVALID_MSG;
if (conn->getProtocol() != pMaskMsg->ProtocolID)
throw ERR_MSG_PROTOCOL_ID;
this->maskMsg = std::string((char*)pMaskMsg->Data, pMaskMsg->DataSize);
}
if (pFlowControlMsg)
memcpy(&this->FlowControlMsg, pFlowControlMsg, sizeof(PASSTHRU_MSG));
else
memset(&this->FlowControlMsg, 0, sizeof(PASSTHRU_MSG));
if (pPatternMsg) {
if (!(conn->getMinMsgLen() < pPatternMsg->DataSize || pPatternMsg->DataSize < conn->getMaxMsgLen()))
throw ERR_INVALID_MSG;
if (conn->getProtocol() != pPatternMsg->ProtocolID)
throw ERR_MSG_PROTOCOL_ID;
this->patternMsg = std::string((char*)pPatternMsg->Data, pPatternMsg->DataSize);
}
if (pFlowControlMsg) {
if (!(conn->getMinMsgLen() < pFlowControlMsg->DataSize || pFlowControlMsg->DataSize < conn->getMaxMsgLen()))
throw ERR_INVALID_MSG;
if (conn->getProtocol() != pFlowControlMsg->ProtocolID)
throw ERR_MSG_PROTOCOL_ID;
this->flowCtrlMsg = std::string((char*)pFlowControlMsg->Data, pFlowControlMsg->DataSize);
this->flowCtrlTxFlags = pFlowControlMsg->TxFlags;
}
};
FILTER_RESULT J2534MessageFilter::check(const PASSTHRU_MSG_INTERNAL& msg) {
bool matches = TRUE;
if (msg.DataSize < this->maskMsg.size()) {
matches = FALSE;
} else {
for (int i = 0; i < (this->maskMsg.size()); i++) {
if (this->patternMsg[i] != (msg.Data[i] & this->maskMsg[i])) {
matches = FALSE;
break;
}
}
}
switch (this->filtertype) {
case PASS_FILTER:
return matches ? FILTER_RESULT_PASS : FILTER_RESULT_NEUTRAL;
case BLOCK_FILTER:
return matches ? FILTER_RESULT_NEUTRAL : FILTER_RESULT_BLOCK;
default:
return matches ? FILTER_RESULT_PASS : FILTER_RESULT_NEUTRAL;
}
}

View File

@ -1,17 +1,31 @@
#pragma once
#include "J2534_v0404.h"
#include "J2534Connection.h"
typedef enum {
FILTER_RESULT_BLOCK,
FILTER_RESULT_NEUTRAL,
FILTER_RESULT_PASS,
} FILTER_RESULT;
//Forward declare
class J2534Connection;
class J2534MessageFilter {
public:
J2534MessageFilter(
J2534Connection *const conn,
unsigned int filtertype,
PASSTHRU_MSG *pMaskMsg,
PASSTHRU_MSG *pPatternMsg,
PASSTHRU_MSG *pFlowControlMsg
);
FILTER_RESULT check(const PASSTHRU_MSG_INTERNAL& msg);
private:
unsigned int filtertype;
PASSTHRU_MSG MaskMsg;
PASSTHRU_MSG PatternMsg;
PASSTHRU_MSG FlowControlMsg;
std::string maskMsg;
std::string patternMsg;
std::string flowCtrlMsg;
unsigned long flowCtrlTxFlags;
};

View File

@ -6,16 +6,14 @@ PandaJ2534Device::PandaJ2534Device(std::unique_ptr<panda::Panda> new_panda) {
this->panda->set_can_speed_kbps(panda::PANDA_CAN1, 500);
this->panda->set_safety_mode(panda::SAFETY_ALLOUTPUT);
this->panda->set_can_loopback(TRUE);
//this->panda->set_can_loopback(FALSE);
//this->panda->set_can_loopback(TRUE);
this->panda->set_can_loopback(FALSE);
this->panda->set_alt_setting(1);
this->panda->reset_can_interrupt_pipe();
DWORD threadid;
this->can_kill_event = CreateEvent(NULL, TRUE, FALSE, NULL);
this->can_thread_handle = CreateThread(NULL, 0, _threadBootstrap, (LPVOID)this, 0, &threadid);
printf("Created PandaDevice\n");
};
PandaJ2534Device::~PandaJ2534Device() {
@ -73,6 +71,7 @@ DWORD PandaJ2534Device::can_recv_thread() {
PASSTHRU_MSG_INTERNAL msg_out;
msg_out.ProtocolID = CAN;
msg_out.DataSize = msg_in.len + 4;
msg_out.ExtraDataIndex = msg_out.DataSize;
msg_out.Data.reserve(msg_out.DataSize);
msg_out.Data += msg_in.addr >> 24;
msg_out.Data += (msg_in.addr >> 16) & 0xFF;
@ -81,7 +80,8 @@ DWORD PandaJ2534Device::can_recv_thread() {
std::string tmp = std::string((char*)&msg_in.dat, msg_in.len);
msg_out.Data += tmp;
msg_out.Timestamp = msg_in.recv_time;
msg_out.RxStatus = msg_in.addr_29b ? CAN_29BIT_ID : 0;
msg_out.RxStatus = (msg_in.addr_29b ? CAN_29BIT_ID : 0) |
(msg_in.is_receipt ? TX_MSG_TYPE : 0);
// TODO: Make this more efficient
for (auto& conn : this->connections)

View File

@ -1,6 +1,7 @@
// pandaJ2534DLL.cpp : Defines the exported functions for the DLL application.
// Protocol derived from the following site (which shall be referred to as The Protocol Reference).
// Protocol derived from the following sites (which shall be referred to as The Protocol Reference #).
// https://web.archive.org/web/20130805013326/https://tunertools.com/prodimages/DrewTech/Manuals/PassThru_API-1.pdf
// http://web.archive.org/web/20170910063536/http://www.tiecar.net/downloads/SAE_J2534_2002.pdf
#include "stdafx.h"
#include "J2534_v0404.h"
@ -204,9 +205,9 @@ PANDAJ2534DLL_API long PTAPI PassThruReadVersion(unsigned long DeviceID, char *p
#pragma EXPORT
if (!pFirmwareVersion || !pDllVersion || !pApiVersion) return ret_code(ERR_NULL_PARAMETER);
if (check_valid_DeviceID(DeviceID) != STATUS_NOERROR) return J25334LastError;
strcpy_s(pFirmwareVersion, 6, "00.02");
strcpy_s(pDllVersion, 6, "00.01");
strcpy_s(pApiVersion, sizeof(J2534_APIVER_NOVEMBER_2004), J2534_APIVER_NOVEMBER_2004);
strcpy_s(pFirmwareVersion, 80, "00.02");
strcpy_s(pDllVersion, 80, "00.01");
strcpy_s(pApiVersion, 80, J2534_APIVER_NOVEMBER_2004);
return ret_code(STATUS_NOERROR);
}
PANDAJ2534DLL_API long PTAPI PassThruGetLastError(char *pErrorDescription) {
@ -320,6 +321,12 @@ PANDAJ2534DLL_API long PTAPI PassThruIoctl(unsigned long ChannelID, unsigned lon
case LOOPBACK:
inconfig->ConfigPtr[i].Value = get_channel(ChannelID)->loopback;
break;
case BIT_SAMPLE_POINT:
inconfig->ConfigPtr[i].Value = 80;
break;
case SYNC_JUMP_WIDTH:
inconfig->ConfigPtr[i].Value = 15;
break;
default:
// HDS rarely reads off values through ioctl GET_CONFIG, but it often
// just wants the call to pass without erroring, so just don't do anything.
@ -390,14 +397,14 @@ PANDAJ2534DLL_API long PTAPI PassThruIoctl(unsigned long ChannelID, unsigned lon
return ret_code(get_channel(ChannelID)->clearPeriodicMsgs());
case CLEAR_MSG_FILTERS:
return ret_code(get_channel(ChannelID)->clearMsgFilters());
case CLEAR_FUNCT_MSG_LOOKUP_TABLE:
case CLEAR_FUNCT_MSG_LOOKUP_TABLE: // LOOKUP TABLE IS RELATED TO J1850 PWM. Unsupported.
if (!pInput) return ret_code(ERR_NULL_PARAMETER);
return ret_code(get_channel(ChannelID)->clearFunctMsgLookupTable((PASSTHRU_MSG*)pInput));
case ADD_TO_FUNCT_MSG_LOOKUP_TABLE:
return ret_code(STATUS_NOERROR);
case ADD_TO_FUNCT_MSG_LOOKUP_TABLE: // LOOKUP TABLE IS RELATED TO J1850 PWM. Unsupported.
if (!pInput) return ret_code(ERR_NULL_PARAMETER);
return ret_code(get_channel(ChannelID)->addtoFunctMsgLookupTable((PASSTHRU_MSG*)pInput));
case DELETE_FROM_FUNCT_MSG_LOOKUP_TABLE:
return ret_code(get_channel(ChannelID)->deleteFromFunctMsgLookupTable());
return ret_code(STATUS_NOERROR);
case DELETE_FROM_FUNCT_MSG_LOOKUP_TABLE: // LOOKUP TABLE IS RELATED TO J1850 PWM. Unsupported.
return ret_code(STATUS_NOERROR);
case READ_PROG_VOLTAGE:
*(unsigned long*)pOutput = 0;
break;