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.
237 lines
6.3 KiB
237 lines
6.3 KiB
#pragma once
|
|
|
|
// The following ifdef block is the standard way of creating macros which make exporting
|
|
// from a DLL simpler. All files within this DLL are compiled with the PANDA_EXPORTS
|
|
// symbol defined on the command line. This symbol should not be defined on any project
|
|
// that uses this DLL. This way any other project whose source files include this file see
|
|
// PANDA_API functions as being imported from a DLL, whereas this DLL sees symbols
|
|
// defined with this macro as being exported.
|
|
#ifdef PANDA_EXPORTS
|
|
#define PANDA_API __declspec(dllexport)
|
|
#else
|
|
#define PANDA_API
|
|
#endif
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
#include <unordered_map>
|
|
#include <memory>
|
|
#include <iostream>
|
|
#include <chrono>
|
|
|
|
#include <windows.h>
|
|
#include <winusb.h>
|
|
|
|
#if defined(UNICODE)
|
|
#define _tcout std::wcout
|
|
#define tstring std::wstring
|
|
#else
|
|
#define _tcout std::cout
|
|
#define tstring std::string
|
|
#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>;
|
|
|
|
namespace panda {
|
|
typedef enum _PANDA_SAFETY_MODE : uint16_t {
|
|
SAFETY_NOOUTPUT = 0,
|
|
SAFETY_HONDA = 1,
|
|
SAFETY_ALLOUTPUT = 0x1337,
|
|
} PANDA_SAFETY_MODE;
|
|
|
|
typedef enum _PANDA_SERIAL_PORT : uint8_t {
|
|
SERIAL_DEBUG = 0,
|
|
SERIAL_ESP = 1,
|
|
SERIAL_LIN1 = 2,
|
|
SERIAL_LIN2 = 3,
|
|
} PANDA_SERIAL_PORT;
|
|
|
|
typedef enum _PANDA_SERIAL_PORT_PARITY : uint8_t {
|
|
PANDA_PARITY_OFF = 0,
|
|
PANDA_PARITY_EVEN = 1,
|
|
PANDA_PARITY_ODD = 2,
|
|
} PANDA_SERIAL_PORT_PARITY;
|
|
|
|
typedef enum _PANDA_CAN_PORT : uint8_t {
|
|
PANDA_CAN1 = 0,
|
|
PANDA_CAN2 = 1,
|
|
PANDA_CAN3 = 2,
|
|
PANDA_CAN_UNK = 0xFF,
|
|
} PANDA_CAN_PORT;
|
|
|
|
typedef enum _PANDA_CAN_PORT_CLEAR : uint16_t {
|
|
PANDA_CAN1_TX = 0,
|
|
PANDA_CAN2_TX = 1,
|
|
PANDA_CAN3_TX = 2,
|
|
PANDA_CAN_RX = 0xFFFF,
|
|
} PANDA_CAN_PORT_CLEAR;
|
|
|
|
typedef enum _PANDA_GMLAN_HOST_PORT : uint8_t {
|
|
PANDA_GMLAN_CLEAR = 0,
|
|
PANDA_GMLAN_CAN2 = 1,
|
|
PANDA_GMLAN_CAN3 = 2,
|
|
} PANDA_GMLAN_HOST_PORT;
|
|
|
|
#pragma pack(1)
|
|
typedef struct _PANDA_HEALTH {
|
|
uint32_t voltage;
|
|
uint32_t current;
|
|
uint8_t started;
|
|
uint8_t controls_allowed;
|
|
uint8_t gas_interceptor_detected;
|
|
uint8_t started_signal_detected;
|
|
uint8_t started_alt;
|
|
} PANDA_HEALTH, *PPANDA_HEALTH;
|
|
|
|
typedef struct _PANDA_CAN_MSG {
|
|
uint32_t addr;
|
|
unsigned long long recv_time; //In microseconds since device initialization
|
|
std::chrono::time_point<std::chrono::steady_clock> recv_time_point;
|
|
uint8_t dat[8];
|
|
uint8_t len;
|
|
PANDA_CAN_PORT bus;
|
|
bool is_receipt;
|
|
bool addr_29b;
|
|
} PANDA_CAN_MSG;
|
|
|
|
//Copied from https://stackoverflow.com/a/31488113
|
|
class Timer
|
|
{
|
|
using clock = std::chrono::steady_clock;
|
|
using time_point_type = std::chrono::time_point < clock, std::chrono::microseconds >;
|
|
public:
|
|
Timer() {
|
|
start = std::chrono::time_point_cast<std::chrono::microseconds>(clock::now());
|
|
}
|
|
|
|
// gets the time elapsed from construction.
|
|
unsigned long long /*microseconds*/ Timer::getTimePassedUS() {
|
|
// get the new time
|
|
auto end = std::chrono::time_point_cast<std::chrono::microseconds>(clock::now());
|
|
|
|
// return the difference of the times
|
|
return (end - start).count();
|
|
}
|
|
|
|
// gets the time elapsed from construction.
|
|
unsigned long long /*milliseconds*/ Timer::getTimePassedMS() {
|
|
// get the new time
|
|
auto end = std::chrono::time_point_cast<std::chrono::milliseconds>(clock::now());
|
|
|
|
// return the difference of the times
|
|
auto startms = std::chrono::time_point_cast<std::chrono::milliseconds>(start);
|
|
return (end - startms).count();
|
|
}
|
|
private:
|
|
time_point_type start;
|
|
};
|
|
|
|
// This class is exported from the panda.dll
|
|
class PANDA_API Panda {
|
|
public:
|
|
static std::vector<std::string> listAvailablePandas();
|
|
static std::unique_ptr<Panda> openPanda(std::string sn);
|
|
|
|
~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();
|
|
std::string get_version();
|
|
std::string get_serial();
|
|
std::string get_secret();
|
|
|
|
bool set_usb_power(bool on);
|
|
bool set_esp_power(bool on);
|
|
bool esp_reset(uint16_t bootmode);
|
|
bool set_safety_mode(PANDA_SAFETY_MODE mode);
|
|
bool set_can_forwarding(PANDA_CAN_PORT from_bus, PANDA_CAN_PORT to_bus);
|
|
bool set_gmlan(PANDA_GMLAN_HOST_PORT bus);
|
|
bool set_can_loopback(bool enable);
|
|
bool set_can_speed_cbps(PANDA_CAN_PORT bus, uint16_t speed);
|
|
bool set_can_speed_kbps(PANDA_CAN_PORT bus, uint16_t speed);
|
|
bool set_uart_baud(PANDA_SERIAL_PORT uart, uint32_t rate);
|
|
bool set_uart_parity(PANDA_SERIAL_PORT uart, PANDA_SERIAL_PORT_PARITY parity);
|
|
|
|
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);
|
|
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);
|
|
int serial_write(PANDA_SERIAL_PORT port_number, const void* buff, uint16_t len);
|
|
bool serial_clear(PANDA_SERIAL_PORT port_number);
|
|
private:
|
|
Panda(
|
|
WINUSB_INTERFACE_HANDLE WinusbHandle,
|
|
HANDLE DeviceHandle,
|
|
tstring devPath_,
|
|
std::string sn_
|
|
);
|
|
|
|
int control_transfer(
|
|
uint8_t bmRequestType,
|
|
uint8_t bRequest,
|
|
uint16_t wValue,
|
|
uint16_t wIndex,
|
|
void * data,
|
|
uint16_t wLength,
|
|
unsigned int timeout
|
|
);
|
|
|
|
int bulk_write(
|
|
UCHAR endpoint,
|
|
const void * buff,
|
|
ULONG length,
|
|
PULONG transferred,
|
|
ULONG timeout
|
|
);
|
|
|
|
int Panda::bulk_read(
|
|
UCHAR endpoint,
|
|
void * buff,
|
|
ULONG buff_size,
|
|
PULONG transferred,
|
|
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;
|
|
std::string sn;
|
|
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;
|
|
};
|
|
|
|
}
|
|
|