J2534_WIN: PASS and Block message filters. Related aux features.
parent
30615a3774
commit
52922a8e9f
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
};
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue