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);
|
||||
}
|
||||
|
||||
unsigned long J2534_start_periodic_msg_checked(unsigned long chanid, unsigned long ProtocolID, unsigned long TxFlags, unsigned long DataSize,
|
||||
unsigned long ExtraDataIndex, const char * Data, unsigned long TimeInterval, const __LineInfo * pLineInfo) {
|
||||
PASSTHRU_MSG msg = { ProtocolID, 0, TxFlags, 0, DataSize, ExtraDataIndex };
|
||||
memcpy_s(msg.Data, 4128, Data, DataSize);
|
||||
unsigned long msgID;
|
||||
Assert::AreEqual<long>(STATUS_NOERROR, J2534_start_periodic_msg(chanid, ProtocolID, TxFlags, DataSize,
|
||||
ExtraDataIndex, Data, TimeInterval, &msgID, pLineInfo), _T("Failed to start Periodic Message."), pLineInfo);
|
||||
return msgID;
|
||||
}
|
||||
|
||||
unsigned long J2534_start_periodic_msg(unsigned long chanid, unsigned long ProtocolID, unsigned long TxFlags, unsigned long DataSize,
|
||||
unsigned long ExtraDataIndex, const char * Data, unsigned long TimeInterval, unsigned long* msgID, const __LineInfo * pLineInfo) {
|
||||
PASSTHRU_MSG msg = { ProtocolID, 0, TxFlags, 0, DataSize, ExtraDataIndex };
|
||||
memcpy_s(msg.Data, 4128, Data, DataSize);
|
||||
return PassThruStartPeriodicMsg(chanid, &msg, msgID, TimeInterval);
|
||||
}
|
||||
|
||||
void J2534_send_msg_checked(unsigned long chanid, unsigned long ProtocolID, unsigned long RxStatus, unsigned long TxFlags,
|
||||
unsigned long Timestamp, unsigned long DataSize, unsigned long ExtraDataIndex, const char* Data, const __LineInfo* pLineInfo) {
|
||||
|
||||
|
|
|
@ -12,6 +12,12 @@ extern std::vector<panda::PANDA_CAN_MSG> panda_recv_loop(std::unique_ptr<panda::
|
|||
extern void check_panda_can_msg(panda::PANDA_CAN_MSG& msgin, uint8_t bus, unsigned long addr, bool addr_29b,
|
||||
bool is_receipt, std::string dat, const __LineInfo* pLineInfo = NULL);
|
||||
|
||||
extern unsigned long J2534_start_periodic_msg_checked(unsigned long chanid, unsigned long ProtocolID, unsigned long TxFlags, unsigned long DataSize,
|
||||
unsigned long ExtraDataIndex, const char * Data, unsigned long TimeInterval, const __LineInfo * pLineInfo);
|
||||
|
||||
extern unsigned long J2534_start_periodic_msg(unsigned long chanid, unsigned long ProtocolID, unsigned long TxFlags, unsigned long DataSize,
|
||||
unsigned long ExtraDataIndex, const char* Data, unsigned long TimeInterval, unsigned long* msgID, const __LineInfo* pLineInfo = NULL);
|
||||
|
||||
extern void J2534_send_msg_checked(unsigned long chanid, unsigned long ProtocolID, unsigned long RxStatus, unsigned long TxFlags,
|
||||
unsigned long Timestamp, unsigned long DataSize, unsigned long ExtraDataIndex, const char* Data, const __LineInfo* pLineInfo = NULL);
|
||||
|
||||
|
@ -23,10 +29,10 @@ extern std::vector<PASSTHRU_MSG> j2534_recv_loop(unsigned int chanid, unsigned i
|
|||
extern void check_J2534_can_msg(PASSTHRU_MSG& msgin, unsigned long ProtocolID, unsigned long RxStatus, unsigned long TxFlags,
|
||||
unsigned long DataSize, unsigned long ExtraDataIndex, const char* Data, const __LineInfo* pLineInfo = NULL);
|
||||
|
||||
unsigned long J2534_set_PASS_filter(unsigned long chanid, unsigned long ProtocolID, unsigned long tx,
|
||||
extern unsigned long J2534_set_PASS_filter(unsigned long chanid, unsigned long ProtocolID, unsigned long tx,
|
||||
unsigned long len, char* mask, char* pattern, const __LineInfo* pLineInfo = NULL);
|
||||
|
||||
unsigned long J2534_set_BLOCK_filter(unsigned long chanid, unsigned long ProtocolID, unsigned long tx,
|
||||
extern unsigned long J2534_set_BLOCK_filter(unsigned long chanid, unsigned long ProtocolID, unsigned long tx,
|
||||
unsigned long len, char* mask, char* pattern, const __LineInfo* pLineInfo = NULL);
|
||||
|
||||
extern unsigned long J2534_set_flowctrl_filter(unsigned long chanid, unsigned long tx,
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
Timer::Timer()
|
||||
{
|
||||
start = std::chrono::time_point_cast<std::chrono::milliseconds>(clock::now());
|
||||
reset();
|
||||
}
|
||||
|
||||
// gets the time elapsed from construction.
|
||||
|
@ -14,4 +14,8 @@ unsigned long long /*milliseconds*/ Timer::getTimePassed(){
|
|||
|
||||
// return the difference of the times
|
||||
return (end - start).count();
|
||||
}
|
||||
|
||||
void Timer::reset() {
|
||||
start = std::chrono::time_point_cast<std::chrono::milliseconds>(clock::now());
|
||||
}
|
|
@ -13,6 +13,8 @@ public:
|
|||
// gets the time elapsed from construction.
|
||||
unsigned long long /*milliseconds*/ getTimePassed();
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
time_point_type start;
|
||||
};
|
|
@ -293,6 +293,157 @@ namespace pandaJ2534DLLTest
|
|||
check_panda_can_msg(msg_recv[0], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
}
|
||||
|
||||
TEST_METHOD(J2534_CAN_PeriodicMessageStartStop)
|
||||
{
|
||||
auto chanid = J2534_open_and_connect("", CAN, 0, 500000, LINE_INFO());
|
||||
auto p = getPanda(500);
|
||||
|
||||
auto msgid = J2534_start_periodic_msg_checked(chanid, CAN, 0, 6, 0, "\x0\x0\x3\xAB""HI", 100, LINE_INFO());
|
||||
|
||||
std::vector<panda::PANDA_CAN_MSG> msg_recv = panda_recv_loop(p, 3, 250);
|
||||
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid), _T("Failed to delete filter."), LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[0], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[1], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[2], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
|
||||
auto timediff_1_0 = msg_recv[1].recv_time - msg_recv[0].recv_time;
|
||||
auto timediff_2_1 = msg_recv[2].recv_time - msg_recv[1].recv_time;
|
||||
|
||||
std::ostringstream stringStream1;
|
||||
stringStream1 << "times1: " << timediff_1_0 << ", " << timediff_2_1 << std::endl;
|
||||
Logger::WriteMessage(stringStream1.str().c_str());
|
||||
|
||||
Assert::IsTrue(timediff_1_0 > 90000);
|
||||
Assert::IsTrue(timediff_1_0 < 110000);
|
||||
Assert::IsTrue(timediff_2_1 > 90000);
|
||||
Assert::IsTrue(timediff_2_1 < 110000);
|
||||
|
||||
msg_recv = panda_recv_loop(p, 0, 300);
|
||||
}
|
||||
|
||||
TEST_METHOD(J2534_CAN_PeriodicMessageMultipleStartStop)
|
||||
{
|
||||
auto chanid = J2534_open_and_connect("", CAN, 0, 500000, LINE_INFO());
|
||||
auto p = getPanda(500);
|
||||
|
||||
auto msgid0 = J2534_start_periodic_msg_checked(chanid, CAN, 0, 6, 0, "\x0\x0\x3\xAB""HI", 100, LINE_INFO());
|
||||
auto msgid1 = J2534_start_periodic_msg_checked(chanid, CAN, 0, 6, 0, "\x0\x0\x1\x23""YO", 80, LINE_INFO());
|
||||
|
||||
std::vector<panda::PANDA_CAN_MSG> msg_recv = panda_recv_loop(p, 9, 370);
|
||||
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid0), _T("Failed to delete filter."), LINE_INFO());
|
||||
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid1), _T("Failed to delete filter."), LINE_INFO());
|
||||
//time diagram. 10 ms per character. * is send event. : is termination of periodic messages.
|
||||
//*---------*---------*---------*-----:----* HI
|
||||
//*-------*-------*-------*-------*---:----* YO
|
||||
check_panda_can_msg(msg_recv[0], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[1], 0, 0x123, FALSE, FALSE, "YO", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[2], 0, 0x123, FALSE, FALSE, "YO", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[3], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[4], 0, 0x123, FALSE, FALSE, "YO", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[5], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[6], 0, 0x123, FALSE, FALSE, "YO", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[7], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[8], 0, 0x123, FALSE, FALSE, "YO", LINE_INFO());
|
||||
|
||||
auto timediff_HI_3_0 = msg_recv[3].recv_time - msg_recv[0].recv_time;
|
||||
auto timediff_HI_5_3 = msg_recv[5].recv_time - msg_recv[3].recv_time;
|
||||
auto timediff_HI_7_5 = msg_recv[7].recv_time - msg_recv[5].recv_time;
|
||||
|
||||
auto timediff_YO_2_1 = msg_recv[2].recv_time - msg_recv[1].recv_time;
|
||||
auto timediff_YO_4_2 = msg_recv[4].recv_time - msg_recv[2].recv_time;
|
||||
auto timediff_YO_6_4 = msg_recv[6].recv_time - msg_recv[4].recv_time;
|
||||
auto timediff_YO_8_6 = msg_recv[8].recv_time - msg_recv[6].recv_time;
|
||||
|
||||
std::ostringstream stringStreamHi;
|
||||
stringStreamHi << "HiTimes: " << timediff_HI_3_0 << ", " << timediff_HI_5_3 << ", " << timediff_HI_7_5 << std::endl;
|
||||
Logger::WriteMessage(stringStreamHi.str().c_str());
|
||||
|
||||
std::ostringstream stringStreamYo;
|
||||
stringStreamYo << "HiTimes: " << timediff_YO_2_1 << ", " << timediff_YO_4_2 << ", " << timediff_YO_6_4 << ", " << timediff_YO_8_6 << std::endl;
|
||||
Logger::WriteMessage(stringStreamYo.str().c_str());
|
||||
|
||||
Assert::IsTrue(timediff_HI_3_0 > 90000);
|
||||
Assert::IsTrue(timediff_HI_3_0 < 110000);
|
||||
Assert::IsTrue(timediff_HI_5_3 > 90000);
|
||||
Assert::IsTrue(timediff_HI_5_3 < 110000);
|
||||
Assert::IsTrue(timediff_HI_7_5 > 90000);
|
||||
Assert::IsTrue(timediff_HI_7_5 < 110000);
|
||||
|
||||
Assert::IsTrue(timediff_YO_2_1 > 80000-10000);
|
||||
Assert::IsTrue(timediff_YO_2_1 < 80000+1000);
|
||||
Assert::IsTrue(timediff_YO_4_2 > 80000 - 10000);
|
||||
Assert::IsTrue(timediff_YO_4_2 < 80000 + 10000);
|
||||
Assert::IsTrue(timediff_YO_6_4 > 80000 - 10000);
|
||||
Assert::IsTrue(timediff_YO_6_4 < 80000 + 10000);
|
||||
Assert::IsTrue(timediff_YO_8_6 > 80000 - 10000);
|
||||
Assert::IsTrue(timediff_YO_8_6 < 80000 + 10000);
|
||||
|
||||
msg_recv = panda_recv_loop(p, 0, 300);
|
||||
}
|
||||
|
||||
TEST_METHOD(J2534_CAN_PeriodicMessageStartStop_Loopback)
|
||||
{
|
||||
auto chanid = J2534_open_and_connect("", CAN, 0, 500000, LINE_INFO());
|
||||
write_ioctl(chanid, LOOPBACK, TRUE, LINE_INFO()); // ENABLE J2534 ECHO/LOOPBACK
|
||||
auto p = getPanda(500);
|
||||
auto msgid = J2534_start_periodic_msg_checked(chanid, CAN, 0, 6, 0, "\x0\x0\x3\xAB""HI", 100, LINE_INFO());
|
||||
|
||||
std::vector<panda::PANDA_CAN_MSG> msg_recv = panda_recv_loop(p, 3, 250);
|
||||
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid), _T("Failed to delete filter."), LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[0], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[1], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[2], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
|
||||
auto j2534_msg_recv = j2534_recv_loop(chanid, 3);
|
||||
check_J2534_can_msg(j2534_msg_recv[0], CAN, TX_MSG_TYPE, 0, 6, 0, "\x0\x0\x3\xAB""HI", LINE_INFO());
|
||||
check_J2534_can_msg(j2534_msg_recv[1], CAN, TX_MSG_TYPE, 0, 6, 0, "\x0\x0\x3\xAB""HI", LINE_INFO());
|
||||
check_J2534_can_msg(j2534_msg_recv[2], CAN, TX_MSG_TYPE, 0, 6, 0, "\x0\x0\x3\xAB""HI", LINE_INFO());
|
||||
|
||||
auto timediff_1_0 = j2534_msg_recv[1].Timestamp - j2534_msg_recv[0].Timestamp;
|
||||
auto timediff_2_1 = j2534_msg_recv[2].Timestamp - j2534_msg_recv[1].Timestamp;
|
||||
|
||||
std::ostringstream stringStream1;
|
||||
stringStream1 << "times1: " << timediff_1_0 << ", " << timediff_2_1 << std::endl;
|
||||
Logger::WriteMessage(stringStream1.str().c_str());
|
||||
|
||||
Assert::IsTrue(timediff_1_0 > 90000);
|
||||
Assert::IsTrue(timediff_1_0 < 110000);
|
||||
Assert::IsTrue(timediff_2_1 > 90000);
|
||||
Assert::IsTrue(timediff_2_1 < 110000);
|
||||
|
||||
msg_recv = panda_recv_loop(p, 0, 300);
|
||||
}
|
||||
|
||||
TEST_METHOD(J2534_CAN_PeriodicMessageWithTx)
|
||||
{
|
||||
auto chanid = J2534_open_and_connect("", CAN, 0, 500000, LINE_INFO());
|
||||
auto p = getPanda(500);
|
||||
auto msgid = J2534_start_periodic_msg_checked(chanid, CAN, 0, 6, 0, "\x0\x0\x3\xAB""HI", 100, LINE_INFO());
|
||||
|
||||
J2534_send_msg(chanid, CAN, 0, 0, 0, 7, 0, "\x0\x0\x3\xAB""LOL");
|
||||
|
||||
std::vector<panda::PANDA_CAN_MSG> msg_recv = panda_recv_loop(p, 4, 250);
|
||||
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid), _T("Failed to delete filter."), LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[0], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[1], 0, 0x3AB, FALSE, FALSE, "LOL", LINE_INFO());//Staggered write inbetween multiple scheduled TXs
|
||||
check_panda_can_msg(msg_recv[2], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
check_panda_can_msg(msg_recv[3], 0, 0x3AB, FALSE, FALSE, "HI", LINE_INFO());
|
||||
|
||||
auto timediff_2_0 = msg_recv[2].recv_time - msg_recv[0].recv_time;
|
||||
auto timediff_3_2 = msg_recv[3].recv_time - msg_recv[2].recv_time;
|
||||
|
||||
std::ostringstream stringStream1;
|
||||
stringStream1 << "times1: " << timediff_2_0 << ", " << timediff_3_2 << std::endl;
|
||||
Logger::WriteMessage(stringStream1.str().c_str());
|
||||
|
||||
Assert::IsTrue(timediff_2_0 > 90000);
|
||||
Assert::IsTrue(timediff_2_0 < 110000);
|
||||
Assert::IsTrue(timediff_3_2 > 90000);
|
||||
Assert::IsTrue(timediff_3_2 < 110000);
|
||||
|
||||
msg_recv = panda_recv_loop(p, 0, 300);
|
||||
}
|
||||
|
||||
TEST_METHOD(J2534_CAN_BaudInvalid)
|
||||
{
|
||||
unsigned long chanid;
|
||||
|
@ -686,17 +837,17 @@ namespace pandaJ2534DLLTest
|
|||
auto timediff_5_4 = panda_msg_recv[5].recv_time - panda_msg_recv[4].recv_time;
|
||||
auto timediff_6_5 = panda_msg_recv[6].recv_time - panda_msg_recv[5].recv_time;
|
||||
|
||||
std::ostringstream stringStream1;
|
||||
stringStream1 << "times1: " << timediff_1_0 << ", " << timediff_2_1 << ", " << timediff_3_2 <<
|
||||
", " << timediff_4_3 << ", " << timediff_5_4 << ", " << timediff_6_5 << std::endl;
|
||||
Logger::WriteMessage(stringStream1.str().c_str());
|
||||
|
||||
Assert::IsTrue(timediff_1_0 > 10000);
|
||||
Assert::IsTrue(timediff_2_1 > 10000);
|
||||
Assert::IsTrue(timediff_3_2 > 10000);
|
||||
Assert::IsTrue(timediff_4_3 > 10000);
|
||||
Assert::IsTrue(timediff_5_4 > 10000);
|
||||
Assert::IsTrue(timediff_6_5 > 10000);
|
||||
|
||||
std::ostringstream stringStream1;
|
||||
stringStream1 << "times1: " << timediff_1_0 << ", " << timediff_2_1 << ", " << timediff_3_2 <<
|
||||
", " << timediff_4_3 << ", " << timediff_5_4 << ", " << timediff_6_5 << std::endl;
|
||||
Logger::WriteMessage(stringStream1.str().c_str());
|
||||
}
|
||||
|
||||
//Check that tx works for messages with more than 16 frames. 29 bit. Good Filter. NoPadding. STD address. Large multiframe message.
|
||||
|
@ -819,7 +970,7 @@ namespace pandaJ2534DLLTest
|
|||
J2534_send_msg_checked(chanid, ISO15765, 0, CAN_29BIT_ID, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
|
||||
|
||||
auto panda_msg_recv = panda_recv_loop(p, 1);
|
||||
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x10\x30""AABBCC", LINE_INFO()); //First Frame. Not replying so it needs to time out.
|
||||
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x10\x30""AABBCC", LINE_INFO());
|
||||
|
||||
panda_msg_recv = checked_panda_send(p, 0x18DAF1EF, TRUE, "\x30\x06\x7F", 3, 6, LINE_INFO(), 3000);//Start a conversation... but slow. FC timeout is 250 ms.
|
||||
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x21""DDEEFFG", LINE_INFO());//Check this convo doesn't trigger that timeout.
|
||||
|
@ -834,6 +985,88 @@ namespace pandaJ2534DLLTest
|
|||
check_J2534_can_msg(j2534_msg_recv[1], ISO15765, CAN_29BIT_ID | TX_MSG_TYPE, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
|
||||
}
|
||||
|
||||
//Check MF tx can be sent along side of a periodic message. 29 bit. Good Filter. NoPadding. STD address. Long STmin, checks that MF tx and periodic TX don't break each other.
|
||||
TEST_METHOD(J2534_ISO15765_SuccessTx_29b_Filter_NoPad_STD_SLOWMF_WithPeriodicMsg)
|
||||
{
|
||||
auto chanid = J2534_open_and_connect("", ISO15765, CAN_29BIT_ID, 500000, LINE_INFO());
|
||||
J2534_set_flowctrl_filter(chanid, CAN_29BIT_ID, 4, "\xff\xff\xff\xff", "\x18\xda\xf1\xef", "\x18\xda\xef\xf1", LINE_INFO());
|
||||
write_ioctl(chanid, LOOPBACK, TRUE, LINE_INFO());
|
||||
auto p = getPanda(500);
|
||||
|
||||
//Timing diagram of this test.
|
||||
//* is a periodic msg transfer; F is first frame, L is Flow control, C is Consecutive Frame.
|
||||
// *~~~~~~~*~~~~~~~*~~~~~~~* (The alignment here is unimportant. The exact order is not checked.
|
||||
//F C----C----C----C----C----C (100 ms between Cs)
|
||||
// L
|
||||
|
||||
auto msgid = J2534_start_periodic_msg_checked(chanid, ISO15765, CAN_29BIT_ID, 6, 0, "\x18\xda\xef\xf1""HI", 130, LINE_INFO());
|
||||
J2534_send_msg_checked(chanid, ISO15765, 0, CAN_29BIT_ID, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
|
||||
|
||||
auto panda_msg_recv = panda_recv_loop(p, 2);
|
||||
check_panda_can_msg(panda_msg_recv[0], 0, 0x18DAEFF1, TRUE, FALSE, "\x02""HI", LINE_INFO());
|
||||
check_panda_can_msg(panda_msg_recv[1], 0, 0x18DAEFF1, TRUE, FALSE, "\x10\x30""AABBCC", LINE_INFO());
|
||||
|
||||
Assert::IsTrue(p->can_send(0x18DAF1EF, TRUE, (const uint8_t*)"\x30\x06\x64", 3, panda::PANDA_CAN1), _T("Panda send says it failed."), LINE_INFO());
|
||||
|
||||
Timer t_permsg = Timer();
|
||||
Timer t_MFmsg = Timer();
|
||||
unsigned int MFframesReceived = 0;
|
||||
unsigned int PeriodicMsgReceived = 0;
|
||||
std::array<std::string, 6> const mfMsgExpectedParts{ "\x21""DDEEFFG", "\x22""GHHIIJJ", "\x23""KKLLMMN", "\x24""NOOPPQQ", "\x25""RRSSTTU", "\x26""UVVWWXX" };
|
||||
|
||||
while (TRUE) {
|
||||
std::vector<panda::PANDA_CAN_MSG>msg_recv = p->can_recv();
|
||||
for (auto msg : msg_recv) {
|
||||
if (msg.is_receipt) continue;
|
||||
if ((msg.dat[0] & 0xf0) == 0x20) {
|
||||
Assert::AreEqual<std::string>(mfMsgExpectedParts[MFframesReceived], std::string((const char*)msg.dat, msg.len), _T("Got wrong part of MF msg."), LINE_INFO());
|
||||
MFframesReceived++;
|
||||
t_MFmsg.reset();
|
||||
} else if (std::string((const char*)msg.dat, msg.len) == "\x02HI") {
|
||||
PeriodicMsgReceived++;
|
||||
t_permsg.reset();
|
||||
} else {
|
||||
Assert::IsTrue(FALSE, _T("Got impossible message. Something is very wrong. Check other tests."), LINE_INFO());
|
||||
}
|
||||
}
|
||||
|
||||
if (MFframesReceived >= 6) break;
|
||||
Assert::IsTrue(300 > t_permsg.getTimePassed(), _T("Timed out waiting for periodic msessage frame."), LINE_INFO());
|
||||
Assert::IsTrue(300 > t_MFmsg.getTimePassed(), _T("Timed out waiting for multiframe msessage frame."), LINE_INFO());
|
||||
|
||||
if (msg_recv.size() == 0)
|
||||
Sleep(10);
|
||||
}
|
||||
|
||||
Assert::AreEqual<long>(STATUS_NOERROR, PassThruStopPeriodicMsg(chanid, msgid), _T("Failed to delete filter."), LINE_INFO());
|
||||
|
||||
Assert::IsTrue(PeriodicMsgReceived > 3, _T("Did not receive enough periodic messages. Likely canceled or delayed."), LINE_INFO());
|
||||
|
||||
std::ostringstream stringStream;
|
||||
stringStream << "PeriodicMsgReceived = " << PeriodicMsgReceived << std::endl;
|
||||
Logger::WriteMessage(stringStream.str().c_str());
|
||||
|
||||
unsigned int periodicTxIndicationCount = 0;
|
||||
unsigned int TxIndicationCount = 0;
|
||||
auto j2534_msg_recv = j2534_recv_loop(chanid, 2 + (PeriodicMsgReceived * 2));
|
||||
for (int i = 0; i < PeriodicMsgReceived + 1; i++) {
|
||||
check_J2534_can_msg(j2534_msg_recv[(i * 2) + 0], ISO15765, CAN_29BIT_ID | TX_INDICATION, 0, 4, 0, "\x18\xda\xef\xf1", LINE_INFO());
|
||||
switch (j2534_msg_recv[(i * 2) + 1].DataSize) {
|
||||
case 6:
|
||||
check_J2534_can_msg(j2534_msg_recv[(i * 2) + 1], ISO15765, CAN_29BIT_ID | TX_MSG_TYPE, 0, 4 + 2, 0, "\x18\xda\xef\xf1""HI", LINE_INFO());
|
||||
break;
|
||||
case 4 + 48:
|
||||
check_J2534_can_msg(j2534_msg_recv[(i * 2) + 1], ISO15765, CAN_29BIT_ID | TX_MSG_TYPE, 0, 4 + 48, 0, "\x18\xda\xef\xf1""AABBCCDDEEFFGGHHIIJJKKLLMMNNOOPPQQRRSSTTUUVVWWXX", LINE_INFO());
|
||||
break;
|
||||
default:
|
||||
Assert::IsTrue(FALSE, _T("Got unexpected data!"), LINE_INFO());
|
||||
}
|
||||
}
|
||||
|
||||
Assert::AreNotEqual<unsigned int>(PeriodicMsgReceived, periodicTxIndicationCount, _T("Wrong number of periodic msgs reported by passthru device."), LINE_INFO());
|
||||
Assert::AreNotEqual<unsigned int>(1, TxIndicationCount, _T("Wrong number of TX msgs reported by passthru device."), LINE_INFO());
|
||||
}
|
||||
|
||||
///////////////////// Tests checking things break or recover during send/receive /////////////////////
|
||||
|
||||
//Check rx FAILS when frame is dropped. 29 bit. Good Filter. NoPadding. STD address. Multi Frame.
|
||||
|
|
|
@ -10,3 +10,5 @@
|
|||
// Headers for CppUnitTest
|
||||
#include "CppUnitTest.h"
|
||||
#include <iomanip> //Used for formatting in TestHelpers.cpp
|
||||
#include <string>
|
||||
#include <array>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,12 @@ J2534Connection::J2534Connection(
|
|||
unsigned long BaudRate
|
||||
) : panda_dev(panda_dev), ProtocolID(ProtocolID), Flags(Flags), BaudRate(BaudRate), port(0) { }
|
||||
|
||||
unsigned long J2534Connection::validateTxMsg(PASSTHRU_MSG* msg) {
|
||||
if (msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen())
|
||||
return ERR_INVALID_MSG;
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
|
||||
long J2534Connection::PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) {
|
||||
//Timeout of 0 means return immediately. Non zero means WAIT for that time then return. Dafuk.
|
||||
long err_code = STATUS_NOERROR;
|
||||
|
@ -22,17 +28,17 @@ long J2534Connection::PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMs
|
|||
}
|
||||
|
||||
//Synchronized won't work where we have to break out of a loop
|
||||
message_access_lock.lock();
|
||||
if (this->messages.empty()) {
|
||||
message_access_lock.unlock();
|
||||
messageRxBuff_mutex.lock();
|
||||
if (this->messageRxBuff.empty()) {
|
||||
messageRxBuff_mutex.unlock();
|
||||
if (Timeout == 0)
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto msg_in = this->messages.front();
|
||||
this->messages.pop();
|
||||
message_access_lock.unlock();
|
||||
auto msg_in = this->messageRxBuff.front();
|
||||
this->messageRxBuff.pop();
|
||||
messageRxBuff_mutex.unlock();
|
||||
|
||||
PASSTHRU_MSG *msg_out = &pMsg[msgnum++];
|
||||
msg_out->ProtocolID = this->ProtocolID;
|
||||
|
@ -50,9 +56,60 @@ long J2534Connection::PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMs
|
|||
*pNumMsgs = msgnum;
|
||||
return err_code;
|
||||
}
|
||||
long J2534Connection::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) { return STATUS_NOERROR; }
|
||||
long J2534Connection::PassThruStartPeriodicMsg(PASSTHRU_MSG *pMsg, unsigned long *pMsgID, unsigned long TimeInterval) { return STATUS_NOERROR; }
|
||||
long J2534Connection::PassThruStopPeriodicMsg(unsigned long MsgID) { return STATUS_NOERROR; }
|
||||
|
||||
long J2534Connection::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) {
|
||||
//There doesn't seem to be much reason to implement the timeout here.
|
||||
for (int msgnum = 0; msgnum < *pNumMsgs; msgnum++) {
|
||||
PASSTHRU_MSG* msg = &pMsg[msgnum];
|
||||
if (msg->ProtocolID != this->ProtocolID) {
|
||||
*pNumMsgs = msgnum;
|
||||
return ERR_MSG_PROTOCOL_ID;
|
||||
}
|
||||
|
||||
auto retcode = this->validateTxMsg(msg);
|
||||
if (retcode != STATUS_NOERROR) {
|
||||
*pNumMsgs = msgnum;
|
||||
return retcode;
|
||||
}
|
||||
|
||||
auto msgtx = this->parseMessageTx(*pMsg);
|
||||
if (msgtx != nullptr) //Nullptr is supported for unimplemented connection types.
|
||||
this->schedultMsgTx(std::dynamic_pointer_cast<Action>(msgtx));
|
||||
}
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
|
||||
//The docs say that a device has to support 10 periodic messages, though more is ok.
|
||||
//It is easier to store them on the connection, so 10 per connection it is.
|
||||
long J2534Connection::PassThruStartPeriodicMsg(PASSTHRU_MSG *pMsg, unsigned long *pMsgID, unsigned long TimeInterval) {
|
||||
if (pMsg->DataSize < getMinMsgLen() || pMsg->DataSize > getMaxMsgSingleFrameLen()) return ERR_INVALID_MSG;
|
||||
if (pMsg->ProtocolID != this->ProtocolID) return ERR_MSG_PROTOCOL_ID;
|
||||
if (TimeInterval < 5 || TimeInterval > 65535) return ERR_INVALID_TIME_INTERVAL;
|
||||
|
||||
for (int i = 0; i < this->periodicMessages.size(); i++) {
|
||||
if (periodicMessages[i] != nullptr) continue;
|
||||
|
||||
*pMsgID = i;
|
||||
auto msgtx = this->parseMessageTx(*pMsg);
|
||||
if (msgtx != nullptr) {
|
||||
periodicMessages[i] = std::make_shared<MessagePeriodic>(std::chrono::microseconds(TimeInterval*1000), msgtx);
|
||||
periodicMessages[i]->scheduleImmediate();
|
||||
if (auto panda_dev = this->getPandaDev()) {
|
||||
panda_dev->insertActionIntoTaskList(periodicMessages[i]);
|
||||
}
|
||||
}
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
return ERR_EXCEEDED_LIMIT;
|
||||
}
|
||||
|
||||
long J2534Connection::PassThruStopPeriodicMsg(unsigned long MsgID) {
|
||||
if (MsgID >= this->periodicMessages.size() || this->periodicMessages[MsgID] == nullptr)
|
||||
return ERR_INVALID_MSG_ID;
|
||||
this->periodicMessages[MsgID]->cancel();
|
||||
this->periodicMessages[MsgID] = nullptr;
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
|
||||
long J2534Connection::PassThruStartMsgFilter(unsigned long FilterType, PASSTHRU_MSG *pMaskMsg, PASSTHRU_MSG *pPatternMsg,
|
||||
PASSTHRU_MSG *pFlowControlMsg, unsigned long *pFilterID) {
|
||||
|
@ -93,7 +150,9 @@ long J2534Connection::init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput) { return
|
|||
long J2534Connection::initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput) { return STATUS_NOERROR; }
|
||||
long J2534Connection::clearTXBuff() { return STATUS_NOERROR; }
|
||||
long J2534Connection::clearRXBuff() {
|
||||
this->messages = {};
|
||||
synchronized(messageRxBuff_mutex) {
|
||||
this->messageRxBuff = {};
|
||||
}
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
long J2534Connection::clearPeriodicMsgs() { return STATUS_NOERROR; }
|
||||
|
@ -124,13 +183,6 @@ void J2534Connection::rescheduleExistingTxMsgs() {
|
|||
}
|
||||
}
|
||||
|
||||
void J2534Connection::processMessageReceipt(const J2534Frame& msg) {
|
||||
//TX_MSG_TYPE should be set in RxStatus
|
||||
if (!check_bmask(msg.RxStatus, TX_MSG_TYPE)) return;
|
||||
if (this->loopback)
|
||||
addMsgToRxQueue(msg);
|
||||
}
|
||||
|
||||
//Works well as long as the protocol doesn't support flow control.
|
||||
void J2534Connection::processMessage(const J2534Frame& msg) {
|
||||
FILTER_RESULT filter_res = FILTER_RESULT_NEUTRAL;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "J2534Frame.h"
|
||||
#include "PandaJ2534Device.h"
|
||||
#include "J2534MessageFilter.h"
|
||||
#include "MessagePeriodic.h"
|
||||
|
||||
class J2534Frame;
|
||||
class Action;
|
||||
|
@ -25,7 +26,7 @@ public:
|
|||
);
|
||||
virtual ~J2534Connection() {};
|
||||
virtual long PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
|
||||
virtual long PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
|
||||
long PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
|
||||
virtual long PassThruStartPeriodicMsg(PASSTHRU_MSG *pMsg, unsigned long *pMsgID, unsigned long TimeInterval);
|
||||
virtual long PassThruStopPeriodicMsg(unsigned long MsgID);
|
||||
|
||||
|
@ -35,6 +36,10 @@ public:
|
|||
virtual long PassThruStopMsgFilter(unsigned long FilterID);
|
||||
virtual long PassThruIoctl(unsigned long IoctlID, void *pInput, void *pOutput);
|
||||
|
||||
virtual unsigned long validateTxMsg(PASSTHRU_MSG* msg);
|
||||
|
||||
virtual std::shared_ptr<MessageTx> parseMessageTx(PASSTHRU_MSG& msg) { return nullptr; };
|
||||
|
||||
long init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput);
|
||||
long initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput);
|
||||
long clearTXBuff();
|
||||
|
@ -59,7 +64,6 @@ public:
|
|||
return this->port;
|
||||
}
|
||||
|
||||
virtual void processMessageReceipt(const J2534Frame& msg);
|
||||
virtual void processMessage(const J2534Frame& msg);
|
||||
|
||||
virtual unsigned long getMinMsgLen() {
|
||||
|
@ -70,6 +74,10 @@ public:
|
|||
return 4128;
|
||||
}
|
||||
|
||||
virtual unsigned long getMaxMsgSingleFrameLen() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
void schedultMsgTx(std::shared_ptr<Action> msgout);
|
||||
|
||||
void rescheduleExistingTxMsgs();
|
||||
|
@ -81,8 +89,8 @@ public:
|
|||
}
|
||||
|
||||
void addMsgToRxQueue(const J2534Frame& frame) {
|
||||
synchronized(message_access_lock) {
|
||||
messages.push(frame);
|
||||
synchronized(messageRxBuff_mutex) {
|
||||
messageRxBuff.push(frame);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,12 +104,14 @@ protected:
|
|||
|
||||
std::weak_ptr<PandaJ2534Device> panda_dev;
|
||||
|
||||
std::queue<J2534Frame> messages;
|
||||
Mutex messageRxBuff_mutex;
|
||||
std::queue<J2534Frame> messageRxBuff;
|
||||
|
||||
std::array<std::shared_ptr<J2534MessageFilter>, 10> filters;
|
||||
std::queue<std::shared_ptr<Action>> txbuff;
|
||||
|
||||
std::array<std::shared_ptr<MessagePeriodic>, 10> periodicMessages;
|
||||
|
||||
private:
|
||||
Mutex message_access_lock;
|
||||
Mutex staged_writes_lock;
|
||||
};
|
||||
|
|
|
@ -17,22 +17,13 @@ J2534Connection_CAN::J2534Connection_CAN(
|
|||
panda_dev->panda->set_can_speed_cbps(panda::PANDA_CAN1, BaudRate/100);
|
||||
};
|
||||
|
||||
long J2534Connection_CAN::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) {
|
||||
//There doesn't seem to be much reason to implement the timeout here.
|
||||
for (int msgnum = 0; msgnum < *pNumMsgs; msgnum++) {
|
||||
PASSTHRU_MSG* msg = &pMsg[msgnum];
|
||||
if (msg->ProtocolID != this->ProtocolID) {
|
||||
*pNumMsgs = msgnum;
|
||||
return ERR_MSG_PROTOCOL_ID;
|
||||
}
|
||||
if (msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen() ||
|
||||
(val_is_29bit(msg->TxFlags) != this->_is_29bit() && !check_bmask(this->Flags, CAN_ID_BOTH))) {
|
||||
*pNumMsgs = msgnum;
|
||||
return ERR_INVALID_MSG;
|
||||
}
|
||||
|
||||
auto msgtx = std::make_shared<MessageTx_CAN>(shared_from_this(), *msg);
|
||||
this->schedultMsgTx(std::dynamic_pointer_cast<Action>(msgtx));
|
||||
}
|
||||
unsigned long J2534Connection_CAN::validateTxMsg(PASSTHRU_MSG* msg) {
|
||||
if ((msg->DataSize < this->getMinMsgLen() || msg->DataSize > this->getMaxMsgLen() ||
|
||||
(val_is_29bit(msg->TxFlags) != this->_is_29bit() && !check_bmask(this->Flags, CAN_ID_BOTH))))
|
||||
return ERR_INVALID_MSG;
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
|
||||
std::shared_ptr<MessageTx> J2534Connection_CAN::parseMessageTx(PASSTHRU_MSG& msg) {
|
||||
return std::dynamic_pointer_cast<MessageTx>(std::make_shared<MessageTx_CAN>(shared_from_this(), msg));
|
||||
}
|
||||
|
|
|
@ -14,7 +14,9 @@ public:
|
|||
unsigned long BaudRate
|
||||
);
|
||||
|
||||
virtual long PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
|
||||
virtual unsigned long validateTxMsg(PASSTHRU_MSG* msg);
|
||||
|
||||
virtual std::shared_ptr<MessageTx> parseMessageTx(PASSTHRU_MSG& pMsg);
|
||||
|
||||
virtual unsigned long getMinMsgLen() {
|
||||
return 4;
|
||||
|
@ -24,6 +26,10 @@ public:
|
|||
return 12;
|
||||
}
|
||||
|
||||
virtual unsigned long getMaxMsgSingleFrameLen() {
|
||||
return 12;
|
||||
}
|
||||
|
||||
virtual bool isProtoCan() {
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -18,35 +18,25 @@ J2534Connection_ISO15765::J2534Connection_ISO15765(
|
|||
panda_dev->panda->set_can_speed_cbps(panda::PANDA_CAN1, (uint16_t)(BaudRate / 100));
|
||||
}
|
||||
|
||||
long J2534Connection_ISO15765::PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) {
|
||||
for (unsigned int msgnum = 0; msgnum < *pNumMsgs; msgnum++) {
|
||||
PASSTHRU_MSG* msg = &pMsg[msgnum];
|
||||
unsigned long J2534Connection_ISO15765::validateTxMsg(PASSTHRU_MSG* msg) {
|
||||
if ((msg->DataSize < this->getMinMsgLen() + (msg_is_extaddr(msg) ? 1 : 0) ||
|
||||
msg->DataSize > this->getMaxMsgLen() + (msg_is_extaddr(msg) ? 1 : 0) ||
|
||||
(val_is_29bit(msg->TxFlags) != this->_is_29bit() && !check_bmask(this->Flags, CAN_ID_BOTH))))
|
||||
return ERR_INVALID_MSG;
|
||||
|
||||
if (msg->ProtocolID != this->ProtocolID) {
|
||||
*pNumMsgs = msgnum;
|
||||
return ERR_MSG_PROTOCOL_ID;
|
||||
}
|
||||
if (msg->DataSize < this->getMinMsgLen() + (msg_is_extaddr(msg) ? 1 : 0) ||
|
||||
msg->DataSize > this->getMaxMsgLen() + (msg_is_extaddr(msg) ? 1 : 0) ||
|
||||
(val_is_29bit(msg->TxFlags) != this->_is_29bit() && !check_bmask(this->Flags, CAN_ID_BOTH))) {
|
||||
*pNumMsgs = msgnum;
|
||||
return ERR_INVALID_MSG;
|
||||
}
|
||||
int fid = get_matching_out_fc_filter_id(std::string((const char*)msg->Data, msg->DataSize), msg->TxFlags, 0xFFFFFFFF);
|
||||
if (msg->DataSize > getMaxMsgSingleFrameLen() && fid == -1) return ERR_NO_FLOW_CONTROL; //11 bytes (4 for CANid, 7 payload) is max length of input frame.
|
||||
|
||||
int fid = get_matching_out_fc_filter_id(std::string((const char*)msg->Data, msg->DataSize), msg->TxFlags, 0xFFFFFFFF);
|
||||
if (msg->DataSize > 11 && fid == -1) return ERR_NO_FLOW_CONTROL; //11 bytes (4 for CANid, 7 payload) is max length of input frame.
|
||||
|
||||
auto msgtx = std::make_shared<MessageTx_ISO15765>( shared_from_this(), *msg, (fid == -1) ? nullptr : this->filters[fid] );
|
||||
this->schedultMsgTx(std::dynamic_pointer_cast<Action>(msgtx));
|
||||
}
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
|
||||
void J2534Connection_ISO15765::processMessageReceipt(const J2534Frame& msg) {
|
||||
if (msg.ProtocolID != CAN) return;
|
||||
std::shared_ptr<MessageTx> J2534Connection_ISO15765::parseMessageTx(PASSTHRU_MSG& msg) {
|
||||
int fid = get_matching_out_fc_filter_id(std::string((const char*)msg.Data, msg.DataSize), msg.TxFlags, 0xFFFFFFFF);
|
||||
if (msg.DataSize > getMaxMsgSingleFrameLen() && fid == -1) 1;
|
||||
|
||||
//TX_MSG_TYPE should be set in RxStatus
|
||||
if (!check_bmask(msg.RxStatus, TX_MSG_TYPE)) return;
|
||||
return std::dynamic_pointer_cast<MessageTx>(
|
||||
std::make_shared<MessageTx_ISO15765>(shared_from_this(), msg, (fid == -1) ? nullptr : this->filters[fid])
|
||||
);
|
||||
}
|
||||
|
||||
//https://happilyembedded.wordpress.com/2016/02/15/can-multiple-frame-transmission/
|
||||
|
@ -63,6 +53,8 @@ void J2534Connection_ISO15765::processMessage(const J2534Frame& msg) {
|
|||
switch (msg_get_type(msg, addrlen)) {
|
||||
case FRAME_FLOWCTRL:
|
||||
{
|
||||
if (this->txbuff.size() == 0)
|
||||
return;
|
||||
if (msg.Data.size() < addrlen + 3) return;
|
||||
uint8_t flow_status = msg.Data[addrlen] & 0x0F;
|
||||
uint8_t block_size = msg.Data[addrlen + 1];
|
||||
|
@ -79,6 +71,7 @@ void J2534Connection_ISO15765::processMessage(const J2534Frame& msg) {
|
|||
} else {
|
||||
break;
|
||||
}
|
||||
txConvo->scheduleImmediate();
|
||||
this->rescheduleExistingTxMsgs();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -21,15 +21,16 @@ public:
|
|||
unsigned long BaudRate
|
||||
);
|
||||
|
||||
virtual long PassThruWriteMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout);
|
||||
|
||||
virtual long PassThruStartMsgFilter(unsigned long FilterType, PASSTHRU_MSG * pMaskMsg, PASSTHRU_MSG * pPatternMsg, PASSTHRU_MSG * pFlowControlMsg, unsigned long * pFilterID);
|
||||
|
||||
int get_matching_out_fc_filter_id(const std::string & msgdata, unsigned long flags, unsigned long flagmask);
|
||||
|
||||
int get_matching_in_fc_filter_id(const J2534Frame& msg, unsigned long flagmask = CAN_29BIT_ID);
|
||||
|
||||
virtual void processMessageReceipt(const J2534Frame& msg);
|
||||
virtual unsigned long validateTxMsg(PASSTHRU_MSG* msg);
|
||||
|
||||
virtual std::shared_ptr<MessageTx> parseMessageTx(PASSTHRU_MSG& msg);
|
||||
|
||||
virtual void processMessage(const J2534Frame& msg);
|
||||
|
||||
virtual unsigned long getMinMsgLen() {
|
||||
|
@ -40,6 +41,10 @@ public:
|
|||
return 4099;
|
||||
};
|
||||
|
||||
virtual unsigned long getMaxMsgSingleFrameLen() {
|
||||
return 11;
|
||||
}
|
||||
|
||||
virtual bool _is_29bit() {
|
||||
return (this->Flags & CAN_29BIT_ID) == CAN_29BIT_ID;
|
||||
}
|
||||
|
|
|
@ -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 void reset() = 0;
|
||||
|
||||
protected:
|
||||
J2534Frame fullmsg;
|
||||
};
|
|
@ -2,8 +2,6 @@
|
|||
#include "MessageTx_CAN.h"
|
||||
#include "J2534Connection_CAN.h"
|
||||
|
||||
//class J2534Connection_CAN;
|
||||
|
||||
MessageTx_CAN::MessageTx_CAN(
|
||||
std::shared_ptr<J2534Connection> connection_in,
|
||||
PASSTHRU_MSG& to_send
|
||||
|
@ -32,7 +30,15 @@ BOOL MessageTx_CAN::checkTxReceipt(J2534Frame frame) {
|
|||
if (txReady()) return FALSE;
|
||||
if (frame.Data == fullmsg.Data && ((this->fullmsg.TxFlags & CAN_29BIT_ID) == (frame.RxStatus & CAN_29BIT_ID))) {
|
||||
txInFlight = FALSE;
|
||||
if (auto conn_sp = std::static_pointer_cast<J2534Connection_CAN>(this->connection.lock()))
|
||||
if (conn_sp->loopback)
|
||||
conn_sp->addMsgToRxQueue(frame);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void MessageTx_CAN::reset() {
|
||||
sentyet = FALSE;
|
||||
txInFlight = FALSE;
|
||||
}
|
||||
|
|
|
@ -25,6 +25,8 @@ public:
|
|||
return !sentyet;
|
||||
};
|
||||
|
||||
virtual void reset();
|
||||
|
||||
private:
|
||||
BOOL sentyet;
|
||||
BOOL txInFlight;
|
||||
|
|
|
@ -131,11 +131,21 @@ BOOL MessageTx_ISO15765::txReady() {
|
|||
return block_size > 0 || sendAll || this->frames_sent == 0;
|
||||
}
|
||||
|
||||
void MessageTx_ISO15765::reset() {
|
||||
frames_sent = 0;
|
||||
consumed_count = 0;
|
||||
block_size = 0;
|
||||
txInFlight = FALSE;
|
||||
sendAll = FALSE;
|
||||
numWaitFrames = 0;
|
||||
didtimeout = FALSE;
|
||||
}
|
||||
|
||||
void MessageTx_ISO15765::onTimeout() {
|
||||
didtimeout = TRUE;
|
||||
if (auto conn_sp = std::static_pointer_cast<J2534Connection_ISO15765>(this->connection.lock())) {
|
||||
if (auto panda_dev_sp = conn_sp->getPandaDev()) {
|
||||
panda_dev_sp->removeConnectionTopAction(conn_sp);
|
||||
panda_dev_sp->removeConnectionTopAction(conn_sp, shared_from_this());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -75,7 +75,7 @@ DWORD PandaJ2534Device::can_recv_thread() {
|
|||
J2534Frame msg_out(msg_in);
|
||||
|
||||
if (msg_in.is_receipt) {
|
||||
synchronized(activeTXs_mutex) {
|
||||
synchronized(task_queue_mutex) {
|
||||
if (txMsgsAwaitingEcho.size() > 0) {
|
||||
auto msgtx = txMsgsAwaitingEcho.front();
|
||||
if (auto conn = msgtx->connection.lock()) {
|
||||
|
@ -89,8 +89,7 @@ DWORD PandaJ2534Device::can_recv_thread() {
|
|||
txMsgsAwaitingEcho.pop(); //Remove the TX object and schedule record.
|
||||
|
||||
if (msgtx->isFinished()) {
|
||||
conn->processMessageReceipt(msg_out); //Alert the connection a tx is done.
|
||||
this->removeConnectionTopAction(conn);
|
||||
this->removeConnectionTopAction(conn, msgtx);
|
||||
} else {
|
||||
if (msgtx->txReady()) { //Not finished, ready to send next frame.
|
||||
msgtx->schedule(msg_in.recv_time_point, TRUE);
|
||||
|
@ -135,7 +134,7 @@ DWORD PandaJ2534Device::msg_tx_thread() {
|
|||
ResetEvent(this->flow_control_wakeup_event);
|
||||
|
||||
while (TRUE) {
|
||||
synchronized(activeTXs_mutex) { //implemented with for loop. Consumes breaks.
|
||||
synchronized(task_queue_mutex) { //implemented with for loop. Consumes breaks.
|
||||
if (this->task_queue.size() == 0) {
|
||||
sleepDuration = INFINITE;
|
||||
goto break_flow_ctrl_loop;
|
||||
|
@ -159,7 +158,7 @@ DWORD PandaJ2534Device::msg_tx_thread() {
|
|||
}
|
||||
|
||||
void PandaJ2534Device::insertActionIntoTaskList(std::shared_ptr<Action> action) {
|
||||
synchronized(activeTXs_mutex) {
|
||||
synchronized(task_queue_mutex) {
|
||||
auto iter = this->task_queue.begin();
|
||||
for (; iter != this->task_queue.end(); iter++) {
|
||||
if (action->expire < (*iter)->expire) break;
|
||||
|
@ -191,11 +190,14 @@ void PandaJ2534Device::unstallConnectionTx(std::shared_ptr<J2534Connection> conn
|
|||
if (ret.second == TRUE) return; //Conn already exists.
|
||||
this->insertActionIntoTaskList(conn->txbuff.front());
|
||||
}
|
||||
SetEvent(flow_control_wakeup_event);
|
||||
}
|
||||
|
||||
void PandaJ2534Device::removeConnectionTopAction(std::shared_ptr<J2534Connection> conn) {
|
||||
synchronized(activeTXs_mutex) {
|
||||
void PandaJ2534Device::removeConnectionTopAction(std::shared_ptr<J2534Connection> conn, std::shared_ptr<MessageTx> msg) {
|
||||
synchronized(task_queue_mutex) {
|
||||
if (conn->txbuff.size() == 0)
|
||||
return;
|
||||
if (conn->txbuff.front() != msg)
|
||||
return;
|
||||
conn->txbuff.pop(); //Remove the top TX message from the connection tx queue.
|
||||
|
||||
//Remove the connection from the active connection list if no more messages are scheduled with this connection.
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
|
||||
void unstallConnectionTx(std::shared_ptr<J2534Connection> conn);
|
||||
|
||||
void removeConnectionTopAction(std::shared_ptr<J2534Connection> conn);
|
||||
void removeConnectionTopAction(std::shared_ptr<J2534Connection> conn, std::shared_ptr<MessageTx> msg);
|
||||
|
||||
std::queue<std::shared_ptr<MessageTx>> txMsgsAwaitingEcho;
|
||||
|
||||
|
@ -57,7 +57,7 @@ private:
|
|||
}
|
||||
DWORD msg_tx_thread();
|
||||
std::list<std::shared_ptr<Action>> task_queue;
|
||||
Mutex activeTXs_mutex;
|
||||
Mutex task_queue_mutex;
|
||||
|
||||
std::queue<std::shared_ptr<J2534Connection>> ConnTxQueue;
|
||||
std::set<std::shared_ptr<J2534Connection>> ConnTxSet;
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
<ClInclude Include="..\panda\panda.h" />
|
||||
<ClInclude Include="constants_ISO15765.h" />
|
||||
<ClInclude Include="dllmain.h" />
|
||||
<ClInclude Include="MessagePeriodic.h" />
|
||||
<ClInclude Include="MessageRx.h" />
|
||||
<ClInclude Include="J2534Connection.h" />
|
||||
<ClInclude Include="J2534Connection_CAN.h" />
|
||||
|
@ -122,6 +123,7 @@
|
|||
<ClCompile Include="J2534Connection_CAN.cpp" />
|
||||
<ClCompile Include="J2534Connection_ISO15765.cpp" />
|
||||
<ClCompile Include="J2534MessageFilter.cpp" />
|
||||
<ClCompile Include="MessagePeriodic.cpp" />
|
||||
<ClCompile Include="MessageTxTimeout.cpp" />
|
||||
<ClCompile Include="MessageTx_CAN.cpp" />
|
||||
<ClCompile Include="MessageTx_ISO15765.cpp" />
|
||||
|
@ -141,6 +143,9 @@
|
|||
<ItemGroup>
|
||||
<ResourceCompile Include="pandaJ2534DLL.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ClassDiagram.cd" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
|
|
|
@ -99,6 +99,9 @@
|
|||
<ClInclude Include="MessageTx.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MessagePeriodic.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="pandaJ2534DLL.cpp">
|
||||
|
@ -137,10 +140,16 @@
|
|||
<ClCompile Include="MessageTx_CAN.cpp">
|
||||
<Filter>Source Files\J2534_CAN</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MessagePeriodic.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="pandaJ2534DLL.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ClassDiagram.cd" />
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue