J2534_WIN: ISO15765 Flow Control WAIT and ABORT support.

master
Jessy Diamond Exum 2017-10-16 02:59:26 -07:00
parent 4d02257243
commit 403aeb84eb
11 changed files with 309 additions and 74 deletions

View File

@ -44,7 +44,18 @@ std::vector<panda::PANDA_CAN_MSG> panda_recv_loop(std::unique_ptr<panda::Panda>&
} }
std::ostringstream stringStream; std::ostringstream stringStream;
stringStream << "j2534_recv_loop Broke at " << t.getTimePassed() << " ms size is " << ret_messages.size();
stringStream << "j2534_recv_loop Broke at " << t.getTimePassed() << " ms size is " << ret_messages.size() << std::endl;
if (num_expected != ret_messages.size()) {
stringStream << "Incorrect number of messages received. Displaying the messages:" << std::endl;
for (auto msg : ret_messages) {
stringStream << " TS: " << msg.recv_time << "; Dat: ";
for (int i = 0; i < msg.len; i++) stringStream << std::hex << std::setw(2) << std::setfill('0') << int(msg.dat[i] & 0xFF) << " ";
stringStream << std::endl;
}
}
Logger::WriteMessage(stringStream.str().c_str()); Logger::WriteMessage(stringStream.str().c_str());
Assert::AreEqual<unsigned long>(num_expected, ret_messages.size(), _T("Received wrong number of messages.")); Assert::AreEqual<unsigned long>(num_expected, ret_messages.size(), _T("Received wrong number of messages."));

View File

