Skip to content

Commit b3e2787

Browse files
authored
J2534 iso14230 (commaai#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 installer
1 parent 390b8bc commit b3e2787

19 files changed

+772
-224
lines changed

drivers/windows/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -304,3 +304,4 @@ __pycache__/
304304

305305
# installer
306306
*.exe
307+
*.zip

drivers/windows/README.md

+3-5
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,9 @@ ______/\\\\\\\\\\\____/\\\\\\\\\_______/\\\\\\\\\\\\\\\______/\\\\\\\\\\________
1717
|_| (Code by Jessy Diamond Exum)
1818
```
1919

20-
2120
# Installing J2534 driver:
2221

23-
[Download](https://github.com/commaai/panda/files/4017364/panda.J2534.driver.install.zip)
22+
[Download](https://github.com/commaai/panda/files/4844692/panda.J2534.driver.install.zip)
2423

2524
Depending on what version of windows you are on, you may need to separately install the WinUSB driver (see next section).
2625

@@ -80,8 +79,8 @@ features.
8079
- [ ] **J1850PWM** *(Outdated, and not physically supported by the panda)*
8180
- [X] **CAN**
8281
- [X] **ISO15765**
83-
- [ ] **ISO9141** *(This protocol could be implemented if 5 BAUD init support is added to the panda.)*
84-
- [ ] **ISO14230/KWP2000** *(Could be supported with FAST init, 5baud init if panda adds support for 5bps serial)*
82+
- [X] **ISO9141**
83+
- [X] **ISO14230/KWP2000**
8584

8685
# Building the Project:
8786

@@ -116,7 +115,6 @@ code will not work, so without this file, the installer will refuse to build.
116115

117116
- Apply a style-guide and consistent naming convention for Classes/Functions/Variables.
118117
- Send multiple messages (each with a different address) from a given connection at the same time.
119-
- Implement ISO14230/KWP2000 FAST (LIN communication is already supported with the raw panda USB driver).
120118
- Find more documentation about SW_CAN_PS (Single Wire CAN, aka GMLAN).
121119
- Find example of client using a _PS version of a protocol (PS is pin select, and may support using different CAN buses).
122120

drivers/windows/pandaJ2534DLL/J2534Connection.cpp

+93-16
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ J2534Connection::J2534Connection(
77
unsigned long ProtocolID,
88
unsigned long Flags,
99
unsigned long BaudRate
10-
) : panda_dev(panda_dev), ProtocolID(ProtocolID), Flags(Flags), BaudRate(BaudRate), port(0) { }
10+
) : panda_dev(panda_dev), ProtocolID(ProtocolID), Flags(Flags), BaudRate(BaudRate), Parity(0), port(0) { }
1111

1212
unsigned long J2534Connection::validateTxMsg(PASSTHRU_MSG* msg) {
1313
if (msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen())
@@ -60,7 +60,7 @@ long J2534Connection::PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMs
6060

6161
long J2534Connection::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) {
6262
//There doesn't seem to be much reason to implement the timeout here.
63-
for (int msgnum = 0; msgnum < *pNumMsgs; msgnum++) {
63+
for (unsigned int msgnum = 0; msgnum < *pNumMsgs; msgnum++) {
6464
PASSTHRU_MSG* msg = &pMsg[msgnum];
6565
if (msg->ProtocolID != this->ProtocolID) {
6666
*pNumMsgs = msgnum;
@@ -87,7 +87,7 @@ long J2534Connection::PassThruStartPeriodicMsg(PASSTHRU_MSG *pMsg, unsigned long
8787
if (pMsg->ProtocolID != this->ProtocolID) return ERR_MSG_PROTOCOL_ID;
8888
if (TimeInterval < 5 || TimeInterval > 65535) return ERR_INVALID_TIME_INTERVAL;
8989

90-
for (int i = 0; i < this->periodicMessages.size(); i++) {
90+
for (unsigned int i = 0; i < this->periodicMessages.size(); i++) {
9191
if (periodicMessages[i] != nullptr) continue;
9292

9393
*pMsgID = i;
@@ -114,11 +114,11 @@ long J2534Connection::PassThruStopPeriodicMsg(unsigned long MsgID) {
114114

115115
long J2534Connection::PassThruStartMsgFilter(unsigned long FilterType, PASSTHRU_MSG *pMaskMsg, PASSTHRU_MSG *pPatternMsg,
116116
PASSTHRU_MSG *pFlowControlMsg, unsigned long *pFilterID) {
117-
for (int i = 0; i < this->filters.size(); i++) {
117+
for (unsigned int i = 0; i < this->filters.size(); i++) {
118118
if (filters[i] == nullptr) {
119119
try {
120120
auto newfilter = std::make_shared<J2534MessageFilter>(this, FilterType, pMaskMsg, pPatternMsg, pFlowControlMsg);
121-
for (int check_idx = 0; check_idx < filters.size(); check_idx++) {
121+
for (unsigned int check_idx = 0; check_idx < filters.size(); check_idx++) {
122122
if (filters[check_idx] == nullptr) continue;
123123
if (filters[check_idx] == newfilter) {
124124
filters[i] = nullptr;
@@ -147,28 +147,99 @@ long J2534Connection::PassThruIoctl(unsigned long IoctlID, void *pInput, void *p
147147
return STATUS_NOERROR;
148148
}
149149

150-
long J2534Connection::init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput) { return ERR_FAILED; }
151-
long J2534Connection::initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput) { return ERR_FAILED; }
150+
long J2534Connection::init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput) {
151+
if (pInput->NumOfBytes == 1) {
152+
if (auto panda_ps = this->panda_dev.lock()) {
153+
auto resp = panda_ps->kline_five_baud_init(pInput->BytePtr[0]);
154+
if (resp.size() > 0) {
155+
auto key_bytes = resp.c_str();
156+
if (pOutput->NumOfBytes >= 1) {
157+
pOutput->BytePtr[0] = key_bytes[0];
158+
}
159+
if (pOutput->NumOfBytes >= 2) {
160+
pOutput->BytePtr[1] = key_bytes[1];
161+
}
162+
return STATUS_NOERROR;
163+
}
164+
}
165+
}
166+
167+
return ERR_FAILED;
168+
}
169+
long J2534Connection::initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput) {
170+
if (auto panda_ps = this->panda_dev.lock()) {
171+
auto start_comm = std::string((char*)pInput->Data, pInput->DataSize);
172+
auto resp = panda_ps->kline_wakeup_start_comm(start_comm);
173+
if (resp.size() > 0) {
174+
pOutput->ProtocolID = pInput->ProtocolID;
175+
pOutput->RxStatus = 0;
176+
pOutput->TxFlags = 0;
177+
pOutput->Timestamp = pInput->Timestamp;
178+
pOutput->ExtraDataIndex = resp.size();
179+
memcpy(pOutput->Data, resp.c_str(), resp.size());
180+
pOutput->DataSize = resp.size();
181+
return STATUS_NOERROR;
182+
}
183+
}
184+
185+
return ERR_FAILED;
186+
}
152187
long J2534Connection::clearTXBuff() {
153188
if (auto panda_ps = this->panda_dev.lock()) {
154189
synchronized(staged_writes_lock) {
155190
this->txbuff = {};
156-
panda_ps->panda->can_clear(panda::PANDA_CAN1_TX);
191+
switch (this->ProtocolID)
192+
{
193+
case CAN:
194+
case CAN_PS:
195+
case ISO15765:
196+
case ISO15765_PS:
197+
panda_ps->panda->can_clear(panda::PANDA_CAN1_TX);
198+
break;
199+
case ISO9141:
200+
case ISO9141_PS:
201+
case ISO14230:
202+
case ISO14230_PS:
203+
panda_ps->panda->serial_clear(panda::SERIAL_LIN1);
204+
panda_ps->panda->serial_clear(panda::SERIAL_LIN2);
205+
break;
206+
default:
207+
break;
208+
}
157209
}
210+
return STATUS_NOERROR;
158211
}
159-
return STATUS_NOERROR;
212+
return ERR_FAILED;
160213
}
161214
long J2534Connection::clearRXBuff() {
162215
if (auto panda_ps = this->panda_dev.lock()) {
163216
synchronized(messageRxBuff_mutex) {
164217
this->messageRxBuff = {};
165-
panda_ps->panda->can_clear(panda::PANDA_CAN_RX);
218+
switch (this->ProtocolID)
219+
{
220+
case CAN:
221+
case CAN_PS:
222+
case ISO15765:
223+
case ISO15765_PS:
224+
panda_ps->panda->can_clear(panda::PANDA_CAN_RX);
225+
break;
226+
case ISO9141:
227+
case ISO9141_PS:
228+
case ISO14230:
229+
case ISO14230_PS:
230+
panda_ps->panda->serial_clear(panda::SERIAL_LIN1);
231+
panda_ps->panda->serial_clear(panda::SERIAL_LIN2);
232+
break;
233+
default:
234+
break;
235+
}
166236
}
237+
return STATUS_NOERROR;
167238
}
168-
return STATUS_NOERROR;
239+
return ERR_FAILED;
169240
}
170241
long J2534Connection::clearPeriodicMsgs() {
171-
for (int i = 0; i < this->periodicMessages.size(); i++) {
242+
for (unsigned int i = 0; i < this->periodicMessages.size(); i++) {
172243
if (periodicMessages[i] == nullptr) continue;
173244
this->periodicMessages[i]->cancel();
174245
this->periodicMessages[i] = nullptr;
@@ -185,6 +256,10 @@ void J2534Connection::setBaud(unsigned long baud) {
185256
this->BaudRate = baud;
186257
}
187258

259+
void J2534Connection::setParity(unsigned long parity) {
260+
this->Parity = parity;
261+
}
262+
188263
void J2534Connection::schedultMsgTx(std::shared_ptr<Action> msgout) {
189264
if (auto panda_ps = this->panda_dev.lock()) {
190265
synchronized(staged_writes_lock) {
@@ -226,6 +301,9 @@ void J2534Connection::processIOCTLSetConfig(unsigned long Parameter, unsigned lo
226301
case LOOPBACK: // 0 (OFF), 1 (ON) [0]
227302
this->loopback = (Value != 0);
228303
break;
304+
case PARITY:
305+
this->setParity(Value);
306+
break;
229307
case ISO15765_WFT_MAX:
230308
break;
231309
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
247325
case TIDLE:
248326
case TINIL:
249327
case TWUP:
250-
case PARITY:
251328
case T1_MAX: // SCI related options. The panda does not appear to support this
252329
case T2_MAX:
253330
case T3_MAX:
@@ -259,9 +336,9 @@ void J2534Connection::processIOCTLSetConfig(unsigned long Parameter, unsigned lo
259336
}
260337

261338
// reserved parameters usually mean special equiptment is required
262-
if (Parameter >= 0x20) {
263-
throw ERR_NOT_SUPPORTED;
264-
}
339+
//if (Parameter >= 0x20) {
340+
// throw ERR_NOT_SUPPORTED;
341+
//}
265342
}
266343

267344
unsigned long J2534Connection::processIOCTLGetConfig(unsigned long Parameter) {

drivers/windows/pandaJ2534DLL/J2534Connection.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,15 @@ class J2534Connection : public std::enable_shared_from_this<J2534Connection> {
5151

5252
//IOCTL functions
5353

54-
long init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput);
55-
long initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput);
54+
virtual long init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput);
55+
virtual long initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput);
5656
long clearTXBuff();
5757
long clearRXBuff();
5858
long clearPeriodicMsgs();
5959
long clearMsgFilters();
6060

6161
virtual void setBaud(unsigned long baud);
62+
virtual void setParity(unsigned long parity);
6263

6364
unsigned long getBaud() {
6465
return this->BaudRate;
@@ -124,6 +125,7 @@ class J2534Connection : public std::enable_shared_from_this<J2534Connection> {
124125
unsigned long ProtocolID;
125126
unsigned long Flags;
126127
unsigned long BaudRate;
128+
unsigned long Parity;
127129
unsigned long port;
128130

129131
std::weak_ptr<PandaJ2534Device> panda_dev;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#include "stdafx.h"
2+
#include "J2534Connection_ISO14230.h"
3+
#include "MessageTx_ISO14230.h"
4+
#include "Timer.h"
5+
6+
J2534Connection_ISO14230::J2534Connection_ISO14230(
7+
std::shared_ptr<PandaJ2534Device> panda_dev,
8+
unsigned long ProtocolID,
9+
unsigned long Flags,
10+
unsigned long BaudRate
11+
) : J2534Connection(panda_dev, ProtocolID, Flags, BaudRate) {
12+
this->port = 0;
13+
14+
if (BaudRate % 100 || BaudRate < 2400 || BaudRate > 115200)
15+
throw ERR_INVALID_BAUDRATE;
16+
17+
panda_dev->panda->set_uart_baud(panda::SERIAL_LIN1, BaudRate);
18+
panda_dev->panda->set_uart_baud(panda::SERIAL_LIN2, BaudRate);
19+
};
20+
21+
unsigned long J2534Connection_ISO14230::validateTxMsg(PASSTHRU_MSG* msg) {
22+
if (msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen())
23+
return ERR_INVALID_MSG;
24+
return STATUS_NOERROR;
25+
}
26+
27+
std::shared_ptr<MessageTx> J2534Connection_ISO14230::parseMessageTx(PASSTHRU_MSG& msg) {
28+
return std::dynamic_pointer_cast<MessageTx>(std::make_shared<MessageTx_ISO14230>(shared_from_this(), msg));
29+
}
30+
31+
void J2534Connection_ISO14230::setBaud(unsigned long BaudRate) {
32+
if (auto panda_dev = this->getPandaDev()) {
33+
if (BaudRate % 100 || BaudRate < 2400 || BaudRate > 115200)
34+
throw ERR_NOT_SUPPORTED;
35+
36+
panda_dev->panda->set_uart_baud(panda::SERIAL_LIN1, BaudRate);
37+
panda_dev->panda->set_uart_baud(panda::SERIAL_LIN2, BaudRate);
38+
return J2534Connection::setBaud(BaudRate);
39+
} else {
40+
throw ERR_DEVICE_NOT_CONNECTED;
41+
}
42+
}
43+
44+
void J2534Connection_ISO14230::setParity(unsigned long Parity) {
45+
if (auto panda_dev = this->getPandaDev()) {
46+
panda::PANDA_SERIAL_PORT_PARITY parity;
47+
switch (Parity) {
48+
case 0:
49+
parity = panda::PANDA_PARITY_OFF;
50+
break;
51+
case 1:
52+
parity = panda::PANDA_PARITY_ODD;
53+
break;
54+
case 2:
55+
parity = panda::PANDA_PARITY_EVEN;
56+
break;
57+
default:
58+
throw ERR_NOT_SUPPORTED;
59+
}
60+
panda_dev->panda->set_uart_parity(panda::SERIAL_LIN1, parity);
61+
panda_dev->panda->set_uart_parity(panda::SERIAL_LIN2, parity);
62+
return J2534Connection::setParity(Parity);
63+
}
64+
else {
65+
throw ERR_DEVICE_NOT_CONNECTED;
66+
}
67+
}
68+
69+
void J2534Connection_ISO14230::processMessage(const J2534Frame& msg) {
70+
FILTER_RESULT filter_res = FILTER_RESULT_NEUTRAL;
71+
72+
for (auto filter : this->filters) {
73+
if (filter == nullptr) continue;
74+
FILTER_RESULT current_check_res = filter->check(msg);
75+
if (current_check_res == FILTER_RESULT_BLOCK) return;
76+
if (current_check_res == FILTER_RESULT_PASS) filter_res = FILTER_RESULT_PASS;
77+
}
78+
79+
if (filter_res == FILTER_RESULT_PASS) {
80+
addMsgToRxQueue(J2534Frame(msg.ProtocolID, START_OF_MESSAGE, 0, 0));
81+
addMsgToRxQueue(msg);
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#pragma once
2+
3+
#include "J2534Connection.h"
4+
#include "panda_shared/panda.h"
5+
6+
class J2534Connection_ISO14230 : public J2534Connection {
7+
public:
8+
J2534Connection_ISO14230(
9+
std::shared_ptr<PandaJ2534Device> panda_dev,
10+
unsigned long ProtocolID,
11+
unsigned long Flags,
12+
unsigned long BaudRate
13+
);
14+
15+
virtual unsigned long validateTxMsg(PASSTHRU_MSG* msg);
16+
17+
virtual std::shared_ptr<MessageTx> parseMessageTx(PASSTHRU_MSG& pMsg);
18+
19+
virtual void setBaud(unsigned long baud);
20+
virtual void setParity(unsigned long Parity);
21+
22+
virtual unsigned long getMinMsgLen() {
23+
return 2;
24+
}
25+
26+
virtual unsigned long getMaxMsgLen() {
27+
return KLINE_MSG_MAX_LEN;
28+
}
29+
30+
virtual unsigned long getMaxMsgSingleFrameLen() {
31+
return KLINE_MSG_MAX_LEN;
32+
}
33+
34+
virtual bool isProtoCan() {
35+
return FALSE;
36+
}
37+
38+
virtual void processMessage(const J2534Frame& msg);
39+
};

drivers/windows/pandaJ2534DLL/J2534Frame.h

+10
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,20 @@ class J2534Frame {
1818
Data += msg_in.addr & 0xFF;
1919
Data += std::string((char*)&msg_in.dat, msg_in.len);
2020
Timestamp = msg_in.recv_time;
21+
TxFlags = 0;
2122
RxStatus = (msg_in.addr_29b ? CAN_29BIT_ID : 0) |
2223
(msg_in.is_receipt ? TX_MSG_TYPE : 0);
2324
}
2425

26+
J2534Frame(unsigned long protocol, const panda::PANDA_KLINE_MSG& msg_in) {
27+
ProtocolID = protocol;
28+
ExtraDataIndex = msg_in.data.size() - (msg_in.valid ? 1 : 0);
29+
Data = msg_in.data;
30+
Timestamp = 0;
31+
TxFlags = 0;
32+
RxStatus = 0;
33+
}
34+
2535
J2534Frame(const PASSTHRU_MSG& msg) {
2636
this->ProtocolID = msg.ProtocolID;
2737
this->RxStatus = msg.RxStatus;

0 commit comments

Comments
 (0)