J2534_WIN: Periodic message support and tests.
parent
3683bbfea8
commit
c41d8230d7
|
@ -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);
|
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,
|
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) {
|
unsigned long Timestamp, unsigned long DataSize, unsigned long ExtraDataIndex, const char* Data, const __LineInfo* pLineInfo) {
|
||||||
|
|
||||||
|
|
|
@ -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,
|
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);
|
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,
|
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);
|
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,
|
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 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 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);
|
unsigned long len, char* mask, char* pattern, const __LineInfo* pLineInfo = NULL);
|
||||||
|
|
||||||
extern unsigned long J2534_set_flowctrl_filter(unsigned long chanid, unsigned long tx,
|
extern unsigned long J2534_set_flowctrl_filter(unsigned long chanid, unsigned long tx,
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
Timer::Timer()
|
Timer::Timer()
|
||||||
{
|
{
|
||||||
start = std::chrono::time_point_cast<std::chrono::milliseconds>(clock::now());
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets the time elapsed from construction.
|
// gets the time elapsed from construction.
|
||||||
|
@ -14,4 +14,8 @@ unsigned long long /*milliseconds*/ Timer::getTimePassed(){
|
||||||
|
|
||||||
// return the difference of the times
|
// return the difference of the times
|
||||||
return (end - start).count();
|
return (end - start).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer::reset() {
|
||||||
|
start = std::chrono::time_point_cast<std::chrono::milliseconds>(clock::now());
|
||||||
}
|
}
|
|
@ -13,6 +13,8 @@ public:
|
||||||
// gets the time elapsed from construction.
|
// gets the time elapsed from construction.
|
||||||
unsigned long long /*milliseconds*/ getTimePassed();
|
unsigned long long /*milliseconds*/ getTimePassed();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
time_point_type start;
|
time_point_type start;
|
||||||
};
|
};
|
|
@ -293,6 +293,157 @@ namespace pandaJ2534DLLTest
|
||||||
check_panda_can_msg(msg_recv[0], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
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)
|
TEST_METHOD(J2534_CAN_BaudInvalid)
|
||||||
{
|
{
|
||||||
unsigned long chanid;
|
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_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;
|
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_1_0 > 10000);
|
||||||
Assert::IsTrue(timediff_2_1 > 10000);
|
Assert::IsTrue(timediff_2_1 > 10000);
|
||||||
Assert::IsTrue(timediff_3_2 > 10000);
|
Assert::IsTrue(timediff_3_2 > 10000);
|
||||||
Assert::IsTrue(timediff_4_3 > 10000);
|
Assert::IsTrue(timediff_4_3 > 10000);
|
||||||
Assert::IsTrue(timediff_5_4 > 10000);
|
Assert::IsTrue(timediff_5_4 > 10000);
|
||||||
Assert::IsTrue(timediff_6_5 > 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.
|
//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());
|
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);
|
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.
|
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.
|
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_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 /////////////////////
|
///////////////////// 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.
|
//Check rx FAILS when frame is dropped. 29 bit. Good Filter. NoPadding. STD address. Multi Frame.
|
||||||
|
|
|
@ -10,3 +10,5 @@
|
||||||
// Headers for CppUnitTest
|
// Headers for CppUnitTest
|
||||||
#include "CppUnitTest.h"
|
#include "CppUnitTest.h"
|
||||||
#include <iomanip> //Used for formatting in TestHelpers.cpp
|
#include <iomanip> //Used for formatting in TestHelpers.cpp
|
||||||
|
#include <string>
|
||||||
|
#include <array>
|
||||||
|
|
|
@ -23,6 +23,10 @@ public:
|
||||||
expire = std::chrono::steady_clock::now();
|
expire = std::chrono::steady_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scheduleDelay() {
|
||||||
|
expire += this->delay;
|
||||||
|
}
|
||||||
|
|
||||||
void scheduleImmediateDelay() {
|
void scheduleImmediateDelay() {
|
||||||
expire = std::chrono::steady_clock::now() + this->delay;
|
expire = std::chrono::steady_clock::now() + this->delay;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,12 @@ J2534Connection::J2534Connection(
|
||||||
unsigned long BaudRate
|
unsigned long BaudRate
|
||||||
) : panda_dev(panda_dev), ProtocolID(ProtocolID), Flags(Flags), BaudRate(BaudRate), port(0) { }
|
) : panda_dev(panda_dev), ProtocolID(ProtocolID), Flags(Flags), BaudRate(BaudRate), 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) {
|
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.
|
//Timeout of 0 means return immediately. Non zero means WAIT for that time then return. Dafuk.
|
||||||
long err_code = STATUS_NOERROR;
|
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
|
//Synchronized won't work where we have to break out of a loop
|
||||||
message_access_lock.lock();
|
messageRxBuff_mutex.lock();
|
||||||
if (this->messages.empty()) {
|
if (this->messageRxBuff.empty()) {
|
||||||
message_access_lock.unlock();
|
messageRxBuff_mutex.unlock();
|
||||||
if (Timeout == 0)
|
if (Timeout == 0)
|
||||||
break;
|
break;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto msg_in = this->messages.front();
|
auto msg_in = this->messageRxBuff.front();
|
||||||
this->messages.pop();
|
this->messageRxBuff.pop();
|
||||||
message_access_lock.unlock();
|
messageRxBuff_mutex.unlock();
|
||||||
|
|
||||||
PASSTHRU_MSG *msg_out = &pMsg[msgnum++];
|
PASSTHRU_MSG *msg_out = &pMsg[msgnum++];
|
||||||
msg_out->ProtocolID = this->ProtocolID;
|
msg_out->ProtocolID = this->ProtocolID;
|
||||||
|
@ -50,9 +56,60 @@ long J2534Connection::PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMs
|
||||||
*pNumMsgs = msgnum;
|
*pNumMsgs = msgnum;
|
||||||
return err_code;
|
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::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) {
|
||||||
long J2534Connection::PassThruStopPeriodicMsg(unsigned long MsgID) { return STATUS_NOERROR; }
|
//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,
|
long J2534Connection::PassThruStartMsgFilter(unsigned long FilterType, PASSTHRU_MSG *pMaskMsg, PASSTHRU_MSG *pPatternMsg,
|
||||||
PASSTHRU_MSG *pFlowControlMsg, unsigned long *pFilterID) {
|
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::initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput) { return STATUS_NOERROR; }
|
||||||
long J2534Connection::clearTXBuff() { return STATUS_NOERROR; }
|
long J2534Connection::clearTXBuff() { return STATUS_NOERROR; }
|
||||||
long J2534Connection::clearRXBuff() {
|
long J2534Connection::clearRXBuff() {
|
||||||
this->messages = {};
|
synchronized(messageRxBuff_mutex) {
|
||||||
|
this->messageRxBuff = {};
|
||||||
|
}
|
||||||
return STATUS_NOERROR;
|
return STATUS_NOERROR;
|
||||||
}
|
}
|
||||||
long J2534Connection::clearPeriodicMsgs() { 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.
|
//Works well as long as the protocol doesn't support flow control.
|
||||||
void J2534Connection::processMessage(const J2534Frame& msg) {
|
void J2534Connection::processMessage(const J2534Frame& msg) {
|
||||||
FILTER_RESULT filter_res = FILTER_RESULT_NEUTRAL;
|
FILTER_RESULT filter_res = FILTER_RESULT_NEUTRAL;
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include "J2534Frame.h"
|
#include "J2534Frame.h"
|
||||||
#include "PandaJ2534Device.h"
|
#include "PandaJ2534Device.h"
|
||||||
#include "J2534MessageFilter.h"
|
#include "J2534MessageFilter.h"
|
||||||
|
#include "MessagePeriodic.h"
|
||||||
|
|
||||||
class J2534Frame;
|
class J2534Frame;
|
||||||
class Action;
|
class Action;
|
||||||
|
@ -25,7 +26,7 @@ public:
|
||||||
);
|
);
|
||||||
virtual ~J2534Connection() {};
|
virtual ~J2534Connection() {};
|
||||||
virtual long PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
|
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 PassThruStartPeriodicMsg(PASSTHRU_MSG *pMsg, unsigned long *pMsgID, unsigned long TimeInterval);
|
||||||
virtual long PassThruStopPeriodicMsg(unsigned long MsgID);
|
virtual long PassThruStopPeriodicMsg(unsigned long MsgID);
|
||||||
|
|
||||||
|
@ -35,6 +36,10 @@ public:
|
||||||
virtual long PassThruStopMsgFilter(unsigned long FilterID);
|
virtual long PassThruStopMsgFilter(unsigned long FilterID);
|
||||||
virtual long PassThruIoctl(unsigned long IoctlID, void *pInput, void *pOutput);
|
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 init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput);
|
||||||
long initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput);
|
long initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput);
|
||||||
long clearTXBuff();
|
long clearTXBuff();
|
||||||
|
@ -59,7 +64,6 @@ public:
|
||||||
return this->port;
|
return this->port;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void processMessageReceipt(const J2534Frame& msg);
|
|
||||||
virtual void processMessage(const J2534Frame& msg);
|
virtual void processMessage(const J2534Frame& msg);
|
||||||
|
|
||||||
virtual unsigned long getMinMsgLen() {
|
virtual unsigned long getMinMsgLen() {
|
||||||
|
@ -70,6 +74,10 @@ public:
|
||||||
return 4128;
|
return 4128;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual unsigned long getMaxMsgSingleFrameLen() {
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
|
||||||
void schedultMsgTx(std::shared_ptr<Action> msgout);
|
void schedultMsgTx(std::shared_ptr<Action> msgout);
|
||||||
|
|
||||||
void rescheduleExistingTxMsgs();
|
void rescheduleExistingTxMsgs();
|
||||||
|
@ -81,8 +89,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
void addMsgToRxQueue(const J2534Frame& frame) {
|
void addMsgToRxQueue(const J2534Frame& frame) {
|
||||||
synchronized(message_access_lock) {
|
synchronized(messageRxBuff_mutex) {
|
||||||
messages.push(frame);
|
messageRxBuff.push(frame);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,12 +104,14 @@ protected:
|
||||||
|
|
||||||
std::weak_ptr<PandaJ2534Device> panda_dev;
|
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::array<std::shared_ptr<J2534MessageFilter>, 10> filters;
|
||||||
std::queue<std::shared_ptr<Action>> txbuff;
|
std::queue<std::shared_ptr<Action>> txbuff;
|
||||||
|
|
||||||
|
std::array<std::shared_ptr<MessagePeriodic>, 10> periodicMessages;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Mutex message_access_lock;
|
|
||||||
Mutex staged_writes_lock;
|
Mutex staged_writes_lock;
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,22 +17,13 @@ J2534Connection_CAN::J2534Connection_CAN(
|
||||||
panda_dev->panda->set_can_speed_cbps(panda::PANDA_CAN1, BaudRate/100);
|
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) {
|
unsigned long J2534Connection_CAN::validateTxMsg(PASSTHRU_MSG* msg) {
|
||||||
//There doesn't seem to be much reason to implement the timeout here.
|
if ((msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen() ||
|
||||||
for (int msgnum = 0; msgnum < *pNumMsgs; msgnum++) {
|
(val_is_29bit(msg->TxFlags) != this->_is_29bit() && !check_bmask(this->Flags, CAN_ID_BOTH))))
|
||||||
PASSTHRU_MSG* msg = &pMsg[msgnum];
|
return ERR_INVALID_MSG;
|
||||||
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));
|
|
||||||
}
|
|
||||||
return STATUS_NOERROR;
|
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));
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,9 @@ public:
|
||||||
unsigned long BaudRate
|
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() {
|
virtual unsigned long getMinMsgLen() {
|
||||||
return 4;
|
return 4;
|
||||||
|
@ -24,6 +26,10 @@ public:
|
||||||
return 12;
|
return 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual unsigned long getMaxMsgSingleFrameLen() {
|
||||||
|
return 12;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool isProtoCan() {
|
virtual bool isProtoCan() {
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,35 +18,25 @@ J2534Connection_ISO15765::J2534Connection_ISO15765(
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
long J2534Connection_ISO15765::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) {
|
unsigned long J2534Connection_ISO15765::validateTxMsg(PASSTHRU_MSG* msg) {
|
||||||
for (unsigned int msgnum = 0; msgnum < *pNumMsgs; msgnum++) {
|
if ((msg->DataSize < this->getMinMsgLen() + (msg_is_extaddr(msg) ? 1 : 0) ||
|
||||||
PASSTHRU_MSG* msg = &pMsg[msgnum];
|
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) {
|
int fid = get_matching_out_fc_filter_id(std::string((const char*)msg->Data, msg->DataSize), msg->TxFlags, 0xFFFFFFFF);
|
||||||
*pNumMsgs = msgnum;
|
if (msg->DataSize > getMaxMsgSingleFrameLen() && fid == -1) return ERR_NO_FLOW_CONTROL; //11 bytes (4 for CANid, 7 payload) is max length of input frame.
|
||||||
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 > 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;
|
return STATUS_NOERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
void J2534Connection_ISO15765::processMessageReceipt(const J2534Frame& msg) {
|
std::shared_ptr<MessageTx> J2534Connection_ISO15765::parseMessageTx(PASSTHRU_MSG& msg) {
|
||||||
if (msg.ProtocolID != CAN) return;
|
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
|
return std::dynamic_pointer_cast<MessageTx>(
|
||||||
if (!check_bmask(msg.RxStatus, TX_MSG_TYPE)) return;
|
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/
|
//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)) {
|
switch (msg_get_type(msg, addrlen)) {
|
||||||
case FRAME_FLOWCTRL:
|
case FRAME_FLOWCTRL:
|
||||||
{
|
{
|
||||||
|
if (this->txbuff.size() == 0)
|
||||||
|
return;
|
||||||
if (msg.Data.size() < addrlen + 3) return;
|
if (msg.Data.size() < addrlen + 3) return;
|
||||||
uint8_t flow_status = msg.Data[addrlen] & 0x0F;
|
uint8_t flow_status = msg.Data[addrlen] & 0x0F;
|
||||||
uint8_t block_size = msg.Data[addrlen + 1];
|
uint8_t block_size = msg.Data[addrlen + 1];
|
||||||
|
@ -79,6 +71,7 @@ void J2534Connection_ISO15765::processMessage(const J2534Frame& msg) {
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
txConvo->scheduleImmediate();
|
||||||
this->rescheduleExistingTxMsgs();
|
this->rescheduleExistingTxMsgs();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,15 +21,16 @@ public:
|
||||||
unsigned long BaudRate
|
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);
|
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_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);
|
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 void processMessage(const J2534Frame& msg);
|
||||||
|
|
||||||
virtual unsigned long getMinMsgLen() {
|
virtual unsigned long getMinMsgLen() {
|
||||||
|
@ -40,6 +41,10 @@ public:
|
||||||
return 4099;
|
return 4099;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
virtual unsigned long getMaxMsgSingleFrameLen() {
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
|
||||||
virtual bool _is_29bit() {
|
virtual bool _is_29bit() {
|
||||||
return (this->Flags & CAN_29BIT_ID) == CAN_29BIT_ID;
|
return (this->Flags & CAN_29BIT_ID) == CAN_29BIT_ID;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
};
|
|
@ -18,6 +18,8 @@ public:
|
||||||
|
|
||||||
virtual BOOL txReady() = 0;
|
virtual BOOL txReady() = 0;
|
||||||
|
|
||||||
|
virtual void reset() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
J2534Frame fullmsg;
|
J2534Frame fullmsg;
|
||||||
};
|
};
|
|
@ -2,8 +2,6 @@
|
||||||
#include "MessageTx_CAN.h"
|
#include "MessageTx_CAN.h"
|
||||||
#include "J2534Connection_CAN.h"
|
#include "J2534Connection_CAN.h"
|
||||||
|
|
||||||
//class J2534Connection_CAN;
|
|
||||||
|
|
||||||
MessageTx_CAN::MessageTx_CAN(
|
MessageTx_CAN::MessageTx_CAN(
|
||||||
std::shared_ptr<J2534Connection> connection_in,
|
std::shared_ptr<J2534Connection> connection_in,
|
||||||
PASSTHRU_MSG& to_send
|
PASSTHRU_MSG& to_send
|
||||||
|
@ -32,7 +30,15 @@ BOOL MessageTx_CAN::checkTxReceipt(J2534Frame frame) {
|
||||||
if (txReady()) return FALSE;
|
if (txReady()) return FALSE;
|
||||||
if (frame.Data == fullmsg.Data && ((this->fullmsg.TxFlags & CAN_29BIT_ID) == (frame.RxStatus & CAN_29BIT_ID))) {
|
if (frame.Data == fullmsg.Data && ((this->fullmsg.TxFlags & CAN_29BIT_ID) == (frame.RxStatus & CAN_29BIT_ID))) {
|
||||||
txInFlight = FALSE;
|
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 TRUE;
|
||||||
}
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessageTx_CAN::reset() {
|
||||||
|
sentyet = FALSE;
|
||||||
|
txInFlight = FALSE;
|
||||||
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ public:
|
||||||
return !sentyet;
|
return !sentyet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
virtual void reset();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BOOL sentyet;
|
BOOL sentyet;
|
||||||
BOOL txInFlight;
|
BOOL txInFlight;
|
||||||
|
|
|
@ -131,11 +131,21 @@ BOOL MessageTx_ISO15765::txReady() {
|
||||||
return block_size > 0 || sendAll || this->frames_sent == 0;
|
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() {
|
void MessageTx_ISO15765::onTimeout() {
|
||||||
didtimeout = TRUE;
|
didtimeout = TRUE;
|
||||||
if (auto conn_sp = std::static_pointer_cast<J2534Connection_ISO15765>(this->connection.lock())) {
|
if (auto conn_sp = std::static_pointer_cast<J2534Connection_ISO15765>(this->connection.lock())) {
|
||||||
if (auto panda_dev_sp = conn_sp->getPandaDev()) {
|
if (auto panda_dev_sp = conn_sp->getPandaDev()) {
|
||||||
panda_dev_sp->removeConnectionTopAction(conn_sp);
|
panda_dev_sp->removeConnectionTopAction(conn_sp, shared_from_this());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ public:
|
||||||
|
|
||||||
virtual BOOL txReady();
|
virtual BOOL txReady();
|
||||||
|
|
||||||
|
virtual void reset();
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -75,7 +75,7 @@ DWORD PandaJ2534Device::can_recv_thread() {
|
||||||
J2534Frame msg_out(msg_in);
|
J2534Frame msg_out(msg_in);
|
||||||
|
|
||||||
if (msg_in.is_receipt) {
|
if (msg_in.is_receipt) {
|
||||||
synchronized(activeTXs_mutex) {
|
synchronized(task_queue_mutex) {
|
||||||
if (txMsgsAwaitingEcho.size() > 0) {
|
if (txMsgsAwaitingEcho.size() > 0) {
|
||||||
auto msgtx = txMsgsAwaitingEcho.front();
|
auto msgtx = txMsgsAwaitingEcho.front();
|
||||||
if (auto conn = msgtx->connection.lock()) {
|
if (auto conn = msgtx->connection.lock()) {
|
||||||
|
@ -89,8 +89,7 @@ DWORD PandaJ2534Device::can_recv_thread() {
|
||||||
txMsgsAwaitingEcho.pop(); //Remove the TX object and schedule record.
|
txMsgsAwaitingEcho.pop(); //Remove the TX object and schedule record.
|
||||||
|
|
||||||
if (msgtx->isFinished()) {
|
if (msgtx->isFinished()) {
|
||||||
conn->processMessageReceipt(msg_out); //Alert the connection a tx is done.
|
this->removeConnectionTopAction(conn, msgtx);
|
||||||
this->removeConnectionTopAction(conn);
|
|
||||||
} else {
|
} else {
|
||||||
if (msgtx->txReady()) { //Not finished, ready to send next frame.
|
if (msgtx->txReady()) { //Not finished, ready to send next frame.
|
||||||
msgtx->schedule(msg_in.recv_time_point, TRUE);
|
msgtx->schedule(msg_in.recv_time_point, TRUE);
|
||||||
|
@ -135,7 +134,7 @@ DWORD PandaJ2534Device::msg_tx_thread() {
|
||||||
ResetEvent(this->flow_control_wakeup_event);
|
ResetEvent(this->flow_control_wakeup_event);
|
||||||
|
|
||||||
while (TRUE) {
|
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) {
|
if (this->task_queue.size() == 0) {
|
||||||
sleepDuration = INFINITE;
|
sleepDuration = INFINITE;
|
||||||
goto break_flow_ctrl_loop;
|
goto break_flow_ctrl_loop;
|
||||||
|
@ -159,7 +158,7 @@ DWORD PandaJ2534Device::msg_tx_thread() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PandaJ2534Device::insertActionIntoTaskList(std::shared_ptr<Action> action) {
|
void PandaJ2534Device::insertActionIntoTaskList(std::shared_ptr<Action> action) {
|
||||||
synchronized(activeTXs_mutex) {
|
synchronized(task_queue_mutex) {
|
||||||
auto iter = this->task_queue.begin();
|
auto iter = this->task_queue.begin();
|
||||||
for (; iter != this->task_queue.end(); iter++) {
|
for (; iter != this->task_queue.end(); iter++) {
|
||||||
if (action->expire < (*iter)->expire) break;
|
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.
|
if (ret.second == TRUE) return; //Conn already exists.
|
||||||
this->insertActionIntoTaskList(conn->txbuff.front());
|
this->insertActionIntoTaskList(conn->txbuff.front());
|
||||||
}
|
}
|
||||||
SetEvent(flow_control_wakeup_event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PandaJ2534Device::removeConnectionTopAction(std::shared_ptr<J2534Connection> conn) {
|
void PandaJ2534Device::removeConnectionTopAction(std::shared_ptr<J2534Connection> conn, std::shared_ptr<MessageTx> msg) {
|
||||||
synchronized(activeTXs_mutex) {
|
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.
|
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.
|
//Remove the connection from the active connection list if no more messages are scheduled with this connection.
|
||||||
|
|
|
@ -37,7 +37,7 @@ public:
|
||||||
|
|
||||||
void unstallConnectionTx(std::shared_ptr<J2534Connection> conn);
|
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;
|
std::queue<std::shared_ptr<MessageTx>> txMsgsAwaitingEcho;
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ private:
|
||||||
}
|
}
|
||||||
DWORD msg_tx_thread();
|
DWORD msg_tx_thread();
|
||||||
std::list<std::shared_ptr<Action>> task_queue;
|
std::list<std::shared_ptr<Action>> task_queue;
|
||||||
Mutex activeTXs_mutex;
|
Mutex task_queue_mutex;
|
||||||
|
|
||||||
std::queue<std::shared_ptr<J2534Connection>> ConnTxQueue;
|
std::queue<std::shared_ptr<J2534Connection>> ConnTxQueue;
|
||||||
std::set<std::shared_ptr<J2534Connection>> ConnTxSet;
|
std::set<std::shared_ptr<J2534Connection>> ConnTxSet;
|
||||||
|
|
|
@ -90,6 +90,7 @@
|
||||||
<ClInclude Include="..\panda\panda.h" />
|
<ClInclude Include="..\panda\panda.h" />
|
||||||
<ClInclude Include="constants_ISO15765.h" />
|
<ClInclude Include="constants_ISO15765.h" />
|
||||||
<ClInclude Include="dllmain.h" />
|
<ClInclude Include="dllmain.h" />
|
||||||
|
<ClInclude Include="MessagePeriodic.h" />
|
||||||
<ClInclude Include="MessageRx.h" />
|
<ClInclude Include="MessageRx.h" />
|
||||||
<ClInclude Include="J2534Connection.h" />
|
<ClInclude Include="J2534Connection.h" />
|
||||||
<ClInclude Include="J2534Connection_CAN.h" />
|
<ClInclude Include="J2534Connection_CAN.h" />
|
||||||
|
@ -122,6 +123,7 @@
|
||||||
<ClCompile Include="J2534Connection_CAN.cpp" />
|
<ClCompile Include="J2534Connection_CAN.cpp" />
|
||||||
<ClCompile Include="J2534Connection_ISO15765.cpp" />
|
<ClCompile Include="J2534Connection_ISO15765.cpp" />
|
||||||
<ClCompile Include="J2534MessageFilter.cpp" />
|
<ClCompile Include="J2534MessageFilter.cpp" />
|
||||||
|
<ClCompile Include="MessagePeriodic.cpp" />
|
||||||
<ClCompile Include="MessageTxTimeout.cpp" />
|
<ClCompile Include="MessageTxTimeout.cpp" />
|
||||||
<ClCompile Include="MessageTx_CAN.cpp" />
|
<ClCompile Include="MessageTx_CAN.cpp" />
|
||||||
<ClCompile Include="MessageTx_ISO15765.cpp" />
|
<ClCompile Include="MessageTx_ISO15765.cpp" />
|
||||||
|
@ -141,6 +143,9 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="pandaJ2534DLL.rc" />
|
<ResourceCompile Include="pandaJ2534DLL.rc" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="ClassDiagram.cd" />
|
||||||
|
</ItemGroup>
|
||||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
<ImportGroup Label="ExtensionTargets">
|
<ImportGroup Label="ExtensionTargets">
|
||||||
</ImportGroup>
|
</ImportGroup>
|
||||||
|
|
|
@ -99,6 +99,9 @@
|
||||||
<ClInclude Include="MessageTx.h">
|
<ClInclude Include="MessageTx.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="MessagePeriodic.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="pandaJ2534DLL.cpp">
|
<ClCompile Include="pandaJ2534DLL.cpp">
|
||||||
|
@ -137,10 +140,16 @@
|
||||||
<ClCompile Include="MessageTx_CAN.cpp">
|
<ClCompile Include="MessageTx_CAN.cpp">
|
||||||
<Filter>Source Files\J2534_CAN</Filter>
|
<Filter>Source Files\J2534_CAN</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="MessagePeriodic.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="pandaJ2534DLL.rc">
|
<ResourceCompile Include="pandaJ2534DLL.rc">
|
||||||
<Filter>Resource Files</Filter>
|
<Filter>Resource Files</Filter>
|
||||||
</ResourceCompile>
|
</ResourceCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="ClassDiagram.cd" />
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in New Issue