@ -1322,6 +1322,177 @@ namespace pandaJ2534DLLTest
j2534_recv_loop(chanid, 0); j2534_recv_loop(chanid, 0);
} }
//Check MF tx will stop upon receiving a flow control ABORT. 29 bit. Good Filter. NoPadding. STD address. Large STmin, then abort, then send SF.
TEST_METHOD(J2534_ISO15765_SuccessTx_29b_Filter_NoPad_STD__MF_FCAbort_SF)
{
auto chanid = J2534_open_and_connect("", ISO15765, CAN_29BIT_ID, 500000, LINE_INFO());
J2534_set_flowctrl_filter(chanid, CAN_29BIT_ID, 4, "\xff\xff\xff\xff", "\x18\xda\xf1\xef", "\x18\xda\xef\xf1", LINE_INFO());
write_ioctl(chanid, LOOPBACK, TRUE, LINE_INFO());
auto p = getPanda(500);
J2534_send_msg_checked(chanid, ISO15765, 0, CAN_29BIT_ID, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
auto panda_msg_recv = panda_recv_loop(p, 1);
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x10\x30""AABBCC", LINE_INFO());
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x30\x02\x20", 3, 2, LINE_INFO());//Start a conversation. FC timeout is 32 ms.
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x21""DDEEFFG", LINE_INFO());
check_panda_can_msg(panda_msg_recv[1], 0, 0x18DAEFF1, TRUE, FALSE, "\x22""GHHIIJJ", LINE_INFO());
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x32\x0\x0", 3, 0, LINE_INFO());//Abort the conversation
J2534_send_msg_checked(chanid, ISO15765, 0, CAN_29BIT_ID, 0, 4 + 4, 0, "\x18\xda\xef\xf1""SUP!", LINE_INFO());
auto j2534_msg_recv = j2534_recv_loop(chanid, 2);
check_J2534_can_msg(j2534_msg_recv[0], ISO15765, CAN_29BIT_ID | TX_INDICATION, 0, 4, 0, "\x18\xda\xef\xf1", LINE_INFO());
check_J2534_can_msg(j2534_msg_recv[1], ISO15765, CAN_29BIT_ID | TX_MSG_TYPE, 0, 4 + 4, 0, "\x18\xda\xef\xf1""SUP!", LINE_INFO());
}
//Check MF tx will stop upon receiving a flow control ABORT during valid blocksize. 29 bit. Good Filter. NoPadding. STD address. Large STmin, then mid tx abort, then send SF.
TEST_METHOD(J2534_ISO15765_SuccessTx_29b_Filter_NoPad_STD__MF_FCMixTXAbort_SF)
{
auto chanid = J2534_open_and_connect("", ISO15765, CAN_29BIT_ID, 500000, LINE_INFO());
J2534_set_flowctrl_filter(chanid, CAN_29BIT_ID, 4, "\xff\xff\xff\xff", "\x18\xda\xf1\xef", "\x18\xda\xef\xf1", LINE_INFO());
write_ioctl(chanid, LOOPBACK, TRUE, LINE_INFO());
auto p = getPanda(500);
J2534_send_msg_checked(chanid, ISO15765, 0, CAN_29BIT_ID, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
auto panda_msg_recv = panda_recv_loop(p, 1);
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x10\x30""AABBCC", LINE_INFO());
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x30\x06\x7F", 3, 1, LINE_INFO(), 200);//Start a conversation. FC timeout is 127 ms.
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x21""DDEEFFG", LINE_INFO());
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x32\x0\x0", 3, 0, LINE_INFO());//Abort the conversation
panda_recv_loop(p, 0, 200);
J2534_send_msg_checked(chanid, ISO15765, 0, CAN_29BIT_ID, 0, 4 + 4, 0, "\x18\xda\xef\xf1""SUP!", LINE_INFO());
auto j2534_msg_recv = j2534_recv_loop(chanid, 2);
check_J2534_can_msg(j2534_msg_recv[0], ISO15765, CAN_29BIT_ID | TX_INDICATION, 0, 4, 0, "\x18\xda\xef\xf1", LINE_INFO());
check_J2534_can_msg(j2534_msg_recv[1], ISO15765, CAN_29BIT_ID | TX_MSG_TYPE, 0, 4 + 4, 0, "\x18\xda\xef\xf1""SUP!", LINE_INFO());
}
//Check slow tx can be stalled past timeout with CF WAIT frames. 29 bit. Good Filter. NoPadding. STD address. MF tx that would timeout without WAIT frames.
TEST_METHOD(J2534_ISO15765_SuccessTx_29b_Filter_NoPad_STD_MFWithWaitFrames)
{
auto chanid = J2534_open_and_connect("", ISO15765, CAN_29BIT_ID, 500000, LINE_INFO());
J2534_set_flowctrl_filter(chanid, CAN_29BIT_ID, 4, "\xff\xff\xff\xff", "\x18\xda\xf1\xef", "\x18\xda\xef\xf1", LINE_INFO());
write_ioctl(chanid, LOOPBACK, TRUE, LINE_INFO());
write_ioctl(chanid, ISO15765_WFT_MAX, 10, LINE_INFO());
auto p = getPanda(500);
J2534_send_msg_checked(chanid, ISO15765, 0, CAN_29BIT_ID, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
auto panda_msg_recv = panda_recv_loop(p, 1);
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x10\x30""AABBCC", LINE_INFO());
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x30\x02\x40", 3, 2, LINE_INFO(), 3000);//Start a conversation. FC timeout is 250 ms.
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x21""DDEEFFG", LINE_INFO());
check_panda_can_msg(panda_msg_recv[1], 0, 0x18DAEFF1, TRUE, FALSE, "\x22""GHHIIJJ", LINE_INFO());
checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x30\x0\x0", 3, 4, LINE_INFO(), 3000);//Start a conversation. FC timeout is 250 ms.
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x23""KKLLMMN", LINE_INFO());
check_panda_can_msg(panda_msg_recv[1], 0, 0x18DAEFF1, TRUE, FALSE, "\x24""NOOPPQQ", LINE_INFO());
check_panda_can_msg(panda_msg_recv[2], 0, 0x18DAEFF1, TRUE, FALSE, "\x25""RRSSTTU", LINE_INFO());//Some of these should fail to recv if there is an issue.
check_panda_can_msg(panda_msg_recv[3], 0, 0x18DAEFF1, TRUE, FALSE, "\x26""UVVWWXX", LINE_INFO());
auto j2534_msg_recv = j2534_recv_loop(chanid, 2);
check_J2534_can_msg(j2534_msg_recv[0], ISO15765, CAN_29BIT_ID | TX_INDICATION, 0, 4, 0, "\x18\xda\xef\xf1", LINE_INFO());
check_J2534_can_msg(j2534_msg_recv[1], ISO15765, CAN_29BIT_ID | TX_MSG_TYPE, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
}
//Check slow tx can be stalled past timeout with CF WAIT frames during normal TX. 29 bit. Good Filter. NoPadding. STD address. Stalling working MF tx.
TEST_METHOD(J2534_ISO15765_SuccessTx_29b_Filter_NoPad_STD_MFWithMidTXWaitFrames)
{
auto chanid = J2534_open_and_connect("", ISO15765, CAN_29BIT_ID, 500000, LINE_INFO());
J2534_set_flowctrl_filter(chanid, CAN_29BIT_ID, 4, "\xff\xff\xff\xff", "\x18\xda\xf1\xef", "\x18\xda\xef\xf1", LINE_INFO());
write_ioctl(chanid, LOOPBACK, TRUE, LINE_INFO());
write_ioctl(chanid, ISO15765_WFT_MAX, 10, LINE_INFO());
auto p = getPanda(500);
J2534_send_msg_checked(chanid, ISO15765, 0, CAN_29BIT_ID, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
auto panda_msg_recv = panda_recv_loop(p, 1);
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x10\x30""AABBCC", LINE_INFO());
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x30\x06\x64", 3, 2, LINE_INFO(), 120);//Start a conversation. STmin 100. FC timeout is 250 ms.
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x21""DDEEFFG", LINE_INFO());
check_panda_can_msg(panda_msg_recv[1], 0, 0x18DAEFF1, TRUE, FALSE, "\x22""GHHIIJJ", LINE_INFO());
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x30\x0\x0", 3, 4, LINE_INFO(), 3000);//Start a conversation. FC timeout is 250 ms.
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x23""KKLLMMN", LINE_INFO());
check_panda_can_msg(panda_msg_recv[1], 0, 0x18DAEFF1, TRUE, FALSE, "\x24""NOOPPQQ", LINE_INFO());
check_panda_can_msg(panda_msg_recv[2], 0, 0x18DAEFF1, TRUE, FALSE, "\x25""RRSSTTU", LINE_INFO());//Some of these should fail to recv if there is an issue.
check_panda_can_msg(panda_msg_recv[3], 0, 0x18DAEFF1, TRUE, FALSE, "\x26""UVVWWXX", LINE_INFO());
auto j2534_msg_recv = j2534_recv_loop(chanid, 2);
check_J2534_can_msg(j2534_msg_recv[0], ISO15765, CAN_29BIT_ID | TX_INDICATION, 0, 4, 0, "\x18\xda\xef\xf1", LINE_INFO());
check_J2534_can_msg(j2534_msg_recv[1], ISO15765, CAN_29BIT_ID | TX_MSG_TYPE, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
}
//Check that too many WAIT frames will abort the transfer. 29 bit. Good Filter. NoPadding. STD address. Too much stalling causes abort.
TEST_METHOD(J2534_ISO15765_SuccessTx_29b_Filter_NoPad_STD_MFTooManyWaitFrames)
{
auto chanid = J2534_open_and_connect("", ISO15765, CAN_29BIT_ID, 500000, LINE_INFO());
J2534_set_flowctrl_filter(chanid, CAN_29BIT_ID, 4, "\xff\xff\xff\xff", "\x18\xda\xf1\xef", "\x18\xda\xef\xf1", LINE_INFO());
write_ioctl(chanid, LOOPBACK, TRUE, LINE_INFO());
write_ioctl(chanid, ISO15765_WFT_MAX, 2, LINE_INFO());
auto p = getPanda(500);
J2534_send_msg_checked(chanid, ISO15765, 0, CAN_29BIT_ID, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
auto panda_msg_recv = panda_recv_loop(p, 1);
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x10\x30""AABBCC", LINE_INFO());
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x30\x02\x64", 3, 2, LINE_INFO(), 120);//Start a conversation. STmin 100. FC timeout is 250 ms.
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x21""DDEEFFG", LINE_INFO());
check_panda_can_msg(panda_msg_recv[1], 0, 0x18DAEFF1, TRUE, FALSE, "\x22""GHHIIJJ", LINE_INFO());
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x30\x02\x64", 3, 2, LINE_INFO(), 120);//Resume the conversation.
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x23""KKLLMMN", LINE_INFO());
check_panda_can_msg(panda_msg_recv[1], 0, 0x18DAEFF1, TRUE, FALSE, "\x24""NOOPPQQ", LINE_INFO());
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x31\x0\x0", 3, 0, LINE_INFO(), 100);//Delay the conversation.
Sleep(100);
//Should not resume because the conversation has been delayed too long.
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x30\x0\x0", 3, 0, LINE_INFO(), 300);
//Send a SF message to check the tubes are not clogged.
J2534_send_msg_checked(chanid, ISO15765, 0, CAN_29BIT_ID, 0, 4 + 4, 0, "\x18\xda\xef\xf1""SUP!", LINE_INFO());
auto j2534_msg_recv = j2534_recv_loop(chanid, 2);
check_J2534_can_msg(j2534_msg_recv[0], ISO15765, CAN_29BIT_ID | TX_INDICATION, 0, 4, 0, "\x18\xda\xef\xf1", LINE_INFO());
check_J2534_can_msg(j2534_msg_recv[1], ISO15765, CAN_29BIT_ID | TX_MSG_TYPE, 0, 4 + 4, 0, "\x18\xda\xef\xf1""SUP!", LINE_INFO());
}
///////////////////// Tests checking things actually send/receive. Ext 5 byte Addressing ///////////////////// ///////////////////// Tests checking things actually send/receive. Ext 5 byte Addressing /////////////////////
//Check rx passes with filter. 29 bit. Good Filter. NoPadding. EXT address. Single Frame. //Check rx passes with filter. 29 bit. Good Filter. NoPadding. EXT address. Single Frame.

View File

@ -161,9 +161,8 @@ long J2534Connection::clearMsgFilters() {
return STATUS_NOERROR; return STATUS_NOERROR;
} }
long J2534Connection::setBaud(unsigned long baud) { void J2534Connection::setBaud(unsigned long baud) {
this->BaudRate = baud; this->BaudRate = baud;
return STATUS_NOERROR;
} }
void J2534Connection::schedultMsgTx(std::shared_ptr<Action> msgout) { void J2534Connection::schedultMsgTx(std::shared_ptr<Action> msgout) {
@ -198,3 +197,61 @@ void J2534Connection::processMessage(const J2534Frame& msg) {
addMsgToRxQueue(msg); addMsgToRxQueue(msg);
} }
} }
void J2534Connection::processIOCTLSetConfig(unsigned long Parameter, unsigned long Value) {
switch (Parameter) {
case DATA_RATE: // 5-500000
this->setBaud(Value);
case LOOPBACK: // 0 (OFF), 1 (ON) [0]
this->loopback = (Value != 0);
break;
case ISO15765_WFT_MAX:
break;
case NODE_ADDRESS: // J1850PWM Related (Not supported by panda). HDS requires these to 'work'.
case NETWORK_LINE:
case P1_MIN: // A bunch of stuff relating to ISO9141 and ISO14230 that the panda
case P1_MAX: // currently doesn't support. Don't let HDS know we can't use these.
case P2_MIN:
case P2_MAX:
case P3_MIN:
case P3_MAX:
case P4_MIN:
case P4_MAX:
case W0:
case W1:
case W2:
case W3:
case W4:
case W5:
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:
case T4_MAX:
case T5_MAX:
break; // Just smile and nod.
default:
printf("Got unknown SET code %X\n", Parameter);
}
}
unsigned long J2534Connection::processIOCTLGetConfig(unsigned long Parameter) {
switch (Parameter) {
case DATA_RATE:
return this->getBaud();
case LOOPBACK:
return this->loopback;
break;
case BIT_SAMPLE_POINT:
return 80;
case SYNC_JUMP_WIDTH:
return 15;
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.
printf("Got unknown code %X\n", Parameter);
}
}

View File

@ -47,7 +47,7 @@ public:
long clearPeriodicMsgs(); long clearPeriodicMsgs();
long clearMsgFilters(); long clearMsgFilters();
virtual long setBaud(unsigned long baud); virtual void setBaud(unsigned long baud);
unsigned long getBaud() { unsigned long getBaud() {
return this->BaudRate; return this->BaudRate;
@ -65,6 +65,10 @@ public:
return this->port; return this->port;
} }
virtual void processIOCTLSetConfig(unsigned long Parameter, unsigned long Value);
virtual unsigned long processIOCTLGetConfig(unsigned long Parameter);
virtual void processMessage(const J2534Frame& msg); virtual void processMessage(const J2534Frame& msg);
virtual unsigned long getMinMsgLen() { virtual unsigned long getMinMsgLen() {

View File

@ -28,14 +28,14 @@ std::shared_ptr<MessageTx> J2534Connection_CAN::parseMessageTx(PASSTHRU_MSG& msg
return std::dynamic_pointer_cast<MessageTx>(std::make_shared<MessageTx_CAN>(shared_from_this(), msg)); return std::dynamic_pointer_cast<MessageTx>(std::make_shared<MessageTx_CAN>(shared_from_this(), msg));
} }
long J2534Connection_CAN::setBaud(unsigned long BaudRate) { void J2534Connection_CAN::setBaud(unsigned long BaudRate) {
if (auto panda_dev = this->getPandaDev()) { if (auto panda_dev = this->getPandaDev()) {
if (BaudRate % 100 || BaudRate < 10000 || BaudRate > 5000000) if (BaudRate % 100 || BaudRate < 10000 || BaudRate > 5000000)
return ERR_NOT_SUPPORTED; throw ERR_NOT_SUPPORTED;
panda_dev->panda->set_can_speed_cbps(panda::PANDA_CAN1, (uint16_t)(BaudRate / 100)); panda_dev->panda->set_can_speed_cbps(panda::PANDA_CAN1, (uint16_t)(BaudRate / 100));
return J2534Connection::setBaud(BaudRate); return J2534Connection::setBaud(BaudRate);
} else { } else {
return ERR_DEVICE_NOT_CONNECTED; throw ERR_DEVICE_NOT_CONNECTED;
} }
} }

View File

@ -18,7 +18,7 @@ public:
virtual std::shared_ptr<MessageTx> parseMessageTx(PASSTHRU_MSG& pMsg); virtual std::shared_ptr<MessageTx> parseMessageTx(PASSTHRU_MSG& pMsg);
virtual long setBaud(unsigned long baud); virtual void setBaud(unsigned long baud);
virtual unsigned long getMinMsgLen() { virtual unsigned long getMinMsgLen() {
return 4; return 4;

View File

@ -9,7 +9,7 @@ J2534Connection_ISO15765::J2534Connection_ISO15765(
unsigned long ProtocolID, unsigned long ProtocolID,
unsigned long Flags, unsigned long Flags,
unsigned long BaudRate unsigned long BaudRate
) : J2534Connection(panda_dev, ProtocolID, Flags, BaudRate) { ) : J2534Connection(panda_dev, ProtocolID, Flags, BaudRate), wftMax(0) {
this->port = 0; this->port = 0;
if (BaudRate % 100 || BaudRate < 10000 || BaudRate > 5000000) if (BaudRate % 100 || BaudRate < 10000 || BaudRate > 5000000)
@ -76,11 +76,10 @@ void J2534Connection_ISO15765::processMessage(const J2534Frame& msg) {
break; break;
} }
case FLOWCTRL_WAIT: case FLOWCTRL_WAIT:
txConvo->flowControlWait(); txConvo->flowControlWait(this->wftMax);
break; break;
case FLOWCTRL_ABORT: case FLOWCTRL_ABORT:
txConvo->flowControlAbort(); txConvo->flowControlAbort();
this->rxConversations[fid] = nullptr;
break; break;
} }
break; break;
@ -170,15 +169,15 @@ void J2534Connection_ISO15765::processMessage(const J2534Frame& msg) {
} }
} }
long J2534Connection_ISO15765::setBaud(unsigned long BaudRate) { void J2534Connection_ISO15765::setBaud(unsigned long BaudRate) {
if (auto panda_dev = this->getPandaDev()) { if (auto panda_dev = this->getPandaDev()) {
if (BaudRate % 100 || BaudRate < 10000 || BaudRate > 5000000) if (BaudRate % 100 || BaudRate < 10000 || BaudRate > 5000000)
return ERR_NOT_SUPPORTED; throw ERR_NOT_SUPPORTED;
panda_dev->panda->set_can_speed_cbps(panda::PANDA_CAN1, (uint16_t)(BaudRate / 100)); panda_dev->panda->set_can_speed_cbps(panda::PANDA_CAN1, (uint16_t)(BaudRate / 100));
return J2534Connection::setBaud(BaudRate); return J2534Connection::setBaud(BaudRate);
} else { } else {
return ERR_DEVICE_NOT_CONNECTED; throw ERR_DEVICE_NOT_CONNECTED;
} }
} }
@ -209,3 +208,22 @@ int J2534Connection_ISO15765::get_matching_in_fc_filter_id(const J2534Frame& msg
} }
return -1; return -1;
} }
void J2534Connection_ISO15765::processIOCTLSetConfig(unsigned long Parameter, unsigned long Value) {
switch (Parameter) {
case ISO15765_WFT_MAX:
this->wftMax = Value;
break;
default:
J2534Connection::processIOCTLSetConfig(Parameter, Value);
}
}
unsigned long J2534Connection_ISO15765::processIOCTLGetConfig(unsigned long Parameter) {
switch (Parameter) {
case ISO15765_WFT_MAX:
return this->wftMax;
default:
return J2534Connection::processIOCTLGetConfig(Parameter);
}
}

