diff --git a/drivers/windows/pandaJ2534DLL Test/TestHelpers.cpp b/drivers/windows/pandaJ2534DLL Test/TestHelpers.cpp index c5f0f31..8d19e2f 100644 --- a/drivers/windows/pandaJ2534DLL Test/TestHelpers.cpp +++ b/drivers/windows/pandaJ2534DLL Test/TestHelpers.cpp @@ -54,6 +54,23 @@ void check_panda_can_msg(panda::PANDA_CAN_MSG& msgin, uint8_t bus, unsigned long Assert::AreEqual(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(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) { diff --git a/drivers/windows/pandaJ2534DLL Test/TestHelpers.h b/drivers/windows/pandaJ2534DLL Test/TestHelpers.h index 2c28632..bd89db8 100644 --- a/drivers/windows/pandaJ2534DLL Test/TestHelpers.h +++ b/drivers/windows/pandaJ2534DLL Test/TestHelpers.h @@ -12,6 +12,12 @@ extern std::vector panda_recv_loop(std::unique_ptr 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, diff --git a/drivers/windows/pandaJ2534DLL Test/Timer.cpp b/drivers/windows/pandaJ2534DLL Test/Timer.cpp index 2f20f88..33d029e 100644 --- a/drivers/windows/pandaJ2534DLL Test/Timer.cpp +++ b/drivers/windows/pandaJ2534DLL Test/Timer.cpp @@ -4,7 +4,7 @@ Timer::Timer() { - start = std::chrono::time_point_cast(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(clock::now()); } \ No newline at end of file diff --git a/drivers/windows/pandaJ2534DLL Test/Timer.h b/drivers/windows/pandaJ2534DLL Test/Timer.h index d4888fc..cbf5579 100644 --- a/drivers/windows/pandaJ2534DLL Test/Timer.h +++ b/drivers/windows/pandaJ2534DLL Test/Timer.h @@ -13,6 +13,8 @@ public: // gets the time elapsed from construction. unsigned long long /*milliseconds*/ getTimePassed(); + void reset(); + private: time_point_type start; }; \ No newline at end of file diff --git a/drivers/windows/pandaJ2534DLL Test/j2534_tests.cpp b/drivers/windows/pandaJ2534DLL Test/j2534_tests.cpp index d37da1b..d84446f 100644 --- a/drivers/windows/pandaJ2534DLL Test/j2534_tests.cpp +++ b/drivers/windows/pandaJ2534DLL Test/j2534_tests.cpp @@ -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 msg_recv = panda_recv_loop(p, 3, 250); + Assert::AreEqual(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 msg_recv = panda_recv_loop(p, 9, 370); + Assert::AreEqual(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid0), _T("Failed to delete filter."), LINE_INFO()); + Assert::AreEqual(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 msg_recv = panda_recv_loop(p, 3, 250); + Assert::AreEqual(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 msg_recv = panda_recv_loop(p, 4, 250); + Assert::AreEqual(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 const mfMsgExpectedParts{ "\x21""DDEEFFG", "\x22""GHHIIJJ", "\x23""KKLLMMN", "\x24""NOOPPQQ", "\x25""RRSSTTU", "\x26""UVVWWXX" }; + + while (TRUE) { + std::vectormsg_recv = p->can_recv(); + for (auto msg : msg_recv) { + if (msg.is_receipt) continue; + if ((msg.dat[0] & 0xf0) == 0x20) { + Assert::AreEqual(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(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(PeriodicMsgReceived, periodicTxIndicationCount, _T("Wrong number of periodic msgs reported by passthru device."), LINE_INFO()); + Assert::AreNotEqual(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. diff --git a/drivers/windows/pandaJ2534DLL Test/stdafx.h b/drivers/windows/pandaJ2534DLL Test/stdafx.h index edf56ae..1ac8bd8 100644 --- a/drivers/windows/pandaJ2534DLL Test/stdafx.h +++ b/drivers/windows/pandaJ2534DLL Test/stdafx.h @@ -10,3 +10,5 @@ // Headers for CppUnitTest #include "CppUnitTest.h" #include //Used for formatting in TestHelpers.cpp +#include +#include diff --git a/drivers/windows/pandaJ2534DLL/Action.h b/drivers/windows/pandaJ2534DLL/Action.h index a0e3768..24624ef 100644 --- a/drivers/windows/pandaJ2534DLL/Action.h +++ b/drivers/windows/pandaJ2534DLL/Action.h @@ -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; } diff --git a/drivers/windows/pandaJ2534DLL/J2534Connection.cpp b/drivers/windows/pandaJ2534DLL/J2534Connection.cpp index 8edaa65..a6bc5b3 100644 --- a/drivers/windows/pandaJ2534DLL/J2534Connection.cpp +++ b/drivers/windows/pandaJ2534DLL/J2534Connection.cpp @@ -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(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(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; diff --git a/drivers/windows/pandaJ2534DLL/J2534Connection.h b/drivers/windows/pandaJ2534DLL/J2534Connection.h index 31798de..5cedba2 100644 --- a/drivers/windows/pandaJ2534DLL/J2534Connection.h +++ b/drivers/windows/pandaJ2534DLL/J2534Connection.h @@ -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 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 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 panda_dev; - std::queue messages; + Mutex messageRxBuff_mutex; + std::queue messageRxBuff; std::array, 10> filters; std::queue> txbuff; + std::array, 10> periodicMessages; + private: - Mutex message_access_lock; Mutex staged_writes_lock; }; diff --git a/drivers/windows/pandaJ2534DLL/J2534Connection_CAN.cpp b/drivers/windows/pandaJ2534DLL/J2534Connection_CAN.cpp index 6dbdc3e..11c0643 100644 --- a/drivers/windows/pandaJ2534DLL/J2534Connection_CAN.cpp +++ b/drivers/windows/pandaJ2534DLL/J2534Connection_CAN.cpp @@ -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(shared_from_this(), *msg); - this->schedultMsgTx(std::dynamic_pointer_cast(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 J2534Connection_CAN::parseMessageTx(PASSTHRU_MSG& msg) { + return std::dynamic_pointer_cast(std::make_shared(shared_from_this(), msg)); +} diff --git a/drivers/windows/pandaJ2534DLL/J2534Connection_CAN.h b/drivers/windows/pandaJ2534DLL/J2534Connection_CAN.h index 707460e..f7fc9cf 100644 --- a/drivers/windows/pandaJ2534DLL/J2534Connection_CAN.h +++ b/drivers/windows/pandaJ2534DLL/J2534Connection_CAN.h @@ -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 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; } diff --git a/drivers/windows/pandaJ2534DLL/J2534Connection_ISO15765.cpp b/drivers/windows/pandaJ2534DLL/J2534Connection_ISO15765.cpp index f9e921d..a7df0e5 100644 --- a/drivers/windows/pandaJ2534DLL/J2534Connection_ISO15765.cpp +++ b/drivers/windows/pandaJ2534DLL/J2534Connection_ISO15765.cpp @@ -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( shared_from_this(), *msg, (fid == -1) ? nullptr : this->filters[fid] ); - this->schedultMsgTx(std::dynamic_pointer_cast(msgtx)); - } return STATUS_NOERROR; } -void J2534Connection_ISO15765::processMessageReceipt(const J2534Frame& msg) { - if (msg.ProtocolID != CAN) return; +std::shared_ptr 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( + std::make_shared(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; } diff --git a/drivers/windows/pandaJ2534DLL/J2534Connection_ISO15765.h b/drivers/windows/pandaJ2534DLL/J2534Connection_ISO15765.h index accad9c..8960f0e 100644 --- a/drivers/windows/pandaJ2534DLL/J2534Connection_ISO15765.h +++ b/drivers/windows/pandaJ2534DLL/J2534Connection_ISO15765.h @@ -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 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; } diff --git a/drivers/windows/pandaJ2534DLL/MessagePeriodic.cpp b/drivers/windows/pandaJ2534DLL/MessagePeriodic.cpp new file mode 100644 index 0000000..0c3416e --- /dev/null +++ b/drivers/windows/pandaJ2534DLL/MessagePeriodic.cpp @@ -0,0 +1,30 @@ +#include "stdafx.h" +#include "MessagePeriodic.h" +#include "J2534Connection.h" + +MessagePeriodic::MessagePeriodic( + std::chrono::microseconds delay, + std::shared_ptr 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()); + } + } +} diff --git a/drivers/windows/pandaJ2534DLL/MessagePeriodic.h b/drivers/windows/pandaJ2534DLL/MessagePeriodic.h new file mode 100644 index 0000000..495f7ee --- /dev/null +++ b/drivers/windows/pandaJ2534DLL/MessagePeriodic.h @@ -0,0 +1,27 @@ +#pragma once +#include "Action.h" +#include "MessageTx.h" + +class J2534Connection; + +class MessagePeriodic : public Action, public std::enable_shared_from_this +{ +public: + MessagePeriodic( + std::chrono::microseconds delay, + std::shared_ptr msg + ); + + virtual void execute(); + + void cancel() { + this->active = FALSE; + } + +protected: + std::shared_ptr msg; + +private: + BOOL runyet; + BOOL active; +}; diff --git a/drivers/windows/pandaJ2534DLL/MessageTx.h b/drivers/windows/pandaJ2534DLL/MessageTx.h index 1b07a47..5315fa0 100644 --- a/drivers/windows/pandaJ2534DLL/MessageTx.h +++ b/drivers/windows/pandaJ2534DLL/MessageTx.h @@ -18,6 +18,8 @@ public: virtual BOOL txReady() = 0; + virtual void reset() = 0; + protected: J2534Frame fullmsg; }; \ No newline at end of file diff --git a/drivers/windows/pandaJ2534DLL/MessageTx_CAN.cpp b/drivers/windows/pandaJ2534DLL/MessageTx_CAN.cpp index d32f110..8217ce5 100644 --- a/drivers/windows/pandaJ2534DLL/MessageTx_CAN.cpp +++ b/drivers/windows/pandaJ2534DLL/MessageTx_CAN.cpp @@ -2,8 +2,6 @@ #include "MessageTx_CAN.h" #include "J2534Connection_CAN.h" -//class J2534Connection_CAN; - MessageTx_CAN::MessageTx_CAN( std::shared_ptr 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(this->connection.lock())) + if (conn_sp->loopback) + conn_sp->addMsgToRxQueue(frame); return TRUE; } return FALSE; } + +void MessageTx_CAN::reset() { + sentyet = FALSE; + txInFlight = FALSE; +} diff --git a/drivers/windows/pandaJ2534DLL/MessageTx_CAN.h b/drivers/windows/pandaJ2534DLL/MessageTx_CAN.h index 0a93777..afac75e 100644 --- a/drivers/windows/pandaJ2534DLL/MessageTx_CAN.h +++ b/drivers/windows/pandaJ2534DLL/MessageTx_CAN.h @@ -25,6 +25,8 @@ public: return !sentyet; }; + virtual void reset(); + private: BOOL sentyet; BOOL txInFlight; diff --git a/drivers/windows/pandaJ2534DLL/MessageTx_ISO15765.cpp b/drivers/windows/pandaJ2534DLL/MessageTx_ISO15765.cpp index a9d8bdf..887cfe8 100644 --- a/drivers/windows/pandaJ2534DLL/MessageTx_ISO15765.cpp +++ b/drivers/windows/pandaJ2534DLL/MessageTx_ISO15765.cpp @@ -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(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()); } } } diff --git a/drivers/windows/pandaJ2534DLL/MessageTx_ISO15765.h b/drivers/windows/pandaJ2534DLL/MessageTx_ISO15765.h index 4c7c396..8db56b3 100644 --- a/drivers/windows/pandaJ2534DLL/MessageTx_ISO15765.h +++ b/drivers/windows/pandaJ2534DLL/MessageTx_ISO15765.h @@ -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); diff --git a/drivers/windows/pandaJ2534DLL/PandaJ2534Device.cpp b/drivers/windows/pandaJ2534DLL/PandaJ2534Device.cpp index c0230b0..eabc0cb 100644 --- a/drivers/windows/pandaJ2534DLL/PandaJ2534Device.cpp +++ b/drivers/windows/pandaJ2534DLL/PandaJ2534Device.cpp @@ -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) { - 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 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 conn) { - synchronized(activeTXs_mutex) { +void PandaJ2534Device::removeConnectionTopAction(std::shared_ptr conn, std::shared_ptr 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. diff --git a/drivers/windows/pandaJ2534DLL/PandaJ2534Device.h b/drivers/windows/pandaJ2534DLL/PandaJ2534Device.h index a6a5b1d..707ed8e 100644 --- a/drivers/windows/pandaJ2534DLL/PandaJ2534Device.h +++ b/drivers/windows/pandaJ2534DLL/PandaJ2534Device.h @@ -37,7 +37,7 @@ public: void unstallConnectionTx(std::shared_ptr conn); - void removeConnectionTopAction(std::shared_ptr conn); + void removeConnectionTopAction(std::shared_ptr conn, std::shared_ptr msg); std::queue> txMsgsAwaitingEcho; @@ -57,7 +57,7 @@ private: } DWORD msg_tx_thread(); std::list> task_queue; - Mutex activeTXs_mutex; + Mutex task_queue_mutex; std::queue> ConnTxQueue; std::set> ConnTxSet; diff --git a/drivers/windows/pandaJ2534DLL/pandaJ2534DLL.vcxproj b/drivers/windows/pandaJ2534DLL/pandaJ2534DLL.vcxproj index 7f6f54c..498c5b6 100644 --- a/drivers/windows/pandaJ2534DLL/pandaJ2534DLL.vcxproj +++ b/drivers/windows/pandaJ2534DLL/pandaJ2534DLL.vcxproj @@ -90,6 +90,7 @@ + @@ -122,6 +123,7 @@ + @@ -141,6 +143,9 @@ + + + diff --git a/drivers/windows/pandaJ2534DLL/pandaJ2534DLL.vcxproj.filters b/drivers/windows/pandaJ2534DLL/pandaJ2534DLL.vcxproj.filters index b4ba2b6..57f7cef 100644 --- a/drivers/windows/pandaJ2534DLL/pandaJ2534DLL.vcxproj.filters +++ b/drivers/windows/pandaJ2534DLL/pandaJ2534DLL.vcxproj.filters @@ -99,6 +99,9 @@ Header Files + + Header Files + @@ -137,10 +140,16 @@ Source Files\J2534_CAN + + Source Files + Resource Files + + + \ No newline at end of file