J2534 iso14230 (#563)
* ISO14230 * ISO9141 (excluding 5 baud init) * j2534 5 baud init * disable unsupported pin select protocols * update README for new installer * cleanup * cleanup * J2534 windows registry ISO9141 flag * make it easier to select dev J2534 driver * update README with new installermaster
parent
390b8bce81
commit
b3e278755c
|
@ -304,3 +304,4 @@ __pycache__/
|
|||
|
||||
# installer
|
||||
*.exe
|
||||
*.zip
|
|
@ -17,10 +17,9 @@ ______/\\\\\\\\\\\____/\\\\\\\\\_______/\\\\\\\\\\\\\\\______/\\\\\\\\\\________
|
|||
|_| (Code by Jessy Diamond Exum)
|
||||
```
|
||||
|
||||
|
||||
# Installing J2534 driver:
|
||||
|
||||
[Download](https://github.com/commaai/panda/files/4017364/panda.J2534.driver.install.zip)
|
||||
[Download](https://github.com/commaai/panda/files/4844692/panda.J2534.driver.install.zip)
|
||||
|
||||
Depending on what version of windows you are on, you may need to separately install the WinUSB driver (see next section).
|
||||
|
||||
|
@ -80,8 +79,8 @@ features.
|
|||
- [ ] **J1850PWM** *(Outdated, and not physically supported by the panda)*
|
||||
- [X] **CAN**
|
||||
- [X] **ISO15765**
|
||||
- [ ] **ISO9141** *(This protocol could be implemented if 5 BAUD init support is added to the panda.)*
|
||||
- [ ] **ISO14230/KWP2000** *(Could be supported with FAST init, 5baud init if panda adds support for 5bps serial)*
|
||||
- [X] **ISO9141**
|
||||
- [X] **ISO14230/KWP2000**
|
||||
|
||||
# Building the Project:
|
||||
|
||||
|
@ -116,7 +115,6 @@ code will not work, so without this file, the installer will refuse to build.
|
|||
|
||||
- Apply a style-guide and consistent naming convention for Classes/Functions/Variables.
|
||||
- Send multiple messages (each with a different address) from a given connection at the same time.
|
||||
- Implement ISO14230/KWP2000 FAST (LIN communication is already supported with the raw panda USB driver).
|
||||
- Find more documentation about SW_CAN_PS (Single Wire CAN, aka GMLAN).
|
||||
- Find example of client using a _PS version of a protocol (PS is pin select, and may support using different CAN buses).
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ J2534Connection::J2534Connection(
|
|||
unsigned long ProtocolID,
|
||||
unsigned long Flags,
|
||||
unsigned long BaudRate
|
||||
) : panda_dev(panda_dev), ProtocolID(ProtocolID), Flags(Flags), BaudRate(BaudRate), port(0) { }
|
||||
) : panda_dev(panda_dev), ProtocolID(ProtocolID), Flags(Flags), BaudRate(BaudRate), Parity(0), port(0) { }
|
||||
|
||||
unsigned long J2534Connection::validateTxMsg(PASSTHRU_MSG* msg) {
|
||||
if (msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen())
|
||||
|
@ -60,7 +60,7 @@ long J2534Connection::PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMs
|
|||
|
||||
long J2534Connection::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) {
|
||||
//There doesn't seem to be much reason to implement the timeout here.
|
||||
for (int msgnum = 0; msgnum < *pNumMsgs; msgnum++) {
|
||||
for (unsigned int msgnum = 0; msgnum < *pNumMsgs; msgnum++) {
|
||||
PASSTHRU_MSG* msg = &pMsg[msgnum];
|
||||
if (msg->ProtocolID != this->ProtocolID) {
|
||||
*pNumMsgs = msgnum;
|
||||
|
@ -87,7 +87,7 @@ long J2534Connection::PassThruStartPeriodicMsg(PASSTHRU_MSG *pMsg, unsigned long
|
|||
if (pMsg->ProtocolID != this->ProtocolID) return ERR_MSG_PROTOCOL_ID;
|
||||
if (TimeInterval < 5 || TimeInterval > 65535) return ERR_INVALID_TIME_INTERVAL;
|
||||
|
||||
for (int i = 0; i < this->periodicMessages.size(); i++) {
|
||||
for (unsigned int i = 0; i < this->periodicMessages.size(); i++) {
|
||||
if (periodicMessages[i] != nullptr) continue;
|
||||
|
||||
*pMsgID = i;
|
||||
|
@ -114,11 +114,11 @@ long J2534Connection::PassThruStopPeriodicMsg(unsigned long MsgID) {
|
|||
|
||||
long J2534Connection::PassThruStartMsgFilter(unsigned long FilterType, PASSTHRU_MSG *pMaskMsg, PASSTHRU_MSG *pPatternMsg,
|
||||
PASSTHRU_MSG *pFlowControlMsg, unsigned long *pFilterID) {
|
||||
for (int i = 0; i < this->filters.size(); i++) {
|
||||
for (unsigned int i = 0; i < this->filters.size(); i++) {
|
||||
if (filters[i] == nullptr) {
|
||||
try {
|
||||
auto newfilter = std::make_shared<J2534MessageFilter>(this, FilterType, pMaskMsg, pPatternMsg, pFlowControlMsg);
|
||||
for (int check_idx = 0; check_idx < filters.size(); check_idx++) {
|
||||
for (unsigned int check_idx = 0; check_idx < filters.size(); check_idx++) {
|
||||
if (filters[check_idx] == nullptr) continue;
|
||||
if (filters[check_idx] == newfilter) {
|
||||
filters[i] = nullptr;
|
||||
|
@ -147,28 +147,99 @@ long J2534Connection::PassThruIoctl(unsigned long IoctlID, void *pInput, void *p
|
|||
return STATUS_NOERROR;
|
||||
}
|
||||
|
||||
long J2534Connection::init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput) { return ERR_FAILED; }
|
||||
long J2534Connection::initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput) { return ERR_FAILED; }
|
||||
long J2534Connection::init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput) {
|
||||
if (pInput->NumOfBytes == 1) {
|
||||
if (auto panda_ps = this->panda_dev.lock()) {
|
||||
auto resp = panda_ps->kline_five_baud_init(pInput->BytePtr[0]);
|
||||
if (resp.size() > 0) {
|
||||
auto key_bytes = resp.c_str();
|
||||
if (pOutput->NumOfBytes >= 1) {
|
||||
pOutput->BytePtr[0] = key_bytes[0];
|
||||
}
|
||||
if (pOutput->NumOfBytes >= 2) {
|
||||
pOutput->BytePtr[1] = key_bytes[1];
|
||||
}
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_FAILED;
|
||||
}
|
||||
long J2534Connection::initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput) {
|
||||
if (auto panda_ps = this->panda_dev.lock()) {
|
||||
auto start_comm = std::string((char*)pInput->Data, pInput->DataSize);
|
||||
auto resp = panda_ps->kline_wakeup_start_comm(start_comm);
|
||||
if (resp.size() > 0) {
|
||||
pOutput->ProtocolID = pInput->ProtocolID;
|
||||
pOutput->RxStatus = 0;
|
||||
pOutput->TxFlags = 0;
|
||||
pOutput->Timestamp = pInput->Timestamp;
|
||||
pOutput->ExtraDataIndex = resp.size();
|
||||
memcpy(pOutput->Data, resp.c_str(), resp.size());
|
||||
pOutput->DataSize = resp.size();
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_FAILED;
|
||||
}
|
||||
long J2534Connection::clearTXBuff() {
|
||||
if (auto panda_ps = this->panda_dev.lock()) {
|
||||
synchronized(staged_writes_lock) {
|
||||
this->txbuff = {};
|
||||
panda_ps->panda->can_clear(panda::PANDA_CAN1_TX);
|
||||
switch (this->ProtocolID)
|
||||
{
|
||||
case CAN:
|
||||
case CAN_PS:
|
||||
case ISO15765:
|
||||
case ISO15765_PS:
|
||||
panda_ps->panda->can_clear(panda::PANDA_CAN1_TX);
|
||||
break;
|
||||
case ISO9141:
|
||||
case ISO9141_PS:
|
||||
case ISO14230:
|
||||
case ISO14230_PS:
|
||||
panda_ps->panda->serial_clear(panda::SERIAL_LIN1);
|
||||
panda_ps->panda->serial_clear(panda::SERIAL_LIN2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
return STATUS_NOERROR;
|
||||
return ERR_FAILED;
|
||||
}
|
||||
long J2534Connection::clearRXBuff() {
|
||||
if (auto panda_ps = this->panda_dev.lock()) {
|
||||
synchronized(messageRxBuff_mutex) {
|
||||
this->messageRxBuff = {};
|
||||
panda_ps->panda->can_clear(panda::PANDA_CAN_RX);
|
||||
switch (this->ProtocolID)
|
||||
{
|
||||
case CAN:
|
||||
case CAN_PS:
|
||||
case ISO15765:
|
||||
case ISO15765_PS:
|
||||
panda_ps->panda->can_clear(panda::PANDA_CAN_RX);
|
||||
break;
|
||||
case ISO9141:
|
||||
case ISO9141_PS:
|
||||
case ISO14230:
|
||||
case ISO14230_PS:
|
||||
panda_ps->panda->serial_clear(panda::SERIAL_LIN1);
|
||||
panda_ps->panda->serial_clear(panda::SERIAL_LIN2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
return STATUS_NOERROR;
|
||||
return ERR_FAILED;
|
||||
}
|
||||
long J2534Connection::clearPeriodicMsgs() {
|
||||
for (int i = 0; i < this->periodicMessages.size(); i++) {
|
||||
for (unsigned int i = 0; i < this->periodicMessages.size(); i++) {
|
||||
if (periodicMessages[i] == nullptr) continue;
|
||||
this->periodicMessages[i]->cancel();
|
||||
this->periodicMessages[i] = nullptr;
|
||||
|
@ -185,6 +256,10 @@ void J2534Connection::setBaud(unsigned long baud) {
|
|||
this->BaudRate = baud;
|
||||
}
|
||||
|
||||
void J2534Connection::setParity(unsigned long parity) {
|
||||
this->Parity = parity;
|
||||
}
|
||||
|
||||
void J2534Connection::schedultMsgTx(std::shared_ptr<Action> msgout) {
|
||||
if (auto panda_ps = this->panda_dev.lock()) {
|
||||
synchronized(staged_writes_lock) {
|
||||
|
@ -226,6 +301,9 @@ void J2534Connection::processIOCTLSetConfig(unsigned long Parameter, unsigned lo
|
|||
case LOOPBACK: // 0 (OFF), 1 (ON) [0]
|
||||
this->loopback = (Value != 0);
|
||||
break;
|
||||
case PARITY:
|
||||
this->setParity(Value);
|
||||
break;
|
||||
case ISO15765_WFT_MAX:
|
||||
break;
|
||||
case NODE_ADDRESS: // J1850PWM Related (Not supported by panda). HDS requires these to 'work'.
|
||||
|
@ -247,7 +325,6 @@ void J2534Connection::processIOCTLSetConfig(unsigned long Parameter, unsigned lo
|
|||
case TIDLE:
|
||||
case TINIL:
|
||||
case TWUP:
|
||||
case PARITY:
|
||||
case T1_MAX: // SCI related options. The panda does not appear to support this
|
||||
case T2_MAX:
|
||||
case T3_MAX:
|
||||
|
@ -259,9 +336,9 @@ void J2534Connection::processIOCTLSetConfig(unsigned long Parameter, unsigned lo
|
|||
}
|
||||
|
||||
// reserved parameters usually mean special equiptment is required
|
||||
if (Parameter >= 0x20) {
|
||||
throw ERR_NOT_SUPPORTED;
|
||||
}
|
||||
//if (Parameter >= 0x20) {
|
||||
// throw ERR_NOT_SUPPORTED;
|
||||
//}
|
||||
}
|
||||
|
||||
unsigned long J2534Connection::processIOCTLGetConfig(unsigned long Parameter) {
|
||||
|
|
|
@ -51,14 +51,15 @@ public:
|
|||
|
||||
//IOCTL functions
|
||||
|
||||
long init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput);
|
||||
long initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput);
|
||||
virtual long init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput);
|
||||
virtual long initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput);
|
||||
long clearTXBuff();
|
||||
long clearRXBuff();
|
||||
long clearPeriodicMsgs();
|
||||
long clearMsgFilters();
|
||||
|
||||
virtual void setBaud(unsigned long baud);
|
||||
virtual void setParity(unsigned long parity);
|
||||
|
||||
unsigned long getBaud() {
|
||||
return this->BaudRate;
|
||||
|
@ -124,6 +125,7 @@ protected:
|
|||
unsigned long ProtocolID;
|
||||
unsigned long Flags;
|
||||
unsigned long BaudRate;
|
||||
unsigned long Parity;
|
||||
unsigned long port;
|
||||
|
||||
std::weak_ptr<PandaJ2534Device> panda_dev;
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
#include "stdafx.h"
|
||||
#include "J2534Connection_ISO14230.h"
|
||||
#include "MessageTx_ISO14230.h"
|
||||
#include "Timer.h"
|
||||
|
||||
J2534Connection_ISO14230::J2534Connection_ISO14230(
|
||||
std::shared_ptr<PandaJ2534Device> panda_dev,
|
||||
unsigned long ProtocolID,
|
||||
unsigned long Flags,
|
||||
unsigned long BaudRate
|
||||
) : J2534Connection(panda_dev, ProtocolID, Flags, BaudRate) {
|
||||
this->port = 0;
|
||||
|
||||
if (BaudRate % 100 || BaudRate < 2400 || BaudRate > 115200)
|
||||
throw ERR_INVALID_BAUDRATE;
|
||||
|
||||
panda_dev->panda->set_uart_baud(panda::SERIAL_LIN1, BaudRate);
|
||||
panda_dev->panda->set_uart_baud(panda::SERIAL_LIN2, BaudRate);
|
||||
};
|
||||
|
||||
unsigned long J2534Connection_ISO14230::validateTxMsg(PASSTHRU_MSG* msg) {
|
||||
if (msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen())
|
||||
return ERR_INVALID_MSG;
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
|
||||
std::shared_ptr<MessageTx> J2534Connection_ISO14230::parseMessageTx(PASSTHRU_MSG& msg) {
|
||||
return std::dynamic_pointer_cast<MessageTx>(std::make_shared<MessageTx_ISO14230>(shared_from_this(), msg));
|
||||
}
|
||||
|
||||
void J2534Connection_ISO14230::setBaud(unsigned long BaudRate) {
|
||||
if (auto panda_dev = this->getPandaDev()) {
|
||||
if (BaudRate % 100 || BaudRate < 2400 || BaudRate > 115200)
|
||||
throw ERR_NOT_SUPPORTED;
|
||||
|
||||
panda_dev->panda->set_uart_baud(panda::SERIAL_LIN1, BaudRate);
|
||||
panda_dev->panda->set_uart_baud(panda::SERIAL_LIN2, BaudRate);
|
||||
return J2534Connection::setBaud(BaudRate);
|
||||
} else {
|
||||
throw ERR_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
void J2534Connection_ISO14230::setParity(unsigned long Parity) {
|
||||
if (auto panda_dev = this->getPandaDev()) {
|
||||
panda::PANDA_SERIAL_PORT_PARITY parity;
|
||||
switch (Parity) {
|
||||
case 0:
|
||||
parity = panda::PANDA_PARITY_OFF;
|
||||
break;
|
||||
case 1:
|
||||
parity = panda::PANDA_PARITY_ODD;
|
||||
break;
|
||||
case 2:
|
||||
parity = panda::PANDA_PARITY_EVEN;
|
||||
break;
|
||||
default:
|
||||
throw ERR_NOT_SUPPORTED;
|
||||
}
|
||||
panda_dev->panda->set_uart_parity(panda::SERIAL_LIN1, parity);
|
||||
panda_dev->panda->set_uart_parity(panda::SERIAL_LIN2, parity);
|
||||
return J2534Connection::setParity(Parity);
|
||||
}
|
||||
else {
|
||||
throw ERR_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
void J2534Connection_ISO14230::processMessage(const J2534Frame& msg) {
|
||||
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;
|
||||
}
|
||||
|
||||
if (filter_res == FILTER_RESULT_PASS) {
|
||||
addMsgToRxQueue(J2534Frame(msg.ProtocolID, START_OF_MESSAGE, 0, 0));
|
||||
addMsgToRxQueue(msg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
#pragma once
|
||||
|
||||
#include "J2534Connection.h"
|
||||
#include "panda_shared/panda.h"
|
||||
|
||||
class J2534Connection_ISO14230 : public J2534Connection {
|
||||
public:
|
||||
J2534Connection_ISO14230(
|
||||
std::shared_ptr<PandaJ2534Device> panda_dev,
|
||||
unsigned long ProtocolID,
|
||||
unsigned long Flags,
|
||||
unsigned long BaudRate
|
||||
);
|
||||
|
||||
virtual unsigned long validateTxMsg(PASSTHRU_MSG* msg);
|
||||
|
||||
virtual std::shared_ptr<MessageTx> parseMessageTx(PASSTHRU_MSG& pMsg);
|
||||
|
||||
virtual void setBaud(unsigned long baud);
|
||||
virtual void setParity(unsigned long Parity);
|
||||
|
||||
virtual unsigned long getMinMsgLen() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
virtual unsigned long getMaxMsgLen() {
|
||||
return KLINE_MSG_MAX_LEN;
|
||||
}
|
||||
|
||||
virtual unsigned long getMaxMsgSingleFrameLen() {
|
||||
return KLINE_MSG_MAX_LEN;
|
||||
}
|
||||
|
||||
virtual bool isProtoCan() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
virtual void processMessage(const J2534Frame& msg);
|
||||
};
|
|
@ -18,10 +18,20 @@ public:
|
|||
Data += msg_in.addr & 0xFF;
|
||||
Data += std::string((char*)&msg_in.dat, msg_in.len);
|
||||
Timestamp = msg_in.recv_time;
|
||||
TxFlags = 0;
|
||||
RxStatus = (msg_in.addr_29b ? CAN_29BIT_ID : 0) |
|
||||
(msg_in.is_receipt ? TX_MSG_TYPE : 0);
|
||||
}
|
||||
|
||||
J2534Frame(unsigned long protocol, const panda::PANDA_KLINE_MSG& msg_in) {
|
||||
ProtocolID = protocol;
|
||||
ExtraDataIndex = msg_in.data.size() - (msg_in.valid ? 1 : 0);
|
||||
Data = msg_in.data;
|
||||
Timestamp = 0;
|
||||
TxFlags = 0;
|
||||
RxStatus = 0;
|
||||
}
|
||||
|
||||
J2534Frame(const PASSTHRU_MSG& msg) {
|
||||
this->ProtocolID = msg.ProtocolID;
|
||||
this->RxStatus = msg.RxStatus;
|
||||
|
|
|
@ -79,7 +79,7 @@ FILTER_RESULT J2534MessageFilter::check(const J2534Frame& msg) {
|
|||
if (msg.Data.size() < this->maskMsg.size()) {
|
||||
matches = FALSE;
|
||||
} else {
|
||||
for (int i = 0; i < this->maskMsg.size(); i++) {
|
||||
for (unsigned int i = 0; i < this->maskMsg.size(); i++) {
|
||||
if (this->patternMsg[i] != (msg.Data[i] & this->maskMsg[i])) {
|
||||
matches = FALSE;
|
||||
break;
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,40 @@
|
|||
#include "stdafx.h"
|
||||
#include "MessageTx_ISO14230.h"
|
||||
#include "J2534Connection_ISO14230.h"
|
||||
|
||||
MessageTx_ISO14230::MessageTx_ISO14230(
|
||||
std::shared_ptr<J2534Connection> connection_in,
|
||||
PASSTHRU_MSG& to_send
|
||||
) : MessageTx(connection_in, to_send), sentyet(FALSE), txInFlight(FALSE) {};
|
||||
|
||||
void MessageTx_ISO14230::execute() {
|
||||
if (auto conn_sp = this->connection.lock()) {
|
||||
if (auto panda_dev_sp = conn_sp->getPandaDev()) {
|
||||
if (panda_dev_sp->kline_send(this->fullmsg.Data)) {
|
||||
if (auto conn_sp = this->connection.lock())
|
||||
{
|
||||
if (conn_sp->loopback) {
|
||||
auto echo = J2534Frame(conn_sp->getProtocol(), TX_MSG_TYPE, 0, this->fullmsg.Timestamp);
|
||||
echo.Data = std::string(this->fullmsg.Data);
|
||||
echo.ExtraDataIndex = this->fullmsg.Data.size();
|
||||
conn_sp->addMsgToRxQueue(J2534Frame(conn_sp->getProtocol(), START_OF_MESSAGE, 0, this->fullmsg.Timestamp));
|
||||
conn_sp->addMsgToRxQueue(echo);
|
||||
}
|
||||
}
|
||||
this->txInFlight = FALSE;
|
||||
this->sentyet = TRUE;
|
||||
}
|
||||
// remove action since echo was read back in kline_send()
|
||||
panda_dev_sp->removeConnectionTopAction(conn_sp, shared_from_this());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOOL MessageTx_ISO14230::checkTxReceipt(J2534Frame frame) {
|
||||
throw "not implemented!";
|
||||
}
|
||||
|
||||
void MessageTx_ISO14230::reset() {
|
||||
sentyet = FALSE;
|
||||
txInFlight = FALSE;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
#pragma once
|
||||
#include <memory>
|
||||
#include "MessageTx.h"
|
||||
|
||||
class J2534Connection;
|
||||
|
||||
class MessageTx_ISO14230 : public MessageTx
|
||||
{
|
||||
public:
|
||||
MessageTx_ISO14230(
|
||||
std::shared_ptr<J2534Connection> connection_in,
|
||||
PASSTHRU_MSG& to_send
|
||||
);
|
||||
|
||||
virtual void execute();
|
||||
|
||||
virtual BOOL checkTxReceipt(J2534Frame frame);
|
||||
|
||||
virtual BOOL isFinished() {
|
||||
return !txInFlight && sentyet;
|
||||
};
|
||||
|
||||
virtual BOOL txReady() {
|
||||
return !sentyet;
|
||||
};
|
||||
|
||||
virtual void reset();
|
||||
|
||||
private:
|
||||
BOOL sentyet;
|
||||
BOOL txInFlight;
|
||||
};
|
|
@ -12,6 +12,9 @@ PandaJ2534Device::PandaJ2534Device(std::unique_ptr<panda::Panda> new_panda) : tx
|
|||
|
||||
this->thread_kill_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
DWORD klineListenThreadID;
|
||||
this->kline_recv_handle = CreateThread(NULL, 0, _kline_recv_threadBootstrap, (LPVOID)this, 0, &klineListenThreadID);
|
||||
|
||||
DWORD canListenThreadID;
|
||||
this->can_recv_handle = CreateThread(NULL, 0, _can_recv_threadBootstrap, (LPVOID)this, 0, &canListenThreadID);
|
||||
|
||||
|
@ -25,7 +28,11 @@ PandaJ2534Device::PandaJ2534Device(std::unique_ptr<panda::Panda> new_panda) : tx
|
|||
|
||||
PandaJ2534Device::~PandaJ2534Device() {
|
||||
SetEvent(this->thread_kill_event);
|
||||
DWORD res = WaitForSingleObject(this->can_recv_handle, INFINITE);
|
||||
|
||||
DWORD res = WaitForSingleObject(this->kline_recv_handle, INFINITE);
|
||||
CloseHandle(this->kline_recv_handle);
|
||||
|
||||
res = WaitForSingleObject(this->can_recv_handle, INFINITE);
|
||||
CloseHandle(this->can_recv_handle);
|
||||
|
||||
res = WaitForSingleObject(this->can_process_handle, INFINITE);
|
||||
|
@ -73,6 +80,89 @@ DWORD PandaJ2534Device::addChannel(std::shared_ptr<J2534Connection>& conn, unsig
|
|||
return STATUS_NOERROR;
|
||||
}
|
||||
|
||||
std::string PandaJ2534Device::kline_five_baud_init(uint8_t addr) {
|
||||
synchronized(kline_rx_mutex) {
|
||||
Sleep(300); // W1
|
||||
this->panda->kline_slow_init(true, true, addr);
|
||||
// wakeup sometimes adds a leading null char
|
||||
this->panda->serial_clear(panda::SERIAL_LIN1);
|
||||
this->panda->serial_clear(panda::SERIAL_LIN2);
|
||||
// read 0x55 KB1 KB2
|
||||
auto key_bytes = this->panda->serial_read(panda::SERIAL_LIN1, 3, 300);
|
||||
auto bytes = key_bytes.c_str();
|
||||
if (key_bytes.size() == 3 && bytes[0] == 0x55) {
|
||||
Sleep(25); // W4
|
||||
// send inverted KB2
|
||||
auto kb2_inv = std::string(1, ~bytes[2]);
|
||||
if (this->panda->serial_write(panda::SERIAL_LIN1, kb2_inv)) {
|
||||
// read addr inverted
|
||||
auto addr_inv = this->panda->serial_read(panda::SERIAL_LIN1, 1, 50);
|
||||
if (addr_inv.size() == 1 && addr_inv.c_str()[0] == ~addr) {
|
||||
// return only KB1 KB2
|
||||
return key_bytes.substr(1, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::string PandaJ2534Device::kline_wakeup_start_comm(std::string& start_comm) {
|
||||
synchronized(kline_rx_mutex) {
|
||||
Sleep(25);
|
||||
this->panda->kline_fast_init(true, true);
|
||||
// wakeup sometimes adds a leading null char
|
||||
this->panda->serial_clear(panda::SERIAL_LIN1);
|
||||
this->panda->serial_clear(panda::SERIAL_LIN2);
|
||||
// send start communication message
|
||||
if (this->panda->kline_send(panda::SERIAL_LIN1, start_comm)) {
|
||||
Sleep(25);
|
||||
// read start communication response
|
||||
return this->panda->serial_read(panda::SERIAL_LIN1, KLINE_MSG_MAX_LEN, 20);
|
||||
}
|
||||
}
|
||||
|
||||
return std::string();
|
||||
}
|
||||
|
||||
BOOL PandaJ2534Device::kline_send(std::string& data) {
|
||||
// since send reads echo, block rx thread
|
||||
synchronized(kline_rx_mutex) {
|
||||
return this->panda->kline_send(panda::SERIAL_LIN1, data) ? TRUE : FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
DWORD PandaJ2534Device::kline_recv_thread() {
|
||||
this->panda->serial_clear(panda::SERIAL_LIN1);
|
||||
while (true) {
|
||||
if (!WaitForSingleObject(this->thread_kill_event, 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
std::vector<panda::PANDA_KLINE_MSG> msg_recv;
|
||||
synchronized(kline_rx_mutex) {
|
||||
msg_recv = this->panda->kline_recv(panda::SERIAL_LIN1);
|
||||
}
|
||||
if (msg_recv.empty()) {
|
||||
Sleep(1);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (auto msg : msg_recv) {
|
||||
for (auto& conn : this->connections) {
|
||||
if (conn != nullptr && !conn->isProtoCan()) {
|
||||
J2534Frame msg_out(conn->getProtocol(), msg);
|
||||
conn->processMessage(msg_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD PandaJ2534Device::can_recv_thread() {
|
||||
this->panda->can_clear(panda::PANDA_CAN_RX);
|
||||
this->panda->can_rx_q_push(this->thread_kill_event);
|
||||
|
|
|
@ -52,9 +52,19 @@ public:
|
|||
//transmission is complete. This tracks what is still waiting to hear an echo.
|
||||
std::queue<std::shared_ptr<MessageTx>> txMsgsAwaitingEcho;
|
||||
|
||||
std::string kline_five_baud_init(uint8_t addr);
|
||||
std::string kline_wakeup_start_comm(std::string& start_comm);
|
||||
BOOL kline_send(std::string& data);
|
||||
|
||||
private:
|
||||
HANDLE thread_kill_event;
|
||||
|
||||
HANDLE kline_recv_handle;
|
||||
static DWORD WINAPI _kline_recv_threadBootstrap(LPVOID This) {
|
||||
return ((PandaJ2534Device*)This)->kline_recv_thread();
|
||||
}
|
||||
DWORD kline_recv_thread();
|
||||
|
||||
HANDLE can_recv_handle;
|
||||
static DWORD WINAPI _can_recv_threadBootstrap(LPVOID This) {
|
||||
return ((PandaJ2534Device*)This)->can_recv_thread();
|
||||
|
@ -80,4 +90,6 @@ private:
|
|||
std::set<std::shared_ptr<J2534Connection>> ConnTxSet;
|
||||
Mutex connTXSet_mutex;
|
||||
BOOL txInProgress;
|
||||
|
||||
Mutex kline_rx_mutex;
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "J2534_v0404.h"
|
||||
#include "panda_shared/panda.h"
|
||||
#include "J2534Connection.h"
|
||||
#include "J2534Connection_ISO14230.h"
|
||||
#include "J2534Connection_CAN.h"
|
||||
#include "J2534Connection_ISO15765.h"
|
||||
#include "PandaJ2534Device.h"
|
||||
|
@ -95,10 +96,10 @@ PANDAJ2534DLL_API long PTAPI PassThruOpen(void *pName, unsigned long *pDevice
|
|||
if (new_panda == nullptr) {
|
||||
if(sn == "" && pandas.size() == 1)
|
||||
return ret_code(ERR_DEVICE_IN_USE);
|
||||
for (auto& pn : pandas) {
|
||||
if (pn->panda->get_usb_sn() == sn)
|
||||
return ret_code(ERR_DEVICE_IN_USE);
|
||||
}
|
||||
//for (auto& pn : pandas) {
|
||||
// if (pn->panda->get_usb_sn() == sn)
|
||||
// return ret_code(ERR_DEVICE_IN_USE);
|
||||
//}
|
||||
return ret_code(ERR_DEVICE_NOT_CONNECTED);
|
||||
}
|
||||
|
||||
|
@ -140,36 +141,36 @@ PANDAJ2534DLL_API long PTAPI PassThruConnect(unsigned long DeviceID, unsigned lo
|
|||
switch (ProtocolID) {
|
||||
//SW seems to refer to Single Wire. https://www.nxp.com/files-static/training_pdf/20451_BUS_COMM_WBT.pdf
|
||||
//SW_ protocols may be touched on here: https://www.iso.org/obp/ui/#iso:std:iso:22900:-2:ed-1:v1:en
|
||||
//case J1850VPW: // These protocols are outdated and will not be supported. HDS wants them to not fail to open.
|
||||
//case J1850PWM: // ^-- it appears HDS no longer needs this, and TIS needs it disabled --^
|
||||
//case J1850VPW_PS:
|
||||
//case J1850PWM_PS:
|
||||
case ISO9141: //This protocol could be implemented if 5 BAUD init support is added to the panda.
|
||||
case ISO9141_PS:
|
||||
case ISO14230: //Only supporting Fast init until panda adds support for 5 BAUD init.
|
||||
case ISO14230_PS:
|
||||
conn = std::make_shared<J2534Connection>(panda, ProtocolID, Flags, BaudRate);
|
||||
break;
|
||||
case CAN:
|
||||
case CAN_PS:
|
||||
//case SW_CAN_PS:
|
||||
conn = std::make_shared<J2534Connection_CAN>(panda, ProtocolID, Flags, BaudRate);
|
||||
break;
|
||||
case ISO15765:
|
||||
case ISO15765_PS:
|
||||
conn = std::make_shared<J2534Connection_ISO15765>(panda, ProtocolID, Flags, BaudRate);
|
||||
break;
|
||||
//case SW_ISO15765_PS: // SW = Single Wire. GMLAN is a SW CAN protocol
|
||||
//case GM_UART_PS: // PS = Pin Select. Handles different ports.
|
||||
//Looks like SCI based protocols may not be compatible with the panda:
|
||||
//http://mdhmotors.com/can-communications-vehicle-network-protocols/3/
|
||||
//case SCI_A_ENGINE:
|
||||
//case SCI_A_TRANS:
|
||||
//case SCI_B_ENGINE:
|
||||
//case J1850VPW: // These protocols are outdated and will not be supported. HDS wants them to not fail to open.
|
||||
//case J1850PWM: // ^-- it appears HDS no longer needs this, and TIS needs it disabled --^
|
||||
//case J1850VPW_PS:
|
||||
//case J1850PWM_PS:
|
||||
case ISO9141:
|
||||
//case ISO9141_PS:
|
||||
case ISO14230:
|
||||
//case ISO14230_PS:
|
||||
conn = std::make_shared<J2534Connection_ISO14230>(panda, ProtocolID, Flags, BaudRate);
|
||||
break;
|
||||
case CAN:
|
||||
//case CAN_PS:
|
||||
//case SW_CAN_PS:
|
||||
conn = std::make_shared<J2534Connection_CAN>(panda, ProtocolID, Flags, BaudRate);
|
||||
break;
|
||||
case ISO15765:
|
||||
//case ISO15765_PS:
|
||||
conn = std::make_shared<J2534Connection_ISO15765>(panda, ProtocolID, Flags, BaudRate);
|
||||
break;
|
||||
//case SW_ISO15765_PS: // SW = Single Wire. GMLAN is a SW CAN protocol
|
||||
//case GM_UART_PS: // PS = Pin Select. Handles different ports.
|
||||
//Looks like SCI based protocols may not be compatible with the panda:
|
||||
//http://mdhmotors.com/can-communications-vehicle-network-protocols/3/
|
||||
//case SCI_A_ENGINE:
|
||||
//case SCI_A_TRANS:
|
||||
//case SCI_B_ENGINE:
|
||||
//case SCI_B_TRANS:
|
||||
//case J2610_PS:
|
||||
default:
|
||||
return ret_code(ERR_INVALID_PROTOCOL_ID);
|
||||
//case J2610_PS:
|
||||
default:
|
||||
return ret_code(ERR_INVALID_PROTOCOL_ID);
|
||||
}
|
||||
} catch (int e) {
|
||||
return ret_code(e);
|
||||
|
@ -424,6 +425,7 @@ PANDAJ2534DLL_API long PTAPI PassThruIoctl(unsigned long ChannelID, unsigned lon
|
|||
break;
|
||||
default:
|
||||
printf("Got unknown IIOCTL %X\n", IoctlID);
|
||||
return ret_code(ERR_INVALID_IOCTL_ID);
|
||||
}
|
||||
|
||||
return ret_code(STATUS_NOERROR);
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
<ClInclude Include="..\panda\panda.h" />
|
||||
<ClInclude Include="constants_ISO15765.h" />
|
||||
<ClInclude Include="dllmain.h" />
|
||||
<ClInclude Include="J2534Connection_ISO14230.h" />
|
||||
<ClInclude Include="MessagePeriodic.h" />
|
||||
<ClInclude Include="MessageRx.h" />
|
||||
<ClInclude Include="J2534Connection.h" />
|
||||
|
@ -103,6 +104,7 @@
|
|||
<ClInclude Include="MessageTx.h" />
|
||||
<ClInclude Include="MessageTxTimeout.h" />
|
||||
<ClInclude Include="MessageTx_CAN.h" />
|
||||
<ClInclude Include="MessageTx_ISO14230.h" />
|
||||
<ClInclude Include="MessageTx_ISO15765.h" />
|
||||
<ClInclude Include="PandaJ2534Device.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
|
@ -122,11 +124,13 @@
|
|||
</ClCompile>
|
||||
<ClCompile Include="J2534Connection.cpp" />
|
||||
<ClCompile Include="J2534Connection_CAN.cpp" />
|
||||
<ClCompile Include="J2534Connection_ISO14230.cpp" />
|
||||
<ClCompile Include="J2534Connection_ISO15765.cpp" />
|
||||
<ClCompile Include="J2534MessageFilter.cpp" />
|
||||
<ClCompile Include="MessagePeriodic.cpp" />
|
||||
<ClCompile Include="MessageTxTimeout.cpp" />
|
||||
<ClCompile Include="MessageTx_CAN.cpp" />
|
||||
<ClCompile Include="MessageTx_ISO14230.cpp" />
|
||||
<ClCompile Include="MessageTx_ISO15765.cpp" />
|
||||
<ClCompile Include="PandaJ2534Device.cpp" />
|
||||
<ClCompile Include="pandaJ2534DLL.cpp" />
|
||||
|
|
|
@ -1,155 +1,173 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\depends">
|
||||
<UniqueIdentifier>{a4cd0bce-0a2a-43d9-9c9f-b21a3b607e90}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\boilerplate">
|
||||
<UniqueIdentifier>{a85ee263-380d-4d37-b167-6629cfd5177f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\boilerplate">
|
||||
<UniqueIdentifier>{010a0176-a146-4d3a-824a-fd683904774d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\J2534_CAN">
|
||||
<UniqueIdentifier>{71c9502a-ee59-4d5e-873f-c9cc792e7c76}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\J2534_ISO15765">
|
||||
<UniqueIdentifier>{4fd3183a-c457-430c-b762-f767a5788bca}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\J2534_ISO15765">
|
||||
<UniqueIdentifier>{53cd179e-22d8-43e2-bc61-516d3861fae6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\J2534_CAN">
|
||||
<UniqueIdentifier>{08d548b5-4d0b-4ce4-85e6-5ff3fc987758}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="J2534Connection.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PandaJ2534Device.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="J2534MessageFilter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="synchronize.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="J2534Connection_CAN.h">
|
||||
<Filter>Header Files\J2534_CAN</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="J2534Connection_ISO15765.h">
|
||||
<Filter>Header Files\J2534_ISO15765</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="J2534_v0404.h">
|
||||
<Filter>Header Files\depends</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\panda\panda.h">
|
||||
<Filter>Header Files\depends</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dllmain.h">
|
||||
<Filter>Header Files\boilerplate</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files\boilerplate</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files\boilerplate</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files\boilerplate</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="J2534Frame.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessageTx_ISO15765.h">
|
||||
<Filter>Header Files\J2534_ISO15765</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessageRx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="constants_ISO15765.h">
|
||||
<Filter>Header Files\J2534_ISO15765</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessageTx_CAN.h">
|
||||
<Filter>Header Files\J2534_CAN</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessageTxTimeout.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Action.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessageTx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessagePeriodic.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pandaJ2534DLL.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="J2534Connection.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PandaJ2534Device.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="J2534MessageFilter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="J2534Connection_CAN.cpp">
|
||||
<Filter>Source Files\J2534_CAN</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="J2534Connection_ISO15765.cpp">
|
||||
<Filter>Source Files\J2534_ISO15765</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files\boilerplate</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files\boilerplate</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MessageTx_ISO15765.cpp">
|
||||
<Filter>Source Files\J2534_ISO15765</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MessageTxTimeout.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MessageTx_CAN.cpp">
|
||||
<Filter>Source Files\J2534_CAN</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MessagePeriodic.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="pandaJ2534DLL.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ClassDiagram.cd" />
|
||||
</ItemGroup>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\depends">
|
||||
<UniqueIdentifier>{a4cd0bce-0a2a-43d9-9c9f-b21a3b607e90}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\boilerplate">
|
||||
<UniqueIdentifier>{a85ee263-380d-4d37-b167-6629cfd5177f}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\boilerplate">
|
||||
<UniqueIdentifier>{010a0176-a146-4d3a-824a-fd683904774d}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\J2534_CAN">
|
||||
<UniqueIdentifier>{71c9502a-ee59-4d5e-873f-c9cc792e7c76}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\J2534_ISO15765">
|
||||
<UniqueIdentifier>{4fd3183a-c457-430c-b762-f767a5788bca}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\J2534_ISO15765">
|
||||
<UniqueIdentifier>{53cd179e-22d8-43e2-bc61-516d3861fae6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\J2534_CAN">
|
||||
<UniqueIdentifier>{08d548b5-4d0b-4ce4-85e6-5ff3fc987758}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\J2534_ISO14230">
|
||||
<UniqueIdentifier>{b5c1874e-d3f8-4465-89c5-2e2b7e9f4fa4}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\J2534_ISO14230">
|
||||
<UniqueIdentifier>{b5a39015-f3ca-4888-bd5f-785aeec91345}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="J2534Connection.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="PandaJ2534Device.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="J2534MessageFilter.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="synchronize.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="J2534Connection_CAN.h">
|
||||
<Filter>Header Files\J2534_CAN</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="J2534Connection_ISO15765.h">
|
||||
<Filter>Header Files\J2534_ISO15765</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="J2534_v0404.h">
|
||||
<Filter>Header Files\depends</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\panda\panda.h">
|
||||
<Filter>Header Files\depends</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="dllmain.h">
|
||||
<Filter>Header Files\boilerplate</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files\boilerplate</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stdafx.h">
|
||||
<Filter>Header Files\boilerplate</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="targetver.h">
|
||||
<Filter>Header Files\boilerplate</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="J2534Frame.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessageTx_ISO15765.h">
|
||||
<Filter>Header Files\J2534_ISO15765</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessageRx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="constants_ISO15765.h">
|
||||
<Filter>Header Files\J2534_ISO15765</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessageTx_CAN.h">
|
||||
<Filter>Header Files\J2534_CAN</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessageTxTimeout.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Action.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessageTx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessagePeriodic.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="J2534Connection_ISO14230.h">
|
||||
<Filter>Header Files\J2534_ISO14230</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessageTx_ISO14230.h">
|
||||
<Filter>Header Files\J2534_ISO14230</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pandaJ2534DLL.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="J2534Connection.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="PandaJ2534Device.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="J2534MessageFilter.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="J2534Connection_CAN.cpp">
|
||||
<Filter>Source Files\J2534_CAN</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="J2534Connection_ISO15765.cpp">
|
||||
<Filter>Source Files\J2534_ISO15765</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="dllmain.cpp">
|
||||
<Filter>Source Files\boilerplate</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="stdafx.cpp">
|
||||
<Filter>Source Files\boilerplate</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MessageTx_ISO15765.cpp">
|
||||
<Filter>Source Files\J2534_ISO15765</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MessageTxTimeout.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MessageTx_CAN.cpp">
|
||||
<Filter>Source Files\J2534_CAN</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MessagePeriodic.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="J2534Connection_ISO14230.cpp">
|
||||
<Filter>Source Files\J2534_ISO14230</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MessageTx_ISO14230.cpp">
|
||||
<Filter>Source Files\J2534_ISO14230</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="pandaJ2534DLL.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ClassDiagram.cd" />
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -131,7 +131,7 @@ Section "J2534 Driver"
|
|||
WriteRegDWORD HKLM "${J2534_Reg_Path}" "SCI_B_ENGINE" 00000000
|
||||
WriteRegDWORD HKLM "${J2534_Reg_Path}" "SCI_B_TRANS" 00000000
|
||||
WriteRegDWORD HKLM "${J2534_Reg_Path}" "J1850PWM" 00000000
|
||||
WriteRegDWORD HKLM "${J2534_Reg_Path}" "ISO9141" 00000000
|
||||
WriteRegDWORD HKLM "${J2534_Reg_Path}" "ISO9141" 00000001
|
||||
WriteRegDWORD HKLM "${J2534_Reg_Path}" "ISO14230" 00000001
|
||||
WriteRegStr HKLM "${J2534_Reg_Path}" "Name" "panda"
|
||||
WriteRegStr HKLM "${J2534_Reg_Path}" "Vendor" "comma.ai"
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#define CAN_TRANSMIT 1
|
||||
#define CAN_EXTENDED 4
|
||||
|
||||
#define KLINE_HEADER_FMT_ADDR_MASK 0xC0
|
||||
#define KLINE_HEADER_FMT_LEN_MASK 0x3F
|
||||
|
||||
using namespace panda;
|
||||
|
||||
Panda::Panda(
|
||||
|
@ -451,7 +454,7 @@ bool Panda::can_rx_q_push(HANDLE kill_event, DWORD timeoutms) {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
void Panda::can_rx_q_pop(PANDA_CAN_MSG msg_out[], int &count) {
|
||||
void Panda::can_rx_q_pop(PANDA_CAN_MSG msg_out[], int& count) {
|
||||
count = 0;
|
||||
|
||||
// No data left in queue
|
||||
|
@ -461,8 +464,8 @@ void Panda::can_rx_q_pop(PANDA_CAN_MSG msg_out[], int &count) {
|
|||
}
|
||||
|
||||
auto r_ptr = this->r_ptr;
|
||||
for (int i = 0; i < this->can_rx_q[r_ptr].count; i += sizeof(PANDA_CAN_MSG_INTERNAL)) {
|
||||
auto in_msg_raw = (PANDA_CAN_MSG_INTERNAL *)(this->can_rx_q[r_ptr].data + i);
|
||||
for (unsigned long i = 0; i < this->can_rx_q[r_ptr].count; i += sizeof(PANDA_CAN_MSG_INTERNAL)) {
|
||||
auto in_msg_raw = (PANDA_CAN_MSG_INTERNAL*)(this->can_rx_q[r_ptr].data + i);
|
||||
msg_out[count] = parse_can_recv(in_msg_raw);
|
||||
++count;
|
||||
}
|
||||
|
@ -481,7 +484,7 @@ std::vector<PANDA_CAN_MSG> Panda::can_recv() {
|
|||
return msg_recv;
|
||||
|
||||
for (int i = 0; i < retcount; i += sizeof(PANDA_CAN_MSG_INTERNAL)) {
|
||||
PANDA_CAN_MSG_INTERNAL *in_msg_raw = (PANDA_CAN_MSG_INTERNAL *)(buff + i);
|
||||
PANDA_CAN_MSG_INTERNAL* in_msg_raw = (PANDA_CAN_MSG_INTERNAL*)(buff + i);
|
||||
auto in_msg = parse_can_recv(in_msg_raw);
|
||||
msg_recv.push_back(in_msg);
|
||||
}
|
||||
|
@ -508,15 +511,127 @@ std::string Panda::serial_read(PANDA_SERIAL_PORT port_number) {
|
|||
return result;
|
||||
}
|
||||
|
||||
int Panda::serial_write(PANDA_SERIAL_PORT port_number, const void* buff, uint16_t len) {
|
||||
std::string dat;
|
||||
dat += port_number;
|
||||
dat += std::string((char*)buff, len);
|
||||
int retcount;
|
||||
if (this->bulk_write(2, dat.c_str(), len+1, (PULONG)&retcount, 0) == FALSE) return -1;
|
||||
std::string Panda::serial_read(PANDA_SERIAL_PORT port_number, unsigned int len, unsigned int timeout_ms) {
|
||||
std::string result = std::string();
|
||||
auto ms_remaining = timeout_ms;
|
||||
char buff[0x40];
|
||||
while (len > 0 && ms_remaining > 0) {
|
||||
int retlen = this->control_transfer(REQUEST_IN, 0xe0, port_number, 0, &buff, min(len, 0x40), 0);
|
||||
if (retlen <= 0) {
|
||||
ms_remaining -= 1;
|
||||
Sleep(1);
|
||||
continue;
|
||||
}
|
||||
result += std::string(buff, retlen);
|
||||
len -= retlen;
|
||||
ms_remaining = timeout_ms;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int Panda::serial_write(PANDA_SERIAL_PORT port_number, const std::string& data) {
|
||||
int retcount = 0;
|
||||
for (int i = 0; i < data.size(); i += 0x3F) {
|
||||
std::string slice = std::string(1, (char)port_number) + data.substr(i, min(data.size() - i, 0x3F));
|
||||
int retlen;
|
||||
if (this->bulk_write(2, slice.c_str(), slice.size(), (PULONG)&retlen, 0) == FALSE) return -1;
|
||||
if (retlen != slice.size()) return -1;
|
||||
retcount += retlen - 1;
|
||||
}
|
||||
return retcount;
|
||||
}
|
||||
|
||||
bool Panda::serial_clear(PANDA_SERIAL_PORT port_number) {
|
||||
return this->control_transfer(REQUEST_OUT, 0xf2, port_number, 0, NULL, 0, 0) != -1;
|
||||
}
|
||||
|
||||
uint8_t Panda::kline_checksum(const char* data, size_t size) {
|
||||
unsigned int checksum = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
checksum += (uint8_t)data[i];
|
||||
}
|
||||
return (uint8_t)(checksum % 0x100);
|
||||
}
|
||||
|
||||
PANDA_KLINE_MSG Panda::kline_parse(const std::string& data, bool add_checksum) {
|
||||
auto bytes = data.c_str();
|
||||
auto size = data.size();
|
||||
PANDA_KLINE_MSG msg_in;
|
||||
ZeroMemory(&msg_in, sizeof(PANDA_KLINE_MSG));
|
||||
msg_in.data = std::string(data);
|
||||
|
||||
unsigned int i = 0;
|
||||
unsigned int len = 0;
|
||||
unsigned int expected_len = 2;
|
||||
if (size > i) {
|
||||
// data layout: Fmt [Tgt] [Src] [Len] Data CS <- [ ] indicates optional
|
||||
msg_in.addr_type = (PANDA_KLINE_ADDR_TYPE)(bytes[i] & KLINE_HEADER_FMT_ADDR_MASK);
|
||||
len = bytes[i++] & KLINE_HEADER_FMT_LEN_MASK;
|
||||
if (msg_in.addr_type != 0 && size > i + 2) {
|
||||
expected_len += 2;
|
||||
msg_in.target = bytes[i++];
|
||||
msg_in.source = bytes[i++];
|
||||
}
|
||||
if (len == 0 && size > i + 1) {
|
||||
expected_len += 1;
|
||||
len = bytes[i++];
|
||||
}
|
||||
expected_len += len;
|
||||
if (expected_len == size) {
|
||||
auto checksum = this->kline_checksum(bytes, size - 1);
|
||||
if (msg_in.checksum == checksum) {
|
||||
msg_in.valid = true;
|
||||
}
|
||||
}
|
||||
else if (add_checksum && expected_len == size + 1) {
|
||||
msg_in.checksum = this->kline_checksum(bytes, size);
|
||||
msg_in.data += std::string(1, (char)msg_in.checksum);
|
||||
msg_in.valid = true;
|
||||
}
|
||||
}
|
||||
|
||||
return msg_in;
|
||||
}
|
||||
|
||||
bool Panda::kline_slow_init(bool k, bool l, uint8_t addr) {
|
||||
return this->control_transfer(REQUEST_OUT, 0xf4, k && l ? 2 : (uint16_t)l, (uint16_t)addr, NULL, 0, 0) != -1;
|
||||
}
|
||||
|
||||
bool Panda::kline_fast_init(bool k, bool l) {
|
||||
return this->control_transfer(REQUEST_OUT, 0xf0, k && l ? 2 : (uint16_t)l, 0, NULL, 0, 0) != -1;
|
||||
}
|
||||
|
||||
std::vector<PANDA_KLINE_MSG> Panda::kline_recv(PANDA_SERIAL_PORT port_number) {
|
||||
if (port_number != SERIAL_LIN1 && port_number != SERIAL_LIN2) {
|
||||
throw "invalid serial port number";
|
||||
}
|
||||
|
||||
std::vector<PANDA_KLINE_MSG> msg_recv;
|
||||
|
||||
while (1) {
|
||||
// P1/P4 max time between bytes is 20ms
|
||||
auto result = this->serial_read(port_number, KLINE_MSG_MAX_LEN, 20);
|
||||
if (result.size() == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
auto msg_in = this->kline_parse(result, false);
|
||||
// TODO: only add if msg_in.valid ???
|
||||
msg_recv.push_back(msg_in);
|
||||
}
|
||||
|
||||
return msg_recv;
|
||||
}
|
||||
|
||||
bool Panda::kline_send(PANDA_SERIAL_PORT port_number, const std::string& data) {
|
||||
if (port_number != SERIAL_LIN1 && port_number != SERIAL_LIN2) {
|
||||
throw "invalid serial port number";
|
||||
}
|
||||
auto msg_out = this->kline_parse(data, true);
|
||||
auto result = this->serial_write(port_number, msg_out.data);
|
||||
auto echo = this->serial_read(port_number, msg_out.data.size(), 5);
|
||||
if (echo != msg_out.data) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#define LIN_MSG_MAX_LEN 10
|
||||
#define CAN_RX_QUEUE_LEN 10000
|
||||
#define CAN_RX_MSG_LEN 1000
|
||||
#define KLINE_MSG_MAX_LEN 260
|
||||
|
||||
//template class __declspec(dllexport) std::basic_string<char>;
|
||||
|
||||
|
@ -108,6 +109,21 @@ namespace panda {
|
|||
bool addr_29b;
|
||||
} PANDA_CAN_MSG;
|
||||
|
||||
typedef enum _PANDA_KLINE_ADDR_TYPE : uint8_t {
|
||||
PANDA_KLINE_ADDR_NONE = 0,
|
||||
PANDA_KLINE_ADDR_PHYS = 0x80,
|
||||
PANDA_KLINE_ADDR_FUNC = 0xC0,
|
||||
} PANDA_KLINE_ADDR_TYPE;
|
||||
|
||||
typedef struct _PANDA_KLINE_MSG {
|
||||
PANDA_KLINE_ADDR_TYPE addr_type;
|
||||
uint8_t target;
|
||||
uint8_t source;
|
||||
std::string data;
|
||||
uint8_t checksum;
|
||||
bool valid;
|
||||
} PANDA_KLINE_MSG;
|
||||
|
||||
//Copied from https://stackoverflow.com/a/31488113
|
||||
class Timer
|
||||
{
|
||||
|
@ -179,8 +195,17 @@ namespace panda {
|
|||
bool can_clear(PANDA_CAN_PORT_CLEAR bus);
|
||||
|
||||
std::string serial_read(PANDA_SERIAL_PORT port_number);
|
||||
int serial_write(PANDA_SERIAL_PORT port_number, const void* buff, uint16_t len);
|
||||
std::string serial_read(PANDA_SERIAL_PORT port_number, unsigned int len, unsigned int timeout_ms);
|
||||
int serial_write(PANDA_SERIAL_PORT port_number, const std::string& data);
|
||||
bool serial_clear(PANDA_SERIAL_PORT port_number);
|
||||
|
||||
uint8_t kline_checksum(const char* data, size_t size);
|
||||
PANDA_KLINE_MSG kline_parse(const std::string& data, bool add_checksum);
|
||||
bool kline_slow_init(bool k, bool l, uint8_t addr);
|
||||
bool kline_fast_init(bool k, bool l);
|
||||
std::vector<PANDA_KLINE_MSG> kline_recv(PANDA_SERIAL_PORT port_number);
|
||||
bool kline_send(PANDA_SERIAL_PORT port_number, const std::string& data);
|
||||
|
||||
private:
|
||||
Panda(
|
||||
WINUSB_INTERFACE_HANDLE WinusbHandle,
|
||||
|
|
Loading…
Reference in New Issue