J2534_WIN: Periodic message support and tests.

master
Jessy Diamond Exum 2017-10-15 17:35:33 -07:00
parent 3683bbfea8
commit c41d8230d7
24 changed files with 509 additions and 89 deletions

View File

@ -54,6 +54,23 @@ void check_panda_can_msg(panda::PANDA_CAN_MSG& msgin, uint8_t bus, unsigned long
Assert::AreEqual<std::string>(dat, std::string((char*)msgin.dat, msgin.len), _T("Wrong msg payload"), pLineInfo);
}
unsigned long J2534_start_periodic_msg_checked(unsigned long chanid, unsigned long ProtocolID, unsigned long TxFlags, unsigned long DataSize,
unsigned long ExtraDataIndex, const char * Data, unsigned long TimeInterval, const __LineInfo * pLineInfo) {
PASSTHRU_MSG msg = { ProtocolID, 0, TxFlags, 0, DataSize, ExtraDataIndex };
memcpy_s(msg.Data, 4128, Data, DataSize);
unsigned long msgID;
Assert::AreEqual<long>(STATUS_NOERROR, J2534_start_periodic_msg(chanid, ProtocolID, TxFlags, DataSize,
ExtraDataIndex, Data, TimeInterval, &msgID, pLineInfo), _T("Failed to start Periodic Message."), pLineInfo);
return msgID;
}
unsigned long J2534_start_periodic_msg(unsigned long chanid, unsigned long ProtocolID, unsigned long TxFlags, unsigned long DataSize,
unsigned long ExtraDataIndex, const char * Data, unsigned long TimeInterval, unsigned long* msgID, const __LineInfo * pLineInfo) {
PASSTHRU_MSG msg = { ProtocolID, 0, TxFlags, 0, DataSize, ExtraDataIndex };
memcpy_s(msg.Data, 4128, Data, DataSize);
return PassThruStartPeriodicMsg(chanid, &msg, msgID, TimeInterval);
}
void J2534_send_msg_checked(unsigned long chanid, unsigned long ProtocolID, unsigned long RxStatus, unsigned long TxFlags,
unsigned long Timestamp, unsigned long DataSize, unsigned long ExtraDataIndex, const char* Data, const __LineInfo* pLineInfo) {

View File

@ -12,6 +12,12 @@ extern std::vector<panda::PANDA_CAN_MSG> panda_recv_loop(std::unique_ptr<panda::
extern void check_panda_can_msg(panda::PANDA_CAN_MSG& msgin, uint8_t bus, unsigned long addr, bool addr_29b,
bool is_receipt, std::string dat, const __LineInfo* pLineInfo = NULL);
extern unsigned long J2534_start_periodic_msg_checked(unsigned long chanid, unsigned long ProtocolID, unsigned long TxFlags, unsigned long DataSize,
unsigned long ExtraDataIndex, const char * Data, unsigned long TimeInterval, const __LineInfo * pLineInfo);
extern unsigned long J2534_start_periodic_msg(unsigned long chanid, unsigned long ProtocolID, unsigned long TxFlags, unsigned long DataSize,
unsigned long ExtraDataIndex, const char* Data, unsigned long TimeInterval, unsigned long* msgID, const __LineInfo* pLineInfo = NULL);
extern void J2534_send_msg_checked(unsigned long chanid, unsigned long ProtocolID, unsigned long RxStatus, unsigned long TxFlags,
unsigned long Timestamp, unsigned long DataSize, unsigned long ExtraDataIndex, const char* Data, const __LineInfo* pLineInfo = NULL);
@ -23,10 +29,10 @@ extern std::vector<PASSTHRU_MSG> j2534_recv_loop(unsigned int chanid, unsigned i
extern void check_J2534_can_msg(PASSTHRU_MSG& msgin, unsigned long ProtocolID, unsigned long RxStatus, unsigned long TxFlags,
unsigned long DataSize, unsigned long ExtraDataIndex, const char* Data, const __LineInfo* pLineInfo = NULL);
unsigned long J2534_set_PASS_filter(unsigned long chanid, unsigned long ProtocolID, unsigned long tx,
extern unsigned long J2534_set_PASS_filter(unsigned long chanid, unsigned long ProtocolID, unsigned long tx,
unsigned long len, char* mask, char* pattern, const __LineInfo* pLineInfo = NULL);
unsigned long J2534_set_BLOCK_filter(unsigned long chanid, unsigned long ProtocolID, unsigned long tx,
extern unsigned long J2534_set_BLOCK_filter(unsigned long chanid, unsigned long ProtocolID, unsigned long tx,
unsigned long len, char* mask, char* pattern, const __LineInfo* pLineInfo = NULL);
extern unsigned long J2534_set_flowctrl_filter(unsigned long chanid, unsigned long tx,

View File

@ -4,7 +4,7 @@
Timer::Timer()
{
start = std::chrono::time_point_cast<std::chrono::milliseconds>(clock::now());
reset();
}
// gets the time elapsed from construction.
@ -14,4 +14,8 @@ unsigned long long /*milliseconds*/ Timer::getTimePassed(){
// return the difference of the times
return (end - start).count();
}
void Timer::reset() {
start = std::chrono::time_point_cast<std::chrono::milliseconds>(clock::now());
}

View File

@ -13,6 +13,8 @@ public:
// gets the time elapsed from construction.
unsigned long long /*milliseconds*/ getTimePassed();
void reset();
private:
time_point_type start;
};

View File

@ -293,6 +293,157 @@ namespace pandaJ2534DLLTest
check_panda_can_msg(msg_recv[0], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
}
TEST_METHOD(J2534_CAN_PeriodicMessageStartStop)
{
auto chanid = J2534_open_and_connect("", CAN, 0, 500000, LINE_INFO());
auto p = getPanda(500);
auto msgid = J2534_start_periodic_msg_checked(chanid, CAN, 0, 6, 0, "\x0\x0\x3\xAB""HI", 100, LINE_INFO());
std::vector<panda::PANDA_CAN_MSG> msg_recv = panda_recv_loop(p, 3, 250);
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid), _T("Failed to delete filter."), LINE_INFO());
check_panda_can_msg(msg_recv[0], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
check_panda_can_msg(msg_recv[1], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
check_panda_can_msg(msg_recv[2], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
auto timediff_1_0 = msg_recv[1].recv_time - msg_recv[0].recv_time;
auto timediff_2_1 = msg_recv[2].recv_time - msg_recv[1].recv_time;
std::ostringstream stringStream1;
stringStream1 << "times1: " << timediff_1_0 << ", " << timediff_2_1 << std::endl;
Logger::WriteMessage(stringStream1.str().c_str());
Assert::IsTrue(timediff_1_0 > 90000);
Assert::IsTrue(timediff_1_0 < 110000);
Assert::IsTrue(timediff_2_1 > 90000);
Assert::IsTrue(timediff_2_1 < 110000);
msg_recv = panda_recv_loop(p, 0, 300);
}
TEST_METHOD(J2534_CAN_PeriodicMessageMultipleStartStop)
{
auto chanid = J2534_open_and_connect("", CAN, 0, 500000, LINE_INFO());
auto p = getPanda(500);
auto msgid0 = J2534_start_periodic_msg_checked(chanid, CAN, 0, 6, 0, "\x0\x0\x3\xAB""HI", 100, LINE_INFO());
auto msgid1 = J2534_start_periodic_msg_checked(chanid, CAN, 0, 6, 0, "\x0\x0\x1\x23""YO", 80, LINE_INFO());
std::vector<panda::PANDA_CAN_MSG> msg_recv = panda_recv_loop(p, 9, 370);
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid0), _T("Failed to delete filter."), LINE_INFO());
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid1), _T("Failed to delete filter."), LINE_INFO());
//time diagram. 10 ms per character. * is send event. : is termination of periodic messages.
//*---------*---------*---------*-----:----* HI
//*-------*-------*-------*-------*---:----* YO
check_panda_can_msg(msg_recv[0], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
check_panda_can_msg(msg_recv[1], 0, 0x123, FALSE, FALSE, "YO", LINE_INFO());
check_panda_can_msg(msg_recv[2], 0, 0x123, FALSE, FALSE, "YO", LINE_INFO());
check_panda_can_msg(msg_recv[3], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
check_panda_can_msg(msg_recv[4], 0, 0x123, FALSE, FALSE, "YO", LINE_INFO());
check_panda_can_msg(msg_recv[5], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
check_panda_can_msg(msg_recv[6], 0, 0x123, FALSE, FALSE, "YO", LINE_INFO());
check_panda_can_msg(msg_recv[7], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
check_panda_can_msg(msg_recv[8], 0, 0x123, FALSE, FALSE, "YO", LINE_INFO());
auto timediff_HI_3_0 = msg_recv[3].recv_time - msg_recv[0].recv_time;
auto timediff_HI_5_3 = msg_recv[5].recv_time - msg_recv[3].recv_time;
auto timediff_HI_7_5 = msg_recv[7].recv_time - msg_recv[5].recv_time;
auto timediff_YO_2_1 = msg_recv[2].recv_time - msg_recv[1].recv_time;
auto timediff_YO_4_2 = msg_recv[4].recv_time - msg_recv[2].recv_time;
auto timediff_YO_6_4 = msg_recv[6].recv_time - msg_recv[4].recv_time;
auto timediff_YO_8_6 = msg_recv[8].recv_time - msg_recv[6].recv_time;
std::ostringstream stringStreamHi;
stringStreamHi << "HiTimes: " << timediff_HI_3_0 << ", " << timediff_HI_5_3 << ", " << timediff_HI_7_5 << std::endl;
Logger::WriteMessage(stringStreamHi.str().c_str());
std::ostringstream stringStreamYo;
stringStreamYo << "HiTimes: " << timediff_YO_2_1 << ", " << timediff_YO_4_2 << ", " << timediff_YO_6_4 << ", " << timediff_YO_8_6 << std::endl;
Logger::WriteMessage(stringStreamYo.str().c_str());
Assert::IsTrue(timediff_HI_3_0 > 90000);
Assert::IsTrue(timediff_HI_3_0 < 110000);
Assert::IsTrue(timediff_HI_5_3 > 90000);
Assert::IsTrue(timediff_HI_5_3 < 110000);
Assert::IsTrue(timediff_HI_7_5 > 90000);
Assert::IsTrue(timediff_HI_7_5 < 110000);
Assert::IsTrue(timediff_YO_2_1 > 80000-10000);
Assert::IsTrue(timediff_YO_2_1 < 80000+1000);
Assert::IsTrue(timediff_YO_4_2 > 80000 - 10000);
Assert::IsTrue(timediff_YO_4_2 < 80000 + 10000);
Assert::IsTrue(timediff_YO_6_4 > 80000 - 10000);
Assert::IsTrue(timediff_YO_6_4 < 80000 + 10000);
Assert::IsTrue(timediff_YO_8_6 > 80000 - 10000);
Assert::IsTrue(timediff_YO_8_6 < 80000 + 10000);
msg_recv = panda_recv_loop(p, 0, 300);
}
TEST_METHOD(J2534_CAN_PeriodicMessageStartStop_Loopback)
{
auto chanid = J2534_open_and_connect("", CAN, 0, 500000, LINE_INFO());
write_ioctl(chanid, LOOPBACK, TRUE, LINE_INFO()); // ENABLE J2534 ECHO/LOOPBACK
auto p = getPanda(500);
auto msgid = J2534_start_periodic_msg_checked(chanid, CAN, 0, 6, 0, "\x0\x0\x3\xAB""HI", 100, LINE_INFO());
std::vector<panda::PANDA_CAN_MSG> msg_recv = panda_recv_loop(p, 3, 250);
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid), _T("Failed to delete filter."), LINE_INFO());
check_panda_can_msg(msg_recv[0], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
check_panda_can_msg(msg_recv[1], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
check_panda_can_msg(msg_recv[2], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
auto j2534_msg_recv = j2534_recv_loop(chanid, 3);
check_J2534_can_msg(j2534_msg_recv[0], CAN, TX_MSG_TYPE, 0, 6, 0, "\x0\x0\x3\xAB""HI", LINE_INFO());
check_J2534_can_msg(j2534_msg_recv[1], CAN, TX_MSG_TYPE, 0, 6, 0, "\x0\x0\x3\xAB""HI", LINE_INFO());
check_J2534_can_msg(j2534_msg_recv[2], CAN, TX_MSG_TYPE, 0, 6, 0, "\x0\x0\x3\xAB""HI", LINE_INFO());
auto timediff_1_0 = j2534_msg_recv[1].Timestamp - j2534_msg_recv[0].Timestamp;
auto timediff_2_1 = j2534_msg_recv[2].Timestamp - j2534_msg_recv[1].Timestamp;
std::ostringstream stringStream1;
stringStream1 << "times1: " << timediff_1_0 << ", " << timediff_2_1 << std::endl;
Logger::WriteMessage(stringStream1.str().c_str());
Assert::IsTrue(timediff_1_0 > 90000);
Assert::IsTrue(timediff_1_0 < 110000);
Assert::IsTrue(timediff_2_1 > 90000);
Assert::IsTrue(timediff_2_1 < 110000);
msg_recv = panda_recv_loop(p, 0, 300);
}
TEST_METHOD(J2534_CAN_PeriodicMessageWithTx)
{
auto chanid = J2534_open_and_connect("", CAN, 0, 500000, LINE_INFO());
auto p = getPanda(500);
auto msgid = J2534_start_periodic_msg_checked(chanid, CAN, 0, 6, 0, "\x0\x0\x3\xAB""HI", 100, LINE_INFO());
J2534_send_msg(chanid, CAN, 0, 0, 0, 7, 0, "\x0\x0\x3\xAB""LOL");
std::vector<panda::PANDA_CAN_MSG> msg_recv = panda_recv_loop(p, 4, 250);
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid), _T("Failed to delete filter."), LINE_INFO());
check_panda_can_msg(msg_recv[0], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
check_panda_can_msg(msg_recv[1], 0, 0x3AB, FALSE, FALSE, "LOL", LINE_INFO());//Staggered write inbetween multiple scheduled TXs
check_panda_can_msg(msg_recv[2], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
check_panda_can_msg(msg_recv[3], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
auto timediff_2_0 = msg_recv[2].recv_time - msg_recv[0].recv_time;
auto timediff_3_2 = msg_recv[3].recv_time - msg_recv[2].recv_time;
std::ostringstream stringStream1;
stringStream1 << "times1: " << timediff_2_0 << ", " << timediff_3_2 << std::endl;
Logger::WriteMessage(stringStream1.str().c_str());
Assert::IsTrue(timediff_2_0 > 90000);
Assert::IsTrue(timediff_2_0 < 110000);
Assert::IsTrue(timediff_3_2 > 90000);
Assert::IsTrue(timediff_3_2 < 110000);
msg_recv = panda_recv_loop(p, 0, 300);
}
TEST_METHOD(J2534_CAN_BaudInvalid)
{
unsigned long chanid;
@ -686,17 +837,17 @@ namespace pandaJ2534DLLTest
auto timediff_5_4 = panda_msg_recv[5].recv_time - panda_msg_recv[4].recv_time;
auto timediff_6_5 = panda_msg_recv[6].recv_time - panda_msg_recv[5].recv_time;
std::ostringstream stringStream1;
stringStream1 << "times1: " << timediff_1_0 << ", " << timediff_2_1 << ", " << timediff_3_2 <<
", " << timediff_4_3 << ", " << timediff_5_4 << ", " << timediff_6_5 << std::endl;
Logger::WriteMessage(stringStream1.str().c_str());
Assert::IsTrue(timediff_1_0 > 10000);
Assert::IsTrue(timediff_2_1 > 10000);
Assert::IsTrue(timediff_3_2 > 10000);
Assert::IsTrue(timediff_4_3 > 10000);
Assert::IsTrue(timediff_5_4 > 10000);
Assert::IsTrue(timediff_6_5 > 10000);
std::ostringstream stringStream1;
stringStream1 << "times1: " << timediff_1_0 << ", " << timediff_2_1 << ", " << timediff_3_2 <<
", " << timediff_4_3 << ", " << timediff_5_4 << ", " << timediff_6_5 << std::endl;
Logger::WriteMessage(stringStream1.str().c_str());
}
//Check that tx works for messages with more than 16 frames. 29 bit. Good Filter. NoPadding. STD address. Large multiframe message.
@ -819,7 +970,7 @@ namespace pandaJ2534DLLTest
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()); //First Frame. Not replying so it needs to time out.
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, 6, LINE_INFO(), 3000);//Start a conversation... but slow. FC timeout is 250 ms.
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x21""DDEEFFG", LINE_INFO());//Check this convo doesn't trigger that timeout.
@ -834,6 +985,88 @@ namespace pandaJ2534DLLTest
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 MF tx can be sent along side of a periodic message. 29 bit. Good Filter. NoPadding. STD address. Long STmin, checks that MF tx and periodic TX don't break each other.
TEST_METHOD(J2534_ISO15765_SuccessTx_29b_Filter_NoPad_STD_SLOWMF_WithPeriodicMsg)
{
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);
//Timing diagram of this test.
//* is a periodic msg transfer; F is first frame, L is Flow control, C is Consecutive Frame.
// *~~~~~~~*~~~~~~~*~~~~~~~* (The alignment here is unimportant. The exact order is not checked.
//F C----C----C----C----C----C (100 ms between Cs)
// L
auto msgid = J2534_start_periodic_msg_checked(chanid, ISO15765, CAN_29BIT_ID, 6, 0, "\x18\xda\xef\xf1""HI", 130, LINE_INFO());
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, 2);
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x02""HI", LINE_INFO());
check_panda_can_msg(panda_msg_recv[1], 0, 0x18DAEFF1, TRUE, FALSE, "\x10\x30""AABBCC", LINE_INFO());
Assert::IsTrue(p->can_send(0x18DAF1EF, TRUE, (const uint8_t*)"\x30\x06\x64", 3, panda::PANDA_CAN1), _T("Panda send says it failed."), LINE_INFO());
Timer t_permsg = Timer();
Timer t_MFmsg = Timer();
unsigned int MFframesReceived = 0;
unsigned int PeriodicMsgReceived = 0;
std::array<std::string, 6> const mfMsgExpectedParts{ "\x21""DDEEFFG", "\x22""GHHIIJJ", "\x23""KKLLMMN", "\x24""NOOPPQQ", "\x25""RRSSTTU", "\x26""UVVWWXX" };
while (TRUE) {
std::vector<panda::PANDA_CAN_MSG>msg_recv = p->can_recv();
for (auto msg : msg_recv) {
if (msg.is_receipt) continue;
if ((msg.dat[0] & 0xf0) == 0x20) {
Assert::AreEqual<std::string>(mfMsgExpectedParts[MFframesReceived], std::string((const char*)msg.dat, msg.len), _T("Got wrong part of MF msg."), LINE_INFO());
MFframesReceived++;
t_MFmsg.reset();
} else if (std::string((const char*)msg.dat, msg.len) == "\x02HI") {
PeriodicMsgReceived++;
t_permsg.reset();
} else {
Assert::IsTrue(FALSE, _T("Got impossible message. Something is very wrong. Check other tests."), LINE_INFO());
}
}
if (MFframesReceived >= 6) break;
Assert::IsTrue(300 > t_permsg.getTimePassed(), _T("Timed out waiting for periodic msessage frame."), LINE_INFO());
Assert::IsTrue(300 > t_MFmsg.getTimePassed(), _T("Timed out waiting for multiframe msessage frame."), LINE_INFO());
if (msg_recv.size() == 0)
Sleep(10);
}
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid), _T("Failed to delete filter."), LINE_INFO());
Assert::IsTrue(PeriodicMsgReceived > 3, _T("Did not receive enough periodic messages. Likely canceled or delayed."), LINE_INFO());
std::ostringstream stringStream;
stringStream << "PeriodicMsgReceived = " << PeriodicMsgReceived << std::endl;
Logger::WriteMessage(stringStream.str().c_str());
unsigned int periodicTxIndicationCount = 0;
unsigned int TxIndicationCount = 0;
auto j2534_msg_recv = j2534_recv_loop(chanid, 2 + (PeriodicMsgReceived * 2));
for (int i = 0; i < PeriodicMsgReceived + 1; i++) {
check_J2534_can_msg(j2534_msg_recv[(i * 2) + 0], ISO15765, CAN_29BIT_ID | TX_INDICATION, 0, 4, 0, "\x18\xda\xef\xf1", LINE_INFO());
switch (j2534_msg_recv[(i * 2) + 1].DataSize) {
case 6:
check_J2534_can_msg(j2534_msg_recv[(i * 2) + 1], ISO15765, CAN_29BIT_ID | TX_MSG_TYPE, 0, 4 + 2, 0, "\x18\xda\xef\xf1""HI", LINE_INFO());
break;
case 4 + 48:
check_J2534_can_msg(j2534_msg_recv[(i * 2) + 1], ISO15765, CAN_29BIT_ID | TX_MSG_TYPE, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
break;
default:
Assert::IsTrue(FALSE, _T("Got unexpected data!"), LINE_INFO());
}
}
Assert::AreNotEqual<unsigned int>(PeriodicMsgReceived, periodicTxIndicationCount, _T("Wrong number of periodic msgs reported by passthru device."), LINE_INFO());
Assert::AreNotEqual<unsigned int>(1, TxIndicationCount, _T("Wrong number of TX msgs reported by passthru device."), LINE_INFO());
}
///////////////////// Tests checking things break or recover during send/receive /////////////////////
//Check rx FAILS when frame is dropped. 29 bit. Good Filter. NoPadding. STD address. Multi Frame.

View File

@ -10,3 +10,5 @@
// Headers for CppUnitTest
#include "CppUnitTest.h"
#include <iomanip> //Used for formatting in TestHelpers.cpp
#include <string>
#include <array>

View File

@ -23,6 +23,10 @@ public:
expire = std::chrono::steady_clock::now();
}
void scheduleDelay() {
expire += this->delay;
}
void scheduleImmediateDelay() {
expire = std::chrono::steady_clock::now() + this->delay;
}

View File

@ -9,6 +9,12 @@ J2534Connection::J2534Connection(
unsigned long BaudRate
) : panda_dev(panda_dev), ProtocolID(ProtocolID), Flags(Flags), BaudRate(BaudRate), port(0) { }
unsigned long J2534Connection::validateTxMsg(PASSTHRU_MSG* msg) {
if (msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen())
return ERR_INVALID_MSG;
return STATUS_NOERROR;
}
long J2534Connection::PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) {
//Timeout of 0 means return immediately. Non zero means WAIT for that time then return. Dafuk.
long err_code = STATUS_NOERROR;
@ -22,17 +28,17 @@ long J2534Connection::PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMs
}
//Synchronized won't work where we have to break out of a loop
message_access_lock.lock();
if (this->messages.empty()) {
message_access_lock.unlock();
messageRxBuff_mutex.lock();
if (this->messageRxBuff.empty()) {
messageRxBuff_mutex.unlock();
if (Timeout == 0)
break;
continue;
}
auto msg_in = this->messages.front();
this->messages.pop();
message_access_lock.unlock();
auto msg_in = this->messageRxBuff.front();
this->messageRxBuff.pop();
messageRxBuff_mutex.unlock();
PASSTHRU_MSG *msg_out = &pMsg[msgnum++];
msg_out->ProtocolID = this->ProtocolID;
@ -50,9 +56,60 @@ long J2534Connection::PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMs
*pNumMsgs = msgnum;
return err_code;
}
long J2534Connection::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) { return STATUS_NOERROR; }
long J2534Connection::PassThruStartPeriodicMsg(PASSTHRU_MSG *pMsg, unsigned long *pMsgID, unsigned long TimeInterval) { return STATUS_NOERROR; }
long J2534Connection::PassThruStopPeriodicMsg(unsigned long MsgID) { return STATUS_NOERROR; }
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++) {
PASSTHRU_MSG* msg = &pMsg[msgnum];
if (msg->ProtocolID != this->ProtocolID) {
*pNumMsgs = msgnum;
return ERR_MSG_PROTOCOL_ID;
}
auto retcode = this->validateTxMsg(msg);
if (retcode != STATUS_NOERROR) {
*pNumMsgs = msgnum;
return retcode;
}
auto msgtx = this->parseMessageTx(*pMsg);
if (msgtx != nullptr) //Nullptr is supported for unimplemented connection types.
this->schedultMsgTx(std::dynamic_pointer_cast<Action>(msgtx));
}
return STATUS_NOERROR;
}
//The docs say that a device has to support 10 periodic messages, though more is ok.
//It is easier to store them on the connection, so 10 per connection it is.
long J2534Connection::PassThruStartPeriodicMsg(PASSTHRU_MSG *pMsg, unsigned long *pMsgID, unsigned long TimeInterval) {
if (pMsg->DataSize < getMinMsgLen() || pMsg->DataSize > getMaxMsgSingleFrameLen()) return ERR_INVALID_MSG;
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++) {
if (periodicMessages[i] != nullptr) continue;
*pMsgID = i;
auto msgtx = this->parseMessageTx(*pMsg);
if (msgtx != nullptr) {
periodicMessages[i] = std::make_shared<MessagePeriodic>(std::chrono::microseconds(TimeInterval*1000), msgtx);
periodicMessages[i]->scheduleImmediate();
if (auto panda_dev = this->getPandaDev()) {
panda_dev->insertActionIntoTaskList(periodicMessages[i]);
}
}
return STATUS_NOERROR;
}
return ERR_EXCEEDED_LIMIT;
}
long J2534Connection::PassThruStopPeriodicMsg(unsigned long MsgID) {
if (MsgID >= this->periodicMessages.size() || this->periodicMessages[MsgID] == nullptr)
return ERR_INVALID_MSG_ID;
this->periodicMessages[MsgID]->cancel();
this->periodicMessages[MsgID] = nullptr;
return STATUS_NOERROR;
}
long J2534Connection::PassThruStartMsgFilter(unsigned long FilterType, PASSTHRU_MSG *pMaskMsg, PASSTHRU_MSG *pPatternMsg,
PASSTHRU_MSG *pFlowControlMsg, unsigned long *pFilterID) {
@ -93,7 +150,9 @@ long J2534Connection::init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput) { return
long J2534Connection::initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput) { return STATUS_NOERROR; }
long J2534Connection::clearTXBuff() { return STATUS_NOERROR; }
long J2534Connection::clearRXBuff() {
this->messages = {};
synchronized(messageRxBuff_mutex) {
this->messageRxBuff = {};
}
return STATUS_NOERROR;
}
long J2534Connection::clearPeriodicMsgs() { return STATUS_NOERROR; }
@ -124,13 +183,6 @@ void J2534Connection::rescheduleExistingTxMsgs() {
}
}
void J2534Connection::processMessageReceipt(const J2534Frame& msg) {
//TX_MSG_TYPE should be set in RxStatus
if (!check_bmask(msg.RxStatus, TX_MSG_TYPE)) return;
if (this->loopback)
addMsgToRxQueue(msg);
}
//Works well as long as the protocol doesn't support flow control.
void J2534Connection::processMessage(const J2534Frame& msg) {
FILTER_RESULT filter_res = FILTER_RESULT_NEUTRAL;

View File

@ -5,6 +5,7 @@
#include "J2534Frame.h"
#include "PandaJ2534Device.h"
#include "J2534MessageFilter.h"
#include "MessagePeriodic.h"
class J2534Frame;
class Action;
@ -25,7 +26,7 @@ public:
);
virtual ~J2534Connection() {};
virtual long PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
virtual long PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
long PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
virtual long PassThruStartPeriodicMsg(PASSTHRU_MSG *pMsg, unsigned long *pMsgID, unsigned long TimeInterval);
virtual long PassThruStopPeriodicMsg(unsigned long MsgID);
@ -35,6 +36,10 @@ public:
virtual long PassThruStopMsgFilter(unsigned long FilterID);
virtual long PassThruIoctl(unsigned long IoctlID, void *pInput, void *pOutput);
virtual unsigned long validateTxMsg(PASSTHRU_MSG* msg);
virtual std::shared_ptr<MessageTx> parseMessageTx(PASSTHRU_MSG& msg) { return nullptr; };
long init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput);
long initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput);
long clearTXBuff();
@ -59,7 +64,6 @@ public:
return this->port;
}
virtual void processMessageReceipt(const J2534Frame& msg);
virtual void processMessage(const J2534Frame& msg);
virtual unsigned long getMinMsgLen() {
@ -70,6 +74,10 @@ public:
return 4128;
}
virtual unsigned long getMaxMsgSingleFrameLen() {
return 12;
}
void schedultMsgTx(std::shared_ptr<Action> msgout);
void rescheduleExistingTxMsgs();
@ -81,8 +89,8 @@ public:
}
void addMsgToRxQueue(const J2534Frame& frame) {
synchronized(message_access_lock) {
messages.push(frame);
synchronized(messageRxBuff_mutex) {
messageRxBuff.push(frame);
}
}
@ -96,12 +104,14 @@ protected:
std::weak_ptr<PandaJ2534Device> panda_dev;
std::queue<J2534Frame> messages;
Mutex messageRxBuff_mutex;
std::queue<J2534Frame> messageRxBuff;
std::array<std::shared_ptr<J2534MessageFilter>, 10> filters;
std::queue<std::shared_ptr<Action>> txbuff;
std::array<std::shared_ptr<MessagePeriodic>, 10> periodicMessages;
private:
Mutex message_access_lock;
Mutex staged_writes_lock;
};