View File

@ -33,7 +33,11 @@ public:
virtual void processMessage(const J2534Frame& msg); virtual void processMessage(const J2534Frame& msg);
virtual long setBaud(unsigned long baud); virtual void setBaud(unsigned long baud);
virtual void processIOCTLSetConfig(unsigned long Parameter, unsigned long Value);
virtual unsigned long processIOCTLGetConfig(unsigned long Parameter);
virtual unsigned long getMinMsgLen() { virtual unsigned long getMinMsgLen() {
return 4; return 4;
@ -57,4 +61,5 @@ public:
private: private:
std::array<std::shared_ptr<MessageRx>, 10> rxConversations; std::array<std::shared_ptr<MessageRx>, 10> rxConversations;
unsigned int wftMax;
}; };

View File

@ -11,7 +11,7 @@ MessageTx_ISO15765::MessageTx_ISO15765(
PASSTHRU_MSG& to_send, PASSTHRU_MSG& to_send,
std::shared_ptr<J2534MessageFilter> filter std::shared_ptr<J2534MessageFilter> filter
) : MessageTxTimeoutable(connection_in, to_send), filter(filter), frames_sent(0), ) : MessageTxTimeoutable(connection_in, to_send), filter(filter), frames_sent(0),
consumed_count(0), txInFlight(FALSE), sendAll(FALSE), block_size(0), numWaitFrames(0), didtimeout(FALSE) { consumed_count(0), txInFlight(FALSE), sendAll(FALSE), block_size(0), numWaitFrames(0), didtimeout(FALSE), issuspended(FALSE){
CANid = ((uint8_t)fullmsg.Data[0]) << 24 | ((uint8_t)fullmsg.Data[1]) << 16 | CANid = ((uint8_t)fullmsg.Data[0]) << 24 | ((uint8_t)fullmsg.Data[1]) << 16 |
((uint8_t)fullmsg.Data[2]) << 8 | ((uint8_t)fullmsg.Data[3]); ((uint8_t)fullmsg.Data[2]) << 8 | ((uint8_t)fullmsg.Data[3]);
@ -57,7 +57,7 @@ unsigned int MessageTx_ISO15765::addressLength() {
} }
void MessageTx_ISO15765::execute() { void MessageTx_ISO15765::execute() {
if (didtimeout) return; if (didtimeout || issuspended) return;
if (this->frames_sent >= this->framePayloads.size()) return; if (this->frames_sent >= this->framePayloads.size()) return;
if (block_size == 0 && !sendAll && this->frames_sent > 0) return; if (block_size == 0 && !sendAll && this->frames_sent > 0) return;
if (block_size > 0 && !sendAll) block_size--; if (block_size > 0 && !sendAll) block_size--;
@ -86,7 +86,7 @@ BOOL MessageTx_ISO15765::checkTxReceipt(J2534Frame frame) {
((this->fullmsg.TxFlags & CAN_29BIT_ID) == (frame.RxStatus & CAN_29BIT_ID))) { //Check receipt is expected ((this->fullmsg.TxFlags & CAN_29BIT_ID) == (frame.RxStatus & CAN_29BIT_ID))) { //Check receipt is expected
txInFlight = FALSE; //Received the expected receipt. Allow another msg to be sent. txInFlight = FALSE; //Received the expected receipt. Allow another msg to be sent.
if(this->recvCount == 0 && this->framePayloads.size() > 1) if (this->recvCount == 0 && this->framePayloads.size() > 1)
scheduleTimeout(TIMEOUT_FC); scheduleTimeout(TIMEOUT_FC);
if (frames_sent == framePayloads.size()) { //Check message done if (frames_sent == framePayloads.size()) { //Check message done
@ -115,7 +115,7 @@ BOOL MessageTx_ISO15765::checkTxReceipt(J2534Frame frame) {
//already been received (differentiating from first frame), the //already been received (differentiating from first frame), the
//message is not finished, and there is more than one frame in //message is not finished, and there is more than one frame in
//the message. //the message.
if(block_size == 0 && recvCount != 0 && !sendAll && !this->isFinished() && this->framePayloads.size() > 1) if (block_size == 0 && recvCount != 0 && !sendAll && !this->isFinished() && this->framePayloads.size() > 1)
scheduleTimeout(TIMEOUT_CF); scheduleTimeout(TIMEOUT_CF);
} }
return TRUE; return TRUE;
@ -151,19 +151,30 @@ void MessageTx_ISO15765::onTimeout() {
} }
void MessageTx_ISO15765::flowControlContinue(uint8_t block_size, std::chrono::microseconds separation_time) { void MessageTx_ISO15765::flowControlContinue(uint8_t block_size, std::chrono::microseconds separation_time) {
this->issuspended = FALSE;
this->block_size = block_size; this->block_size = block_size;
this->delay = separation_time; this->delay = separation_time;
this->sendAll = block_size == 0; this->sendAll = block_size == 0;
this->recvCount++; this->recvCount++;
} }
void MessageTx_ISO15765::flowControlWait() { void MessageTx_ISO15765::flowControlWait(unsigned long N_WFTmax) {
this->issuspended = TRUE;
this->recvCount++; this->recvCount++;
this->numWaitFrames++; this->numWaitFrames++;
this->sendAll = FALSE; this->sendAll = FALSE;
scheduleTimeout(TIMEOUT_FC); this->block_size = block_size;
this->delay = std::chrono::microseconds(0);
//Docs are vague on if 0 means NO WAITS ALLOWED or NO LIMIT TO WAITS.
//It is less likely to cause issue if NO LIMIT is assumed.
if (N_WFTmax > 0 && this->numWaitFrames > N_WFTmax) {
this->onTimeout(); //Trigger self destruction of message.
} else {
scheduleTimeout(TIMEOUT_FC);
}
} }
void MessageTx_ISO15765::flowControlAbort() { void MessageTx_ISO15765::flowControlAbort() {
this->recvCount++; this->recvCount++; //Invalidate future timeout actions.
this->onTimeout(); //Trigger self destruction of message.
} }

View File

@ -28,7 +28,7 @@ public:
virtual void onTimeout(); virtual void onTimeout();
void MessageTx_ISO15765::flowControlContinue(uint8_t block_size, std::chrono::microseconds separation_time); void MessageTx_ISO15765::flowControlContinue(uint8_t block_size, std::chrono::microseconds separation_time);
void MessageTx_ISO15765::flowControlWait(); void MessageTx_ISO15765::flowControlWait(unsigned long N_WFTmax);
void MessageTx_ISO15765::flowControlAbort(); void MessageTx_ISO15765::flowControlAbort();
std::shared_ptr<J2534MessageFilter> filter; std::shared_ptr<J2534MessageFilter> filter;
@ -44,4 +44,5 @@ public:
BOOL sendAll; BOOL sendAll;
unsigned int numWaitFrames; unsigned int numWaitFrames;
BOOL didtimeout; BOOL didtimeout;
BOOL issuspended;
}; };

View File

@ -374,23 +374,10 @@ PANDAJ2534DLL_API long PTAPI PassThruIoctl(unsigned long ChannelID, unsigned lon
if (inconfig == NULL) if (inconfig == NULL)
return ret_code(ERR_NULL_PARAMETER); return ret_code(ERR_NULL_PARAMETER);
for (unsigned int i = 0; i < inconfig->NumOfParams; i++) { for (unsigned int i = 0; i < inconfig->NumOfParams; i++) {
switch (inconfig->ConfigPtr[i].Parameter) { try {
case DATA_RATE: inconfig->ConfigPtr[i].Value = get_channel(ChannelID)->processIOCTLGetConfig(inconfig->ConfigPtr[i].Parameter);
inconfig->ConfigPtr[i].Value = get_channel(ChannelID)->getBaud(); } catch (int e) {
break; return ret_code(e);
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.
printf("Got unknown code %X\n", inconfig->ConfigPtr[i].Parameter);
} }
} }
break; break;
@ -401,40 +388,10 @@ PANDAJ2534DLL_API long PTAPI PassThruIoctl(unsigned long ChannelID, unsigned lon
if (inconfig == NULL) if (inconfig == NULL)
return ret_code(ERR_NULL_PARAMETER); return ret_code(ERR_NULL_PARAMETER);
for (unsigned int i = 0; i < inconfig->NumOfParams; i++) { for (unsigned int i = 0; i < inconfig->NumOfParams; i++) {
switch (inconfig->ConfigPtr[i].Parameter) { try {
case DATA_RATE: // 5-500000 get_channel(ChannelID)->processIOCTLSetConfig(inconfig->ConfigPtr[i].Parameter, inconfig->ConfigPtr[i].Value);
return ret_code(get_channel(ChannelID)->setBaud(inconfig->ConfigPtr[i].Value)); } catch (int e) {
case LOOPBACK: // 0 (OFF), 1 (ON) [0] return ret_code(e);
get_channel(ChannelID)->loopback = (inconfig->ConfigPtr[i].Value != 0);
break;
case NODE_ADDRESS: // J1850PWM Related (Not supported by panda). HDS requires these to 'work'.
case NETWORK_LINE:
case P1_MIN: // A bunch of stuff relating to ISO9141 and ISO14230 that the panda
case P1_MAX: // currently doesn't support. Don't let HDS know we can't use these.
case P2_MIN:
case P2_MAX:
case P3_MIN:
case P3_MAX:
case P4_MIN:
case P4_MAX:
case W0:
case W1:
case W2:
case W3:
case W4:
case W5:
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:
case T4_MAX:
case T5_MAX:
break; // Just smile and nod.
default:
printf("Got unknown SET code %X\n", inconfig->ConfigPtr[i].Parameter);
} }
} }
break; break;