You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					431 lines
				
				17 KiB
			
		
		
			
		
	
	
					431 lines
				
				17 KiB
			| 
								 
											8 years ago
										 
									 | 
							
								// pandaJ2534DLL.cpp : Defines the exported functions for the DLL application.
							 | 
						||
| 
								 | 
							
								// Protocol derived from the following sites (which shall be referred to as The Protocol Reference #).
							 | 
						||
| 
								 | 
							
								// https://web.archive.org/web/20130805013326/https://tunertools.com/prodimages/DrewTech/Manuals/PassThru_API-1.pdf
							 | 
						||
| 
								 | 
							
								// http://web.archive.org/web/20170910063536/http://www.tiecar.net/downloads/SAE_J2534_2002.pdf
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "stdafx.h"
							 | 
						||
| 
								 | 
							
								#include "J2534_v0404.h"
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								#include "panda_shared/panda.h"
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								#include "J2534Connection.h"
							 | 
						||
| 
								 | 
							
								#include "J2534Connection_CAN.h"
							 | 
						||
| 
								 | 
							
								#include "J2534Connection_ISO15765.h"
							 | 
						||
| 
								 | 
							
								#include "PandaJ2534Device.h"
							 | 
						||
| 
								 | 
							
								#include "dllmain.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// A quick way to avoid the name mangling that __stdcall liked to do
							 | 
						||
| 
								 | 
							
								#define EXPORT comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								std::vector<std::shared_ptr<PandaJ2534Device>> pandas;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int J25334LastError = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								std::string GetProductAndVersion(TCHAR* szFilename)//std::string & strProductName, std::string & strProductVersion)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
									// allocate a block of memory for the version info
							 | 
						||
| 
								 | 
							
									DWORD dummy;
							 | 
						||
| 
								 | 
							
									DWORD dwSize = GetFileVersionInfoSize(szFilename, &dummy);
							 | 
						||