View File

@ -17,22 +17,13 @@ J2534Connection_CAN::J2534Connection_CAN(
panda_dev->panda->set_can_speed_cbps(panda::PANDA_CAN1, BaudRate/100);
};
long J2534Connection_CAN::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++) {
PASSTHRU_MSG* msg = &pMsg[msgnum];
if (msg->ProtocolID != this->ProtocolID) {
*pNumMsgs = msgnum;
return ERR_MSG_PROTOCOL_ID;
}
if (msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen() ||
(val_is_29bit(msg->TxFlags) != this->_is_29bit() && !check_bmask(this->Flags, CAN_ID_BOTH))) {
*pNumMsgs = msgnum;
return ERR_INVALID_MSG;
}
auto msgtx = std::make_shared<MessageTx_CAN>(shared_from_this(), *msg);
this->schedultMsgTx(std::dynamic_pointer_cast<Action>(msgtx));
}
unsigned long J2534Connection_CAN::validateTxMsg(PASSTHRU_MSG* msg) {
if ((msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen() ||
(val_is_29bit(msg->TxFlags) != this->_is_29bit() && !check_bmask(this->Flags, CAN_ID_BOTH))))
return ERR_INVALID_MSG;
return STATUS_NOERROR;
}
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));
}

View File

@ -14,7 +14,9 @@ public:
unsigned long BaudRate
);
virtual long PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
virtual unsigned long validateTxMsg(PASSTHRU_MSG* msg);
virtual std::shared_ptr<MessageTx> parseMessageTx(PASSTHRU_MSG& pMsg);
virtual unsigned long getMinMsgLen() {
return 4;
@ -24,6 +26,10 @@ public:
return 12;
}
virtual unsigned long getMaxMsgSingleFrameLen() {
return 12;
}
virtual bool isProtoCan() {
return TRUE;
}

View File

@ -18,35 +18,25 @@ J2534Connection_ISO15765::J2534Connection_ISO15765(
panda_dev->panda->set_can_speed_cbps(panda::PANDA_CAN1, (uint16_t)(BaudRate / 100));
}
long J2534Connection_ISO15765::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) {
for (unsigned int msgnum = 0; msgnum < *pNumMsgs; msgnum++) {
PASSTHRU_MSG* msg = &pMsg[msgnum];
unsigned long J2534Connection_ISO15765::validateTxMsg(PASSTHRU_MSG* msg) {
if ((msg->DataSize < this->getMinMsgLen() + (msg_is_extaddr(msg) ? 1 : 0) ||
msg->DataSize > this->getMaxMsgLen() + (msg_is_extaddr(msg) ? 1 : 0) ||
(val_is_29bit(msg->TxFlags) != this->_is_29bit() && !check_bmask(this->Flags, CAN_ID_BOTH))))
return ERR_INVALID_MSG;
if (msg->ProtocolID != this->ProtocolID) {
*pNumMsgs = msgnum;
return ERR_MSG_PROTOCOL_ID;
}
if (msg->DataSize < this->getMinMsgLen() + (msg_is_extaddr(msg) ? 1 : 0) ||
msg->DataSize > this->getMaxMsgLen() + (msg_is_extaddr(msg) ? 1 : 0) ||
(val_is_29bit(msg->TxFlags) != this->_is_29bit() && !check_bmask(this->Flags, CAN_ID_BOTH))) {
*pNumMsgs = msgnum;
return ERR_INVALID_MSG;
}
int fid = get_matching_out_fc_filter_id(std::string((const char*)msg->Data, msg->DataSize), msg->TxFlags, 0xFFFFFFFF);
if (msg->DataSize > getMaxMsgSingleFrameLen() && fid == -1) return ERR_NO_FLOW_CONTROL; //11 bytes (4 for CANid, 7 payload) is max length of input frame.
int fid = get_matching_out_fc_filter_id(std::string((const char*)msg->Data, msg->DataSize), msg->TxFlags, 0xFFFFFFFF);
if (msg->DataSize > 11 && fid == -1) return ERR_NO_FLOW_CONTROL; //11 bytes (4 for CANid, 7 payload) is max length of input frame.
auto msgtx = std::make_shared<MessageTx_ISO15765>( shared_from_this(), *msg, (fid == -1) ? nullptr : this->filters[fid] );
this->schedultMsgTx(std::dynamic_pointer_cast<Action>(msgtx));
}
return STATUS_NOERROR;
}
void J2534Connection_ISO15765::processMessageReceipt(const J2534Frame& msg) {
if (msg.ProtocolID != CAN) return;
std::shared_ptr<MessageTx> J2534Connection_ISO15765::parseMessageTx(PASSTHRU_MSG& msg) {
int fid = get_matching_out_fc_filter_id(std::string((const char*)msg.Data, msg.DataSize), msg.TxFlags, 0xFFFFFFFF);
if (msg.DataSize > getMaxMsgSingleFrameLen() && fid == -1) 1;
//TX_MSG_TYPE should be set in RxStatus
if (!check_bmask(msg.RxStatus, TX_MSG_TYPE)) return;
return std::dynamic_pointer_cast<MessageTx>(
std::make_shared<MessageTx_ISO15765>(shared_from_this(), msg, (fid == -1) ? nullptr : this->filters[fid])
);
}
//https://happilyembedded.wordpress.com/2016/02/15/can-multiple-frame-transmission/
@ -63,6 +53,8 @@ void J2534Connection_ISO15765::processMessage(const J2534Frame& msg) {
switch (msg_get_type(msg, addrlen)) {
case FRAME_FLOWCTRL:
{
if (this->txbuff.size() == 0)
return;
if (msg.Data.size() < addrlen + 3) return;
uint8_t flow_status = msg.Data[addrlen] & 0x0F;
uint8_t block_size = msg.Data[addrlen + 1];
@ -79,6 +71,7 @@ void J2534Connection_ISO15765::processMessage(const J2534Frame& msg) {
} else {
break;
}
txConvo->scheduleImmediate();
this->rescheduleExistingTxMsgs();
break;
}

View File

@ -21,15 +21,16 @@ public:
unsigned long BaudRate
);
virtual long PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
virtual long PassThruStartMsgFilter(unsigned long FilterType, PASSTHRU_MSG * pMaskMsg, PASSTHRU_MSG * pPatternMsg, PASSTHRU_MSG * pFlowControlMsg, unsigned long * pFilterID);
int get_matching_out_fc_filter_id(const std::string & msgdata, unsigned long flags, unsigned long flagmask);
int get_matching_in_fc_filter_id(const J2534Frame& msg, unsigned long flagmask = CAN_29BIT_ID);
virtual void processMessageReceipt(const J2534Frame& msg);
virtual unsigned long validateTxMsg(PASSTHRU_MSG* msg);
virtual std::shared_ptr<MessageTx> parseMessageTx(PASSTHRU_MSG& msg);
virtual void processMessage(const J2534Frame& msg);
virtual unsigned long getMinMsgLen() {
@ -40,6 +41,10 @@ public:
return 4099;
};
virtual unsigned long getMaxMsgSingleFrameLen() {
return 11;
}
virtual bool _is_29bit() {
return (this->Flags & CAN_29BIT_ID) == CAN_29BIT_ID;
}

View File

@ -0,0 +1,30 @@
#include "stdafx.h"
#include "MessagePeriodic.h"
#include "J2534Connection.h"
MessagePeriodic::MessagePeriodic(
std::chrono::microseconds delay,
std::shared_ptr<MessageTx> msg
) : Action(msg->connection, delay), msg(msg), runyet(FALSE), active(TRUE) { };
void MessagePeriodic::execute() {
if (!this->active) return;
if (this->runyet) {
if (msg->isFinished()) {
msg->reset();
msg->execute();
}
} else {
this->runyet = TRUE;
msg->execute();
}
if (auto conn_sp = this->connection.lock()) {
if (auto panda_dev_sp = conn_sp->getPandaDev()) {
//Scheduling must be relative to now incase there was a long stall that
//would case it to be super far behind and try to catch up forever.
this->scheduleImmediateDelay();
panda_dev_sp->insertActionIntoTaskList(shared_from_this());
}
}
}

View File

@ -0,0 +1,27 @@
#pragma once
#include "Action.h"
#include "MessageTx.h"
class J2534Connection;
class MessagePeriodic : public Action, public std::enable_shared_from_this<Action>
{
public:
MessagePeriodic(
std::chrono::microseconds delay,
std::shared_ptr<MessageTx> msg
);
virtual void execute();
void cancel() {
this->active = FALSE;
}
protected:
std::shared_ptr<MessageTx> msg;
private:
BOOL runyet;
BOOL active;
};

View File

@ -18,6 +18,8 @@ public:
virtual BOOL txReady() = 0;
virtual void reset() = 0;
protected:
J2534Frame fullmsg;
};

View File

@ -2,8 +2,6 @@
#include "MessageTx_CAN.h"
#include "J2534Connection_CAN.h"
//class J2534Connection_CAN;
MessageTx_CAN::MessageTx_CAN(
std::shared_ptr<J2534Connection> connection_in,
PASSTHRU_MSG& to_send
@ -32,7 +30,15 @@ BOOL MessageTx_CAN::checkTxReceipt(J2534Frame frame) {
if (txReady()) return FALSE;
if (frame.Data == fullmsg.Data && ((this->fullmsg.TxFlags & CAN_29BIT_ID) == (frame.RxStatus & CAN_29BIT_ID))) {
txInFlight = FALSE;
if (auto conn_sp = std::static_pointer_cast<J2534Connection_CAN>(this->connection.lock()))
if (conn_sp->loopback)
conn_sp->addMsgToRxQueue(frame);
return TRUE;
}
return FALSE;
}
void MessageTx_CAN::reset() {
sentyet = FALSE;
txInFlight = FALSE;
}

View File

@ -25,6 +25,8 @@ public:
return !sentyet;
};
virtual void reset();
private:
BOOL sentyet;
BOOL txInFlight;

View File

@ -131,11 +131,21 @@ BOOL MessageTx_ISO15765::txReady() {
return block_size > 0 || sendAll || this->frames_sent == 0;
}
void MessageTx_ISO15765::reset() {
frames_sent = 0;
consumed_count = 0;
block_size = 0;
txInFlight = FALSE;
sendAll = FALSE;
numWaitFrames = 0;
didtimeout = FALSE;
}
void MessageTx_ISO15765::onTimeout() {
didtimeout = TRUE;
if (auto conn_sp = std::static_pointer_cast<J2534Connection_ISO15765>(this->connection.lock())) {
if (auto panda_dev_sp = conn_sp->getPandaDev()) {
panda_dev_sp->removeConnectionTopAction(conn_sp);
panda_dev_sp->removeConnectionTopAction(conn_sp, shared_from_this());
}
}
}

View File

@ -23,6 +23,8 @@ public:
virtual BOOL txReady();
virtual void reset();
virtual void onTimeout();
void MessageTx_ISO15765::flowControlContinue(uint8_t block_size, std::chrono::microseconds separation_time);

View File

@ -75,7 +75,7 @@ DWORD PandaJ2534Device::can_recv_thread() {
J2534Frame msg_out(msg_in);
if (msg_in.is_receipt) {
synchronized(activeTXs_mutex) {
synchronized(task_queue_mutex) {
if (txMsgsAwaitingEcho.size() > 0) {
auto msgtx = txMsgsAwaitingEcho.front();
if (auto conn = msgtx->connection.lock()) {
@ -89,8 +89,7 @@ DWORD PandaJ2534Device::can_recv_thread() {
txMsgsAwaitingEcho.pop(); //Remove the TX object and schedule record.
if (msgtx->isFinished()) {
conn->processMessageReceipt(msg_out); //Alert the connection a tx is done.
this->removeConnectionTopAction(conn);
this->removeConnectionTopAction(conn, msgtx);
} else {
if (msgtx->txReady()) { //Not finished, ready to send next frame.
msgtx->schedule(msg_in.recv_time_point, TRUE);
@ -135,7 +134,7 @@ DWORD PandaJ2534Device::msg_tx_thread() {
ResetEvent(this->flow_control_wakeup_event);
while (TRUE) {
synchronized(activeTXs_mutex) { //implemented with for loop. Consumes breaks.
synchronized(task_queue_mutex) { //implemented with for loop. Consumes breaks.
if (this->task_queue.size() == 0) {
sleepDuration = INFINITE;
goto break_flow_ctrl_loop;
@ -159,7 +158,7 @@ DWORD PandaJ2534Device::msg_tx_thread() {
}
void PandaJ2534Device::insertActionIntoTaskList(std::shared_ptr<Action> action) {
synchronized(activeTXs_mutex) {
synchronized(task_queue_mutex) {
auto iter = this->task_queue.begin();
for (; iter != this->task_queue.end(); iter++) {
if (action->expire < (*iter)->expire) break;
@ -191,11 +190,14 @@ void PandaJ2534Device::unstallConnectionTx(std::shared_ptr<J2534Connection> conn
if (ret.second == TRUE) return; //Conn already exists.
this->insertActionIntoTaskList(conn->txbuff.front());
}
SetEvent(flow_control_wakeup_event);
}
void PandaJ2534Device::removeConnectionTopAction(std::shared_ptr<J2534Connection> conn) {
synchronized(activeTXs_mutex) {
void PandaJ2534Device::removeConnectionTopAction(std::shared_ptr<J2534Connection> conn, std::shared_ptr<MessageTx> msg) {
synchronized(task_queue_mutex) {
if (conn->txbuff.size() == 0)
return;
if (conn->txbuff.front() != msg)
return;
conn->txbuff.pop(); //Remove the top TX message from the connection tx queue.
//Remove the connection from the active connection list if no more messages are scheduled with this connection.

View File

@ -37,7 +37,7 @@ public:
void unstallConnectionTx(std::shared_ptr<J2534Connection> conn);
void removeConnectionTopAction(std::shared_ptr<J2534Connection> conn);
void removeConnectionTopAction(std::shared_ptr<J2534Connection> conn, std::shared_ptr<MessageTx> msg);
std::queue<std::shared_ptr<MessageTx>> txMsgsAwaitingEcho;
@ -57,7 +57,7 @@ private:
}
DWORD msg_tx_thread();
std::list<std::shared_ptr<Action>> task_queue;
Mutex activeTXs_mutex;
Mutex task_queue_mutex;
std::queue<std::shared_ptr<J2534Connection>> ConnTxQueue;
std::set<std::shared_ptr<J2534Connection>> ConnTxSet;

View File

@ -90,6 +90,7 @@
<ClInclude Include="..\panda\panda.h" />
<ClInclude Include="constants_ISO15765.h" />
<ClInclude Include="dllmain.h" />
<ClInclude Include="MessagePeriodic.h" />
<ClInclude Include="MessageRx.h" />
<ClInclude Include="J2534Connection.h" />
<ClInclude Include="J2534Connection_CAN.h" />
@ -122,6 +123,7 @@
<ClCompile Include="J2534Connection_CAN.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_ISO15765.cpp" />
@ -141,6 +143,9 @@
<ItemGroup>
<ResourceCompile Include="pandaJ2534DLL.rc" />
</ItemGroup>
<ItemGroup>
<None Include="ClassDiagram.cd" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>

View File

@ -99,6 +99,9 @@
<ClInclude Include="MessageTx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="MessagePeriodic.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pandaJ2534DLL.cpp">
@ -137,10 +140,16 @@
<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>
</Project>