fix HDS issues
parent
8203cc8e59
commit
2e99dbf34a
|
@ -1,7 +1,7 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.25420.1
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.27004.2010
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pandaJ2534DLL", "pandaJ2534DLL\pandaJ2534DLL.vcxproj", "{A2BB18A5-F26B-48D6-BBB5-B83D64473C77}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
|
@ -24,6 +24,9 @@ EndProject
|
|||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ECUsim CLI", "ECUsim CLI\ECUsim CLI.vcxproj", "{D99E2FCD-21A4-4065-949A-31E34E0E69D1}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(Performance) = preSolution
|
||||
HasPerformanceSessions = true
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
|
@ -87,4 +90,7 @@ Global
|
|||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {8AF3826E-406A-4F1C-BA80-B4D7FD4B52E1}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -13,13 +13,6 @@
|
|||
|
||||
using namespace panda;
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct _PANDA_CAN_MSG_INTERNAL {
|
||||
uint32_t rir;
|
||||
uint32_t f2;
|
||||
uint8_t dat[8];
|
||||
} PANDA_CAN_MSG_INTERNAL;
|
||||
|
||||
Panda::Panda(
|
||||
WINUSB_INTERFACE_HANDLE WinusbHandle,
|
||||
HANDLE DeviceHandle,
|
||||
|
@ -28,6 +21,7 @@ Panda::Panda(
|
|||
) : usbh(WinusbHandle), devh(DeviceHandle), devPath(devPath_), sn(sn_) {
|
||||
printf("CREATED A PANDA %s\n", this->sn.c_str());
|
||||
this->set_can_loopback(FALSE);
|
||||
this->set_raw_io(TRUE);
|
||||
this->set_alt_setting(0);
|
||||
}
|
||||
|
||||
|
@ -167,7 +161,8 @@ bool Panda::set_alt_setting(UCHAR alt_setting) {
|
|||
this->set_can_loopback(TRUE);
|
||||
Sleep(20); // Give time for any sent messages to appear in the RX buffer.
|
||||
this->can_clear(PANDA_CAN_RX);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// send 4 messages becaus can_recv reads 4 messages at a time
|
||||
for (int i = 0; i < 4; i++) {
|
||||
printf("Sending PAD %d\n", i);
|
||||
if (this->can_send(0x7FF, FALSE, {}, 0, PANDA_CAN1) == FALSE) {
|
||||
auto err = GetLastError();
|
||||
|
@ -177,14 +172,8 @@ bool Panda::set_alt_setting(UCHAR alt_setting) {
|
|||
Sleep(10);
|
||||
//this->can_clear(PANDA_CAN_RX);
|
||||
|
||||
std::vector<PANDA_CAN_MSG> msg_recv;
|
||||
if (alt_setting == 1) {
|
||||
//Read the messages so they do not contaimnate the real message stream.
|
||||
auto err = this->can_recv_async(NULL, msg_recv, 1000);
|
||||
}
|
||||
else {
|
||||
msg_recv = this->can_recv();
|
||||
}
|
||||
//Read the messages so they do not contaimnate the real message stream.
|
||||
this->can_recv();
|
||||
|
||||
//this->set_can_loopback(FALSE);
|
||||
this->set_can_loopback(loopback_backup);
|
||||
|
@ -203,6 +192,17 @@ UCHAR Panda::get_current_alt_setting() {
|
|||
return alt_setting;
|
||||
}
|
||||
|
||||
bool Panda::set_raw_io(bool val) {
|
||||
UCHAR raw_io = val;
|
||||
if (!WinUsb_SetPipePolicy(this->usbh, 0x81, RAW_IO, sizeof(raw_io), &raw_io)) {
|
||||
_tprintf(_T(" Error setting usb raw I/O pipe policy %d, Msg: '%s'\n"),
|
||||
GetLastError(), GetLastErrorAsString().c_str());
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PANDA_HEALTH Panda::get_health()
|
||||
{
|
||||
WINUSB_SETUP_PACKET SetupPacket;
|
||||
|
@ -351,69 +351,84 @@ bool Panda::can_send(uint32_t addr, bool addr_29b, const uint8_t *dat, uint8_t l
|
|||
return this->can_send_many(std::vector<PANDA_CAN_MSG>{msg});
|
||||
}
|
||||
|
||||
void Panda::parse_can_recv(std::vector<PANDA_CAN_MSG>& msg_recv, char *buff, int retcount) {
|
||||
for (int i = 0; i < retcount; i += sizeof(PANDA_CAN_MSG_INTERNAL)) {
|
||||
PANDA_CAN_MSG_INTERNAL *in_msg_raw = (PANDA_CAN_MSG_INTERNAL *)(buff + i);
|
||||
PANDA_CAN_MSG in_msg;
|
||||
PANDA_CAN_MSG Panda::parse_can_recv(PANDA_CAN_MSG_INTERNAL *in_msg_raw) {
|
||||
PANDA_CAN_MSG in_msg;
|
||||
|
||||
in_msg.addr_29b = (bool)(in_msg_raw->rir & CAN_EXTENDED);
|
||||
in_msg.addr = (in_msg.addr_29b) ? (in_msg_raw->rir >> 3) : (in_msg_raw->rir >> 21);
|
||||
in_msg.recv_time = this->runningTime.getTimePassedUS();
|
||||
in_msg.recv_time_point = std::chrono::steady_clock::now();
|
||||
//The timestamp from the device is (in_msg_raw->f2 >> 16),
|
||||
//but this 16 bit value is a little hard to use. Using a
|
||||
//timer since the initialization of this device.
|
||||
in_msg.len = in_msg_raw->f2 & 0xF;
|
||||
memcpy(in_msg.dat, in_msg_raw->dat, 8);
|
||||
in_msg.addr_29b = (bool)(in_msg_raw->rir & CAN_EXTENDED);
|
||||
in_msg.addr = (in_msg.addr_29b) ? (in_msg_raw->rir >> 3) : (in_msg_raw->rir >> 21);
|
||||
in_msg.recv_time = this->runningTime.getTimePassedUS();
|
||||
in_msg.recv_time_point = std::chrono::steady_clock::now();
|
||||
//The timestamp from the device is (in_msg_raw->f2 >> 16),
|
||||
//but this 16 bit value is a little hard to use. Using a
|
||||
//timer since the initialization of this device.
|
||||
in_msg.len = in_msg_raw->f2 & 0xF;
|
||||
memcpy(in_msg.dat, in_msg_raw->dat, 8);
|
||||
|
||||
in_msg.is_receipt = ((in_msg_raw->f2 >> 4) & 0x80) == 0x80;
|
||||
switch ((in_msg_raw->f2 >> 4) & 0x7F) {
|
||||
case PANDA_CAN1:
|
||||
in_msg.bus = PANDA_CAN1;
|
||||
break;
|
||||
case PANDA_CAN2:
|
||||
in_msg.bus = PANDA_CAN2;
|
||||
break;
|
||||
case PANDA_CAN3:
|
||||
in_msg.bus = PANDA_CAN3;
|
||||
break;
|
||||
default:
|
||||
in_msg.bus = PANDA_CAN_UNK;
|
||||
}
|
||||
msg_recv.push_back(in_msg);
|
||||
in_msg.is_receipt = ((in_msg_raw->f2 >> 4) & 0x80) == 0x80;
|
||||
switch ((in_msg_raw->f2 >> 4) & 0x7F) {
|
||||
case PANDA_CAN1:
|
||||
in_msg.bus = PANDA_CAN1;
|
||||
break;
|
||||
case PANDA_CAN2:
|
||||
in_msg.bus = PANDA_CAN2;
|
||||
break;
|
||||
case PANDA_CAN3:
|
||||
in_msg.bus = PANDA_CAN3;
|
||||
break;
|
||||
default:
|
||||
in_msg.bus = PANDA_CAN_UNK;
|
||||
}
|
||||
return in_msg;
|
||||
}
|
||||
|
||||
bool Panda::can_recv_async(HANDLE kill_event, std::vector<PANDA_CAN_MSG>& msg_buff, DWORD timeoutms) {
|
||||
int retcount;
|
||||
char buff[sizeof(PANDA_CAN_MSG_INTERNAL) * 4];
|
||||
bool Panda::can_rx_q_push(HANDLE kill_event, DWORD timeoutms) {
|
||||
while (1) {
|
||||
auto w_ptr = this->w_ptr;
|
||||
auto n_ptr = w_ptr + 1;
|
||||
if (n_ptr == CAN_RX_QUEUE_LEN) {
|
||||
n_ptr = 0;
|
||||
}
|
||||
|
||||
// Overlapped structure required for async read.
|
||||
HANDLE m_hReadFinishedEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||
OVERLAPPED m_overlappedData;
|
||||
memset(&m_overlappedData, sizeof(OVERLAPPED), 0);
|
||||
m_overlappedData.hEvent = m_hReadFinishedEvent;
|
||||
// Pause if there is not a slot available in the queue
|
||||
if (n_ptr == this->r_ptr) {
|
||||
printf("RX queue full!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
HANDLE phSignals[2] = { m_hReadFinishedEvent, kill_event };
|
||||
if (this->can_rx_q[n_ptr].complete) {
|
||||
// TODO: is ResetEvent() faster?
|
||||
CloseHandle(this->can_rx_q[n_ptr].complete);
|
||||
}
|
||||
|
||||
if (!WinUsb_ReadPipe(this->usbh, 0x81, (PUCHAR)buff, sizeof(buff), (PULONG)&retcount, &m_overlappedData)) {
|
||||
// An overlapped read will return true if done, or false with an
|
||||
// error of ERROR_IO_PENDING if the transfer is still in process.
|
||||
DWORD dwError = GetLastError();
|
||||
if (dwError == ERROR_IO_PENDING) {
|
||||
dwError = WaitForMultipleObjects(kill_event ? 2 : 1, phSignals, FALSE, timeoutms);
|
||||
// Overlapped structure required for async read.
|
||||
this->can_rx_q[n_ptr].complete = CreateEvent(NULL, TRUE, TRUE, NULL);
|
||||
memset(&this->can_rx_q[n_ptr].overlapped, sizeof(OVERLAPPED), 0);
|
||||
this->can_rx_q[n_ptr].overlapped.hEvent = this->can_rx_q[n_ptr].complete;
|
||||
this->can_rx_q[n_ptr].error = 0;
|
||||
|
||||
if (!WinUsb_ReadPipe(this->usbh, 0x81, this->can_rx_q[n_ptr].data, sizeof(this->can_rx_q[n_ptr].data), &this->can_rx_q[n_ptr].count, &this->can_rx_q[n_ptr].overlapped)) {
|
||||
// An overlapped read will return true if done, or false with an
|
||||
// error of ERROR_IO_PENDING if the transfer is still in process.
|
||||
this->can_rx_q[n_ptr].error = GetLastError();
|
||||
}
|
||||
|
||||
// Process the pipe read call from the previous invocation of this function
|
||||
if (this->can_rx_q[w_ptr].error == ERROR_IO_PENDING) {
|
||||
HANDLE phSignals[2] = { this->can_rx_q[w_ptr].complete, kill_event };
|
||||
auto dwError = WaitForMultipleObjects(kill_event ? 2 : 1, phSignals, FALSE, timeoutms);
|
||||
|
||||
// Check if packet, timeout (nope), or break
|
||||
if (dwError == WAIT_OBJECT_0) {
|
||||
// Signal came from our usb object. Read the returned data.
|
||||
if (!GetOverlappedResult(this->usbh, &m_overlappedData, (PULONG)&retcount, FALSE)) {
|
||||
if (!GetOverlappedResult(this->usbh, &this->can_rx_q[w_ptr].overlapped, &this->can_rx_q[w_ptr].count, TRUE)) {
|
||||
// TODO: handle other error cases better.
|
||||
dwError = GetLastError();
|
||||
printf("Got overlap error %d\n", dwError);
|
||||
|
||||
return TRUE;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
WinUsb_AbortPipe(this->usbh, 0x81);
|
||||
|
||||
// Return FALSE to show that the optional signal
|
||||
|
@ -422,17 +437,39 @@ bool Panda::can_recv_async(HANDLE kill_event, std::vector<PANDA_CAN_MSG>& msg_bu
|
|||
if (dwError == (WAIT_OBJECT_0 + 1)) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
continue;
|
||||
}
|
||||
} else { // ERROR_BAD_COMMAND happens when device is unplugged.
|
||||
}
|
||||
else if (this->can_rx_q[w_ptr].error != 0) { // ERROR_BAD_COMMAND happens when device is unplugged.
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
this->w_ptr = n_ptr;
|
||||
}
|
||||
|
||||
parse_can_recv(msg_buff, buff, retcount);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void Panda::can_rx_q_pop(PANDA_CAN_MSG msg_out[], int &count) {
|
||||
count = 0;
|
||||
|
||||
// No data left in queue
|
||||
if (this->r_ptr == this->w_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto r_ptr = this->r_ptr;
|
||||
for (int i = 0; i < this->can_rx_q[r_ptr].count; i += sizeof(PANDA_CAN_MSG_INTERNAL)) {
|
||||
auto in_msg_raw = (PANDA_CAN_MSG_INTERNAL *)(this->can_rx_q[r_ptr].data + i);
|
||||
msg_out[count] = parse_can_recv(in_msg_raw);
|
||||
++count;
|
||||
}
|
||||
|
||||
// Advance read pointer (wrap around if needed)
|
||||
++r_ptr;
|
||||
this->r_ptr = (r_ptr == CAN_RX_QUEUE_LEN ? 0 : r_ptr);
|
||||
}
|
||||
|
||||
std::vector<PANDA_CAN_MSG> Panda::can_recv() {
|
||||
std::vector<PANDA_CAN_MSG> msg_recv;
|
||||
int retcount;
|
||||
|
@ -441,7 +478,11 @@ std::vector<PANDA_CAN_MSG> Panda::can_recv() {
|
|||
if (this->bulk_read(0x81, buff, sizeof(buff), (PULONG)&retcount, 0) == FALSE)
|
||||
return msg_recv;
|
||||
|
||||
parse_can_recv(msg_recv, buff, retcount);
|
||||
for (int i = 0; i < retcount; i += sizeof(PANDA_CAN_MSG_INTERNAL)) {
|
||||
PANDA_CAN_MSG_INTERNAL *in_msg_raw = (PANDA_CAN_MSG_INTERNAL *)(buff + i);
|
||||
auto in_msg = parse_can_recv(in_msg_raw);
|
||||
msg_recv.push_back(in_msg);
|
||||
}
|
||||
|
||||
return msg_recv;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
#endif
|
||||
|
||||
#define LIN_MSG_MAX_LEN 10
|
||||
#define CAN_RX_QUEUE_LEN 10000
|
||||
#define CAN_RX_MSG_LEN 1000
|
||||
|
||||
//template class __declspec(dllexport) std::basic_string<char>;
|
||||
|
||||
|
@ -139,6 +141,7 @@ namespace panda {
|
|||
std::string get_usb_sn();
|
||||
bool set_alt_setting(UCHAR alt_setting);
|
||||
UCHAR get_current_alt_setting();
|
||||
bool Panda::set_raw_io(bool val);
|
||||
|
||||
PANDA_HEALTH get_health();
|
||||
bool enter_bootloader();
|
||||
|
@ -160,9 +163,9 @@ namespace panda {
|
|||
|
||||
bool can_send_many(const std::vector<PANDA_CAN_MSG>& can_msgs);
|
||||
bool can_send(uint32_t addr, bool addr_29b, const uint8_t *dat, uint8_t len, PANDA_CAN_PORT bus);
|
||||
void parse_can_recv(std::vector<PANDA_CAN_MSG>& msg_recv, char *buff, int retcount);
|
||||
bool can_recv_async(HANDLE kill_event, std::vector<PANDA_CAN_MSG>& msg_buff, DWORD timeoutms = INFINITE);
|
||||
std::vector<PANDA_CAN_MSG> can_recv();
|
||||
bool can_rx_q_push(HANDLE kill_event, DWORD timeoutms = INFINITE);
|
||||
void can_rx_q_pop(PANDA_CAN_MSG msg_out[], int &count);
|
||||
bool can_clear(PANDA_CAN_PORT_CLEAR bus);
|
||||
|
||||
std::string serial_read(PANDA_SERIAL_PORT port_number);
|
||||
|
@ -202,6 +205,23 @@ namespace panda {
|
|||
ULONG timeout
|
||||
);
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct _PANDA_CAN_MSG_INTERNAL {
|
||||
uint32_t rir;
|
||||
uint32_t f2;
|
||||
uint8_t dat[8];
|
||||
} PANDA_CAN_MSG_INTERNAL;
|
||||
|
||||
typedef struct _CAN_RX_PIPE_READ {
|
||||
unsigned char data[sizeof(PANDA_CAN_MSG_INTERNAL) * CAN_RX_MSG_LEN];
|
||||
unsigned long count;
|
||||
OVERLAPPED overlapped;
|
||||
HANDLE complete;
|
||||
DWORD error;
|
||||
} CAN_RX_PIPE_READ;
|
||||
|
||||
PANDA_CAN_MSG parse_can_recv(PANDA_CAN_MSG_INTERNAL *in_msg_raw);
|
||||
|
||||
WINUSB_INTERFACE_HANDLE usbh;
|
||||
HANDLE devh;
|
||||
tstring devPath;
|
||||
|
@ -209,6 +229,9 @@ namespace panda {
|
|||
bool loopback;
|
||||
|
||||
Timer runningTime;
|
||||
CAN_RX_PIPE_READ can_rx_q[CAN_RX_QUEUE_LEN];
|
||||
unsigned long w_ptr = 0;
|
||||
unsigned long r_ptr = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ long J2534Connection::PassThruReadMsgs(PASSTHRU_MSG *pMsg, unsigned long *pNumMs
|
|||
messageRxBuff_mutex.unlock();
|
||||
if (Timeout == 0)
|
||||
break;
|
||||
Sleep(2);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -148,14 +149,33 @@ long J2534Connection::PassThruIoctl(unsigned long IoctlID, void *pInput, void *p
|
|||
|
||||
long J2534Connection::init5b(SBYTE_ARRAY* pInput, SBYTE_ARRAY* pOutput) { return STATUS_NOERROR; }
|
||||
long J2534Connection::initFast(PASSTHRU_MSG* pInput, PASSTHRU_MSG* pOutput) { return STATUS_NOERROR; }
|
||||
long J2534Connection::clearTXBuff() { return STATUS_NOERROR; }
|
||||
long J2534Connection::clearRXBuff() {
|
||||
synchronized(messageRxBuff_mutex) {
|
||||
this->messageRxBuff = {};
|
||||
long J2534Connection::clearTXBuff() {
|
||||
if (auto panda_ps = this->panda_dev.lock()) {
|
||||
synchronized(staged_writes_lock) {
|
||||
this->txbuff = {};
|
||||
panda_ps->panda->can_clear(panda::PANDA_CAN1_TX);
|
||||
}
|
||||
}
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
long J2534Connection::clearPeriodicMsgs() { return STATUS_NOERROR; }
|
||||
long J2534Connection::clearRXBuff() {
|
||||
if (auto panda_ps = this->panda_dev.lock()) {
|
||||
synchronized(messageRxBuff_mutex) {
|
||||
this->messageRxBuff = {};
|
||||
panda_ps->panda->can_clear(panda::PANDA_CAN_RX);
|
||||
}
|
||||
}
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
long J2534Connection::clearPeriodicMsgs() {
|
||||
for (int i = 0; i < this->periodicMessages.size(); i++) {
|
||||
if (periodicMessages[i] == nullptr) continue;
|
||||
this->periodicMessages[i]->cancel();
|
||||
this->periodicMessages[i] = nullptr;
|
||||
}
|
||||
|
||||
return STATUS_NOERROR;
|
||||
}
|
||||
long J2534Connection::clearMsgFilters() {
|
||||
for (auto& filter : this->filters) filter = nullptr;
|
||||
return STATUS_NOERROR;
|
||||
|
|
|
@ -10,7 +10,7 @@ public:
|
|||
|
||||
J2534Frame(const panda::PANDA_CAN_MSG& msg_in) {
|
||||
ProtocolID = CAN;
|
||||
ExtraDataIndex = 0;
|
||||
ExtraDataIndex = msg_in.len + 4;
|
||||
Data.reserve(msg_in.len + 4);
|
||||
Data += msg_in.addr >> 24;
|
||||
Data += (msg_in.addr >> 16) & 0xFF;
|
||||
|
|
|
@ -95,7 +95,7 @@ BOOL MessageTx_ISO15765::checkTxReceipt(J2534Frame frame) {
|
|||
|
||||
J2534Frame outframe(ISO15765);
|
||||
outframe.Timestamp = frame.Timestamp;
|
||||
outframe.RxStatus = TX_INDICATION | (flags & (ISO15765_ADDR_TYPE | CAN_29BIT_ID));
|
||||
outframe.RxStatus = TX_MSG_TYPE | TX_INDICATION | (flags & (ISO15765_ADDR_TYPE | CAN_29BIT_ID));
|
||||
outframe.Data = frame.Data.substr(0, addressLength());
|
||||
conn_sp->addMsgToRxQueue(outframe);
|
||||
|
||||
|
|
|
@ -8,11 +8,15 @@ PandaJ2534Device::PandaJ2534Device(std::unique_ptr<panda::Panda> new_panda) : tx
|
|||
this->panda->set_esp_power(FALSE);
|
||||
this->panda->set_safety_mode(panda::SAFETY_ALLOUTPUT);
|
||||
this->panda->set_can_loopback(FALSE);
|
||||
this->panda->set_alt_setting(1);
|
||||
this->panda->set_alt_setting(0);
|
||||
|
||||
this->thread_kill_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
||||
DWORD canListenThreadID;
|
||||
this->thread_kill_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
this->can_thread_handle = CreateThread(NULL, 0, _can_recv_threadBootstrap, (LPVOID)this, 0, &canListenThreadID);
|
||||
this->can_recv_handle = CreateThread(NULL, 0, _can_recv_threadBootstrap, (LPVOID)this, 0, &canListenThreadID);
|
||||
|
||||
DWORD canProcessThreadID;
|
||||
this->can_process_handle = CreateThread(NULL, 0, _can_process_threadBootstrap, (LPVOID)this, 0, &canProcessThreadID);
|
||||
|
||||
DWORD flowControlSendThreadID;
|
||||
this->flow_control_wakeup_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
|
@ -21,8 +25,11 @@ PandaJ2534Device::PandaJ2534Device(std::unique_ptr<panda::Panda> new_panda) : tx
|
|||
|
||||
PandaJ2534Device::~PandaJ2534Device() {
|
||||
SetEvent(this->thread_kill_event);
|
||||
DWORD res = WaitForSingleObject(this->can_thread_handle, INFINITE);
|
||||
CloseHandle(this->can_thread_handle);
|
||||
DWORD res = WaitForSingleObject(this->can_recv_handle, INFINITE);
|
||||
CloseHandle(this->can_recv_handle);
|
||||
|
||||
res = WaitForSingleObject(this->can_process_handle, INFINITE);
|
||||
CloseHandle(this->can_process_handle);
|
||||
|
||||
res = WaitForSingleObject(this->flow_control_thread_handle, INFINITE);
|
||||
CloseHandle(this->flow_control_thread_handle);
|
||||
|
@ -67,11 +74,28 @@ DWORD PandaJ2534Device::addChannel(std::shared_ptr<J2534Connection>& conn, unsig
|
|||
}
|
||||
|
||||
DWORD PandaJ2534Device::can_recv_thread() {
|
||||
DWORD err = TRUE;
|
||||
while (err) {
|
||||
std::vector<panda::PANDA_CAN_MSG> msg_recv;
|
||||
err = this->panda->can_recv_async(this->thread_kill_event, msg_recv);
|
||||
for (auto msg_in : msg_recv) {
|
||||
this->panda->can_clear(panda::PANDA_CAN_RX);
|
||||
this->panda->can_rx_q_push(this->thread_kill_event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DWORD PandaJ2534Device::can_process_thread() {
|
||||
panda::PANDA_CAN_MSG msg_recv[CAN_RX_MSG_LEN];
|
||||
|
||||
while (true) {
|
||||
if (!WaitForSingleObject(this->thread_kill_event, 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
this->panda->can_rx_q_pop(msg_recv, count);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
auto msg_in = msg_recv[i];
|
||||
J2534Frame msg_out(msg_in);
|
||||
|
||||
if (msg_in.is_receipt) {
|
||||
|
|
|
@ -55,12 +55,18 @@ public:
|
|||
private:
|
||||
HANDLE thread_kill_event;
|
||||
|
||||
HANDLE can_thread_handle;
|
||||
HANDLE can_recv_handle;
|
||||
static DWORD WINAPI _can_recv_threadBootstrap(LPVOID This) {
|
||||
return ((PandaJ2534Device*)This)->can_recv_thread();
|
||||
}
|
||||
DWORD can_recv_thread();
|
||||
|
||||
HANDLE can_process_handle;
|
||||
static DWORD WINAPI _can_process_threadBootstrap(LPVOID This) {
|
||||
return ((PandaJ2534Device*)This)->can_process_thread();
|
||||
}
|
||||
DWORD can_process_thread();
|
||||
|
||||
HANDLE flow_control_wakeup_event;
|
||||
HANDLE flow_control_thread_handle;
|
||||
static DWORD WINAPI _msg_tx_threadBootstrap(LPVOID This) {
|
||||
|
|
Loading…
Reference in New Issue