| 
								 | 
							
									if (dwSize == 0) {
							 | 
						||
| 
								 | 
							
										return "error";
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									std::vector<BYTE> data(dwSize);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// load the version info
							 | 
						||
| 
								 | 
							
									if (!GetFileVersionInfo(szFilename, NULL, dwSize, &data[0])) {
							 | 
						||
| 
								 | 
							
										return "error";
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// get the name and version strings
							 | 
						||
| 
								 | 
							
									LPVOID pvProductName = NULL;
							 | 
						||
| 
								 | 
							
									unsigned int iProductNameLen = 0;
							 | 
						||
| 
								 | 
							
									LPVOID pvProductVersion = NULL;
							 | 
						||
| 
								 | 
							
									unsigned int iProductVersionLen = 0;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// 040904b0 is a language id.
							 | 
						||
| 
								 | 
							
									if (!VerQueryValueA(&data[0], "\\StringFileInfo\\040904b0\\ProductName", &pvProductName, &iProductNameLen) ||
							 | 
						||
| 
								 | 
							
										!VerQueryValueA(&data[0], "\\StringFileInfo\\040904b0\\ProductVersion", &pvProductVersion, &iProductVersionLen)) {
							 | 
						||
| 
								 | 
							
										return "error";
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									std::string ver_str = std::string((char*)pvProductVersion, iProductVersionLen-1);
							 | 
						||
| 
								 | 
							
									std::string prod_str = std::string((char*)pvProductName, iProductNameLen-1);
							 | 
						||
| 
								 | 
							
									std::string full_ver = prod_str + std::string(": ") + ver_str;
							 | 
						||
| 
								 | 
							
									return full_ver;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								long ret_code(long code) {
							 | 
						||
| 
								 | 
							
									J25334LastError = code;
							 | 
						||
| 
								 | 
							
									return code;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								#define EXTRACT_DID(CID) ((CID & 0xFFFF) - 1)
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
								#define EXTRACT_CID(CID) ((CID >> 16) & 0xFFFF)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								long check_valid_DeviceID(unsigned long DeviceID) {
							 | 
						||
| 
								 | 
							
									uint16_t dev_id = EXTRACT_DID(DeviceID);
							 | 
						||
| 
								 | 
							
									if (pandas.size() <= dev_id || pandas[dev_id] == nullptr)
							 | 
						||
| 
								 | 
							
										return ret_code(ERR_INVALID_DEVICE_ID);
							 | 
						||
| 
								 | 
							
									return ret_code(STATUS_NOERROR);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								long check_valid_ChannelID(unsigned long ChannelID) {
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
									uint16_t dev_id = EXTRACT_DID(ChannelID);
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
									uint16_t con_id = EXTRACT_CID(ChannelID);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (pandas.size() <= dev_id || pandas[dev_id] == nullptr)
							 | 
						||
| 
								 | 
							
										return ret_code(ERR_INVALID_CHANNEL_ID);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (pandas[dev_id]->connections.size() <= con_id) return ret_code(ERR_INVALID_CHANNEL_ID);
							 | 
						||
| 
								 | 
							
									if (pandas[dev_id]->connections[con_id] == nullptr) return ret_code(ERR_DEVICE_NOT_CONNECTED);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return ret_code(STATUS_NOERROR);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								//Do not call without checking if the device/channel id exists first.
							 | 
						||
| 
								 | 
							
								#define get_device(DeviceID) (pandas[EXTRACT_DID(DeviceID)])
							 | 
						||
| 
								 | 
							
								#define get_channel(ChannelID) (get_device(ChannelID)->connections[EXTRACT_CID(ChannelID)])
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI    PassThruOpen(void *pName, unsigned long *pDeviceID) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (pDeviceID == NULL) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
									std::string sn = (pName == NULL) ? "" : std::string((char*)pName);
							 | 
						||
| 
								 | 
							
									if (sn == "J2534-2:")
							 | 
						||
| 
								 | 
							
										sn = "";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									auto new_panda = PandaJ2534Device::openByName(sn);
							 | 
						||
| 
								 | 
							
									if (new_panda == nullptr) {
							 | 
						||
| 
								 | 
							
										if(sn == "" && pandas.size() == 1)
							 | 
						||
| 
								 | 
							
											return ret_code(ERR_DEVICE_IN_USE);
							 | 
						||
| 
								 | 
							
										for (auto& pn : pandas) {
							 | 
						||
| 
								 | 
							
											if (pn->panda->get_usb_sn() == sn)
							 | 
						||
| 
								 | 
							
												return ret_code(ERR_DEVICE_IN_USE);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										return ret_code(ERR_DEVICE_NOT_CONNECTED);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									int panda_index = -1;
							 | 
						||
| 
								 | 
							
									for (unsigned int i = 0; i < pandas.size(); i++)
							 | 
						||
| 
								 | 
							
										if (pandas[i] == nullptr) {
							 | 
						||
| 
								 | 
							
											panda_index = i;
							 | 
						||
| 
								 | 
							
											pandas[panda_index] = std::move(new_panda);
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									if (panda_index == -1) {
							 | 
						||
| 
								 | 
							
										if(pandas.size() == 0xFFFF) //device id will be 16 bit to fit channel next to it.
							 | 
						||
| 
								 | 
							
											return ret_code(ERR_FAILED); //Too many pandas. Off the endangered species list.
							 | 
						||
| 
								 | 
							
										pandas.push_back(std::move(new_panda));
							 | 
						||
| 
								 | 
							
										panda_index = pandas.size()-1;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
									*pDeviceID = panda_index + 1; // TIS doesn't like it when ID == 0
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
									return ret_code(STATUS_NOERROR);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruClose(unsigned long DeviceID) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (check_valid_DeviceID(DeviceID) != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
									get_device(DeviceID) = nullptr;
							 | 
						||
| 
								 | 
							
									return ret_code(STATUS_NOERROR);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruConnect(unsigned long DeviceID, unsigned long ProtocolID,
							 | 
						||
| 
								 | 
							
									                                            unsigned long Flags, unsigned long BaudRate, unsigned long *pChannelID) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (pChannelID == NULL) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
									if (check_valid_DeviceID(DeviceID) != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
									auto& panda = get_device(DeviceID);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									std::shared_ptr<J2534Connection> conn;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									//TODO check if channel can be made
							 | 
						||
| 
								 | 
							
									try {
							 | 
						||
| 
								 | 
							
										switch (ProtocolID) {
							 | 
						||
| 
								 | 
							
											//SW seems to refer to Single Wire. https://www.nxp.com/files-static/training_pdf/20451_BUS_COMM_WBT.pdf
							 | 
						||
| 
								 | 
							
											//SW_ protocols may be touched on here: https://www.iso.org/obp/ui/#iso:std:iso:22900:-2:ed-1:v1:en
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
										//case J1850VPW: // These protocols are outdated and will not be supported. HDS wants them to not fail to open.
							 | 
						||
| 
								 | 
							
										//case J1850PWM: // ^-- it appears HDS no longer needs this, and TIS needs it disabled --^
							 | 
						||
| 
								 | 
							
										//case J1850VPW_PS:
							 | 
						||
| 
								 | 
							
										//case J1850PWM_PS:
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
										case ISO9141: //This protocol could be implemented if 5 BAUD init support is added to the panda.
							 | 
						||
| 
								 | 
							
										case ISO9141_PS:
							 | 
						||
| 
								 | 
							
										case ISO14230: //Only supporting Fast init until panda adds support for 5 BAUD init.
							 | 
						||
| 
								 | 
							
										case ISO14230_PS:
							 | 
						||
| 
								 | 
							
											conn = std::make_shared<J2534Connection>(panda, ProtocolID, Flags, BaudRate);
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case CAN:
							 | 
						||
| 
								 | 
							
										case CAN_PS:
							 | 
						||
| 
								 | 
							
										//case SW_CAN_PS:
							 | 
						||
| 
								 | 
							
											conn = std::make_shared<J2534Connection_CAN>(panda, ProtocolID, Flags, BaudRate);
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										case ISO15765:
							 | 
						||
| 
								 | 
							
										case ISO15765_PS:
							 | 
						||
| 
								 | 
							
											conn = std::make_shared<J2534Connection_ISO15765>(panda, ProtocolID, Flags, BaudRate);
							 | 
						||
| 
								 | 
							
											break;
							 | 
						||
| 
								 | 
							
										//case SW_ISO15765_PS: // SW = Single Wire. GMLAN is a SW CAN protocol
							 | 
						||
| 
								 | 
							
										//case GM_UART_PS: // PS = Pin Select. Handles different ports.
							 | 
						||
| 
								 | 
							
										//Looks like SCI based protocols may not be compatible with the panda:
							 | 
						||
| 
								 | 
							
										//http://mdhmotors.com/can-communications-vehicle-network-protocols/3/
							 | 
						||
| 
								 | 
							
										//case SCI_A_ENGINE:
							 | 
						||
| 
								 | 
							
										//case SCI_A_TRANS:
							 | 
						||
| 
								 | 
							
										//case SCI_B_ENGINE:
							 | 
						||
| 
								 | 
							
											//case SCI_B_TRANS:
							 | 
						||
| 
								 | 
							
										//case J2610_PS:
							 | 
						||
| 
								 | 
							
										default:
							 | 
						||
| 
								 | 
							
											return ret_code(ERR_INVALID_PROTOCOL_ID);
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
									} catch (int e) {
							 | 
						||
| 
								 | 
							
										return ret_code(e);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									unsigned long channel_index;
							 | 
						||
| 
								 | 
							
									unsigned long err = panda->addChannel(conn, &channel_index);
							 | 
						||
| 
								 | 
							
									if (err == STATUS_NOERROR)
							 | 
						||
| 
								 | 
							
										*pChannelID = (channel_index << 16) | DeviceID;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return ret_code(err);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruDisconnect(unsigned long ChannelID) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									unsigned long res = check_valid_DeviceID(ChannelID);
							 | 
						||
| 
								 | 
							
									if (res == ERR_INVALID_DEVICE_ID) return ret_code(ERR_INVALID_CHANNEL_ID);
							 | 
						||
| 
								 | 
							
									if (res != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
									return ret_code(get_device(ChannelID)->closeChannel(EXTRACT_CID(ChannelID)));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruReadMsgs(unsigned long ChannelID, PASSTHRU_MSG *pMsg,
							 | 
						||
| 
								 | 
							
									                                             unsigned long *pNumMsgs, unsigned long Timeout) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (pMsg == NULL || pNumMsgs == NULL) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
									if (check_valid_ChannelID(ChannelID) != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
									return ret_code(get_channel(ChannelID)->PassThruReadMsgs(pMsg, pNumMsgs, Timeout));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruWriteMsgs(unsigned long ChannelID, PASSTHRU_MSG *pMsg, unsigned long *pNumMsgs, unsigned long Timeout) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (pMsg == NULL || pNumMsgs == NULL) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
									if (check_valid_ChannelID(ChannelID) != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
									return ret_code(get_channel(ChannelID)->PassThruWriteMsgs(pMsg, pNumMsgs, Timeout));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruStartPeriodicMsg(unsigned long ChannelID, PASSTHRU_MSG *pMsg, unsigned long *pMsgID, unsigned long TimeInterval) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (pMsg == NULL || pMsgID == NULL) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
									if (check_valid_ChannelID(ChannelID) != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
									return ret_code(get_channel(ChannelID)->PassThruStartPeriodicMsg(pMsg, pMsgID, TimeInterval));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruStopPeriodicMsg(unsigned long ChannelID, unsigned long MsgID) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (check_valid_ChannelID(ChannelID) != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
									return ret_code(get_channel(ChannelID)->PassThruStopPeriodicMsg(MsgID));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruStartMsgFilter(unsigned long ChannelID, unsigned long FilterType, PASSTHRU_MSG *pMaskMsg,
							 | 
						||
| 
								 | 
							
									                                                   PASSTHRU_MSG *pPatternMsg, PASSTHRU_MSG *pFlowControlMsg, unsigned long *pFilterID) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (FilterType != PASS_FILTER && FilterType != BLOCK_FILTER && FilterType != FLOW_CONTROL_FILTER) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
									if (!pFilterID || (!pMaskMsg && !pPatternMsg && !pFlowControlMsg)) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
									if (check_valid_ChannelID(ChannelID) != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
									return ret_code(get_channel(ChannelID)->PassThruStartMsgFilter(FilterType, pMaskMsg, pPatternMsg, pFlowControlMsg, pFilterID));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruStopMsgFilter(unsigned long ChannelID, unsigned long FilterID) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (check_valid_ChannelID(ChannelID) != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
									return ret_code(get_channel(ChannelID)->PassThruStopMsgFilter(FilterID));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruSetProgrammingVoltage(unsigned long DeviceID, unsigned long PinNumber, unsigned long Voltage) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									//Unused
							 | 
						||
| 
								 | 
							
									if (check_valid_DeviceID(DeviceID) != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
									auto& panda = get_device(DeviceID);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									switch (Voltage) {
							 | 
						||
| 
								 | 
							
									case SHORT_TO_GROUND:
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case VOLTAGE_OFF:
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									default:
							 | 
						||
| 
								 | 
							
										if (!(5000 <= Voltage && Voltage <= 20000))
							 | 
						||
| 
								 | 
							
											return ret_code(ERR_NOT_SUPPORTED);
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return ret_code(STATUS_NOERROR);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruReadVersion(unsigned long DeviceID, char *pFirmwareVersion, char *pDllVersion, char *pApiVersion) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (!pFirmwareVersion || !pDllVersion || !pApiVersion) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
									if (check_valid_DeviceID(DeviceID) != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									auto& panda = get_device(DeviceID);
							 | 
						||
| 
								 | 
							
									auto fw_version = panda->panda->get_version();
							 | 
						||
| 
								 | 
							
									strcpy_s(pFirmwareVersion, 80, fw_version.c_str());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									std::string j2534dll_ver;
							 | 
						||
| 
								 | 
							
									TCHAR pandalib_filename[MAX_PATH + 1] = { 0 };
							 | 
						||
| 
								 | 
							
									if (GetModuleFileName(thisdll, pandalib_filename, MAX_PATH) == 0) {
							 | 
						||
| 
								 | 
							
										j2534dll_ver = "error";
							 | 
						||
| 
								 | 
							
									} else {
							 | 
						||
| 
								 | 
							
										j2534dll_ver = GetProductAndVersion(pandalib_filename);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
									std::string fullver = "(" + j2534dll_ver + ")";
							 | 
						||
| 
								 
											8 years ago
										 
									 | 
							
									strcpy_s(pDllVersion, 80, fullver.c_str());
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									strcpy_s(pApiVersion, 80, J2534_APIVER_NOVEMBER_2004);
							 | 
						||
| 
								 | 
							
									return ret_code(STATUS_NOERROR);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruGetLastError(char *pErrorDescription) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (pErrorDescription == NULL) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
									switch (J25334LastError) {
							 | 
						||
| 
								 | 
							
									case STATUS_NOERROR:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Function call successful.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_NOT_SUPPORTED:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Device cannot support requested functionality mandated in J2534.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_INVALID_CHANNEL_ID:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Invalid ChannelID value.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_INVALID_PROTOCOL_ID:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Invalid or unsupported ProtocolID, or resource conflict.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_NULL_PARAMETER:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "NULL pointer supplied where a valid pointer is required.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_INVALID_IOCTL_VALUE:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Invalid value for Ioctl parameter.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_INVALID_FLAGS:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Invalid flag values.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_FAILED:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Undefined error.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_DEVICE_NOT_CONNECTED:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Unable to communicate with device.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_TIMEOUT:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Read or write timeout:");
							 | 
						||
| 
								 | 
							
										// PassThruReadMsgs() - No message available to read or could not read the specified number of messages. The actual number of messages read is placed in <NumMsgs>.
							 | 
						||
| 
								 | 
							
										// PassThruWriteMsgs() - Device could not write the specified number of messages. The actual number of messages sent on the vehicle network is placed in <NumMsgs>.
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_INVALID_MSG:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Invalid message structure pointed to by pMsg.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_INVALID_TIME_INTERVAL:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Invalid TimeInterval value.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_EXCEEDED_LIMIT:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Exceeded maximum number of message IDs or allocated space.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_INVALID_MSG_ID:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Invalid MsgID value.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_DEVICE_IN_USE:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Device is currently open.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_INVALID_IOCTL_ID:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Invalid IoctlID value.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_BUFFER_EMPTY:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Protocol message buffer empty.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_BUFFER_FULL:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Protocol message buffer full. Messages may have been lost.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_BUFFER_OVERFLOW:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "A buffer overflow occurred and messages were lost.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_PIN_INVALID:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Invalid pin number, or pin number already in use.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_CHANNEL_IN_USE:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Channel number is currently connected.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_MSG_PROTOCOL_ID:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "The Message's Protocol does not match the Channel's protocol.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_INVALID_FILTER_ID:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Invalid Filter ID value.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_NO_FLOW_CONTROL:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "No flow control filter set or matched.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_NOT_UNIQUE:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "This filter already exists.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_INVALID_BAUDRATE:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "The desired baud rate cannot be achieved within SAE tolerance.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case ERR_INVALID_DEVICE_ID:
							 | 
						||
| 
								 | 
							
										strcpy_s(pErrorDescription, 80, "Device ID invalid.");
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									return ret_code(STATUS_NOERROR);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								PANDAJ2534DLL_API long PTAPI	PassThruIoctl(unsigned long ChannelID, unsigned long IoctlID,
							 | 
						||
| 
								 | 
							
									                                          void *pInput, void *pOutput) {
							 | 
						||
| 
								 | 
							
									#pragma EXPORT
							 | 
						||
| 
								 | 
							
									if (check_valid_ChannelID(ChannelID) != STATUS_NOERROR) return J25334LastError;
							 | 
						||
| 
								 | 
							
									auto& dev_entry = get_device(ChannelID);
							 | 
						||
| 
								 | 
							
									//get_channel(ChannelID)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									switch (IoctlID) {
							 | 
						||
| 
								 | 
							
									case GET_CONFIG:
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										SCONFIG_LIST *inconfig = (SCONFIG_LIST*)pInput;
							 | 
						||
| 
								 | 
							
										if (inconfig == NULL)
							 | 
						||
| 
								 | 
							
											return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
										for (unsigned int i = 0; i < inconfig->NumOfParams; i++) {
							 | 
						||
| 
								 | 
							
											try {
							 | 
						||
| 
								 | 
							
												inconfig->ConfigPtr[i].Value = get_channel(ChannelID)->processIOCTLGetConfig(inconfig->ConfigPtr[i].Parameter);
							 | 
						||
| 
								 | 
							
											} catch (int e) {
							 | 
						||
| 
								 | 
							
												return ret_code(e);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									case SET_CONFIG:
							 | 
						||
| 
								 | 
							
									{
							 | 
						||
| 
								 | 
							
										SCONFIG_LIST *inconfig = (SCONFIG_LIST*)pInput;
							 | 
						||
| 
								 | 
							
										if (inconfig == NULL)
							 | 
						||
| 
								 | 
							
											return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
										for (unsigned int i = 0; i < inconfig->NumOfParams; i++) {
							 | 
						||
| 
								 | 
							
											try {
							 | 
						||
| 
								 | 
							
												get_channel(ChannelID)->processIOCTLSetConfig(inconfig->ConfigPtr[i].Parameter, inconfig->ConfigPtr[i].Value);
							 | 
						||
| 
								 | 
							
											} catch (int e) {
							 | 
						||
| 
								 | 
							
												return ret_code(e);
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									case READ_VBATT:
							 | 
						||
| 
								 | 
							
										panda::PANDA_HEALTH health = dev_entry->panda->get_health();
							 | 
						||
| 
								 | 
							
										*(unsigned long*)pOutput = health.voltage;
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									case FIVE_BAUD_INIT:
							 | 
						||
| 
								 | 
							
										if (!pInput || !pOutput) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
										return ret_code(get_channel(ChannelID)->init5b((SBYTE_ARRAY*)pInput, (SBYTE_ARRAY*)pOutput));
							 | 
						||
| 
								 | 
							
									case FAST_INIT:
							 | 
						||
| 
								 | 
							
										if (!pInput || !pOutput) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
										return ret_code(get_channel(ChannelID)->initFast((PASSTHRU_MSG*)pInput, (PASSTHRU_MSG*)pOutput));
							 | 
						||
| 
								 | 
							
									case CLEAR_TX_BUFFER:
							 | 
						||
| 
								 | 
							
										return ret_code(get_channel(ChannelID)->clearTXBuff());
							 | 
						||
| 
								 | 
							
									case CLEAR_RX_BUFFER:
							 | 
						||
| 
								 | 
							
										return ret_code(get_channel(ChannelID)->clearRXBuff());
							 | 
						||
| 
								 | 
							
									case CLEAR_PERIODIC_MSGS:
							 | 
						||
| 
								 | 
							
										return ret_code(get_channel(ChannelID)->clearPeriodicMsgs());
							 | 
						||
| 
								 | 
							
									case CLEAR_MSG_FILTERS:
							 | 
						||
| 
								 | 
							
										return ret_code(get_channel(ChannelID)->clearMsgFilters());
							 | 
						||
| 
								 | 
							
									case CLEAR_FUNCT_MSG_LOOKUP_TABLE:			// LOOKUP TABLE IS RELATED TO J1850 PWM. Unsupported.
							 | 
						||
| 
								 | 
							
										if (!pInput) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
										return ret_code(STATUS_NOERROR);
							 | 
						||
| 
								 | 
							
									case ADD_TO_FUNCT_MSG_LOOKUP_TABLE:			// LOOKUP TABLE IS RELATED TO J1850 PWM. Unsupported.
							 | 
						||
| 
								 | 
							
										if (!pInput) return ret_code(ERR_NULL_PARAMETER);
							 | 
						||
| 
								 | 
							
										return ret_code(STATUS_NOERROR);
							 | 
						||
| 
								 | 
							
									case DELETE_FROM_FUNCT_MSG_LOOKUP_TABLE:	// LOOKUP TABLE IS RELATED TO J1850 PWM. Unsupported.
							 | 
						||
| 
								 | 
							
										return ret_code(STATUS_NOERROR);
							 | 
						||
| 
								 | 
							
									case READ_PROG_VOLTAGE:
							 | 
						||
| 
								 | 
							
										*(unsigned long*)pOutput = 0;
							 | 
						||
| 
								 | 
							
										break;
							 | 
						||
| 
								 | 
							
									default:
							 | 
						||
| 
								 | 
							
										printf("Got unknown IIOCTL %X\n", IoctlID);
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return ret_code(STATUS_NOERROR);
							 | 
						||
| 
								 | 
							
								}
							 |