mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-08-20 23:53:44 +08:00
Merge branch 'devel' of https://github.com/commaai/openpilot into devel-en
This commit is contained in:
+5
-3
@@ -39,9 +39,11 @@ Find user made scripts on the [wiki](https://community.comma.ai/wiki/index.php/P
|
||||
|
||||
Note that you may have to setup [udev rules](https://community.comma.ai/wiki/index.php/Panda#Linux_udev_rules) for Linux, such as
|
||||
```
|
||||
sudo -i
|
||||
echo 'SUBSYSTEMS=="usb", ATTR{idVendor}=="bbaa", ATTR{idProduct}=="ddcc", MODE:="0666"' > /etc/udev/rules.d/11-panda.rules
|
||||
exit
|
||||
sudo tee /etc/udev/rules.d/11-panda.rules <<EOF
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="bbaa", ATTRS{idProduct}=="ddcc", MODE="0666"
|
||||
SUBSYSTEM=="usb", ATTRS{idVendor}=="bbaa", ATTRS{idProduct}=="ddee", MODE="0666"
|
||||
EOF
|
||||
sudo udevadm control --reload-rules && sudo udevadm trigger
|
||||
```
|
||||
|
||||
Usage (JavaScript)
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
v1.7.0
|
||||
v1.7.3
|
||||
@@ -11,6 +11,28 @@ void grey_init(void) {
|
||||
current_board->set_esp_gps_mode(ESP_GPS_ENABLED);
|
||||
}
|
||||
|
||||
void grey_set_esp_gps_mode(uint8_t mode) {
|
||||
switch (mode) {
|
||||
case ESP_GPS_DISABLED:
|
||||
// GPS OFF
|
||||
set_gpio_output(GPIOC, 14, 0);
|
||||
set_gpio_output(GPIOC, 5, 0);
|
||||
break;
|
||||
case ESP_GPS_ENABLED:
|
||||
// GPS ON
|
||||
set_gpio_output(GPIOC, 14, 1);
|
||||
set_gpio_output(GPIOC, 5, 1);
|
||||
break;
|
||||
case ESP_GPS_BOOTMODE:
|
||||
set_gpio_output(GPIOC, 14, 1);
|
||||
set_gpio_output(GPIOC, 5, 0);
|
||||
break;
|
||||
default:
|
||||
puts("Invalid ESP/GPS mode\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const board board_grey = {
|
||||
.board_type = "Grey",
|
||||
.harness_config = &white_harness_config,
|
||||
@@ -19,7 +41,7 @@ const board board_grey = {
|
||||
.enable_can_transcievers = white_enable_can_transcievers,
|
||||
.set_led = white_set_led,
|
||||
.set_usb_power_mode = white_set_usb_power_mode,
|
||||
.set_esp_gps_mode = white_set_esp_gps_mode,
|
||||
.set_esp_gps_mode = grey_set_esp_gps_mode,
|
||||
.set_can_mode = white_set_can_mode,
|
||||
.usb_power_mode_tick = white_usb_power_mode_tick,
|
||||
.check_ignition = white_check_ignition,
|
||||
|
||||
@@ -14,6 +14,7 @@ typedef struct {
|
||||
|
||||
#define BUS_MAX 4U
|
||||
|
||||
uint32_t can_rx_errs = 0;
|
||||
uint32_t can_send_errs = 0;
|
||||
uint32_t can_fwd_errs = 0;
|
||||
uint32_t gmlan_send_errs = 0;
|
||||
@@ -381,7 +382,7 @@ void can_rx(uint8_t can_number) {
|
||||
can_send(&to_send, bus_fwd_num, true);
|
||||
}
|
||||
|
||||
safety_rx_hook(&to_push);
|
||||
can_rx_errs += safety_rx_hook(&to_push) ? 0U : 1U;
|
||||
ignition_can_hook(&to_push);
|
||||
|
||||
current_board->set_led(LED_BLUE, true);
|
||||
|
||||
+6
-7
@@ -45,6 +45,7 @@ struct __attribute__((packed)) health_t {
|
||||
uint32_t uptime_pkt;
|
||||
uint32_t voltage_pkt;
|
||||
uint32_t current_pkt;
|
||||
uint32_t can_rx_errs_pkt;
|
||||
uint32_t can_send_errs_pkt;
|
||||
uint32_t can_fwd_errs_pkt;
|
||||
uint32_t gmlan_send_errs_pkt;
|
||||
@@ -170,6 +171,7 @@ int get_health_pkt(void *dat) {
|
||||
|
||||
health->controls_allowed_pkt = controls_allowed;
|
||||
health->gas_interceptor_detected_pkt = gas_interceptor_detected;
|
||||
health->can_rx_errs_pkt = can_rx_errs;
|
||||
health->can_send_errs_pkt = can_send_errs;
|
||||
health->can_fwd_errs_pkt = can_fwd_errs;
|
||||
health->gmlan_send_errs_pkt = gmlan_send_errs;
|
||||
@@ -475,12 +477,6 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
can_init(CAN_NUM_FROM_BUS_NUM(setup->b.wValue.w));
|
||||
}
|
||||
break;
|
||||
// **** 0xdf: set long controls allowed
|
||||
case 0xdf:
|
||||
if (hardwired) {
|
||||
long_controls_allowed = setup->b.wValue.w & 1U;
|
||||
}
|
||||
break;
|
||||
// **** 0xe0: uart read
|
||||
case 0xe0:
|
||||
ur = get_ring_by_number(setup->b.wValue.w);
|
||||
@@ -671,7 +667,7 @@ void __attribute__ ((noinline)) enable_fpu(void) {
|
||||
#define EON_HEARTBEAT_IGNITION_CNT_ON 5U
|
||||
#define EON_HEARTBEAT_IGNITION_CNT_OFF 2U
|
||||
|
||||
// called once per second
|
||||
// called at 1Hz
|
||||
void TIM1_BRK_TIM9_IRQ_Handler(void) {
|
||||
if (TIM9->SR != 0) {
|
||||
can_live = pending_can_live;
|
||||
@@ -740,6 +736,9 @@ void TIM1_BRK_TIM9_IRQ_Handler(void) {
|
||||
uptime_cnt += 1U;
|
||||
safety_mode_cnt += 1U;
|
||||
ignition_can_cnt += 1U;
|
||||
|
||||
// synchronous safety check
|
||||
safety_tick(current_hooks);
|
||||
}
|
||||
TIM9->SR = 0;
|
||||
}
|
||||
|
||||
@@ -11,3 +11,9 @@ void get_provision_chunk(uint8_t *resp) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t chunk[PROVISION_CHUNK_LEN];
|
||||
bool is_provisioned(void) {
|
||||
(void)memcpy(chunk, (uint8_t *)0x1fff79e0, PROVISION_CHUNK_LEN);
|
||||
return (memcmp(chunk, "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", 0x20) != 0);
|
||||
}
|
||||
|
||||
|
||||
+109
-13
@@ -19,11 +19,11 @@
|
||||
|
||||
// from cereal.car.CarParams.SafetyModel
|
||||
#define SAFETY_SILENT 0U
|
||||
#define SAFETY_HONDA 1U
|
||||
#define SAFETY_HONDA_NIDEC 1U
|
||||
#define SAFETY_TOYOTA 2U
|
||||
#define SAFETY_ELM327 3U
|
||||
#define SAFETY_GM 4U
|
||||
#define SAFETY_HONDA_BOSCH 5U
|
||||
#define SAFETY_HONDA_BOSCH_GIRAFFE 5U
|
||||
#define SAFETY_FORD 6U
|
||||
#define SAFETY_CADILLAC 7U
|
||||
#define SAFETY_HYUNDAI 8U
|
||||
@@ -36,12 +36,13 @@
|
||||
#define SAFETY_ALLOUTPUT 17U
|
||||
#define SAFETY_GM_ASCM 18U
|
||||
#define SAFETY_NOOUTPUT 19U
|
||||
#define SAFETY_HONDA_BOSCH_HARNESS 20U
|
||||
|
||||
uint16_t current_safety_mode = SAFETY_SILENT;
|
||||
const safety_hooks *current_hooks = &nooutput_hooks;
|
||||
|
||||
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push){
|
||||
current_hooks->rx(to_push);
|
||||
int safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push){
|
||||
return current_hooks->rx(to_push);
|
||||
}
|
||||
|
||||
int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
@@ -56,7 +57,7 @@ int safety_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
return current_hooks->fwd(bus_num, to_fwd);
|
||||
}
|
||||
|
||||
bool addr_allowed(int addr, int bus, const AddrBus addr_list[], int len) {
|
||||
bool msg_allowed(int addr, int bus, const AddrBus addr_list[], int len) {
|
||||
bool allowed = false;
|
||||
for (int i = 0; i < len; i++) {
|
||||
if ((addr == addr_list[i].addr) && (bus == addr_list[i].bus)) {
|
||||
@@ -67,6 +68,106 @@ bool addr_allowed(int addr, int bus, const AddrBus addr_list[], int len) {
|
||||
return allowed;
|
||||
}
|
||||
|
||||
// compute the time elapsed (in microseconds) from 2 counter samples
|
||||
// case where ts < ts_last is ok: overflow is properly re-casted into uint32_t
|
||||
uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) {
|
||||
return ts - ts_last;
|
||||
}
|
||||
|
||||
int get_addr_check_index(CAN_FIFOMailBox_TypeDef *to_push, AddrCheckStruct addr_list[], const int len) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
int index = -1;
|
||||
for (int i = 0; i < len; i++) {
|
||||
for (uint8_t j = 0U; addr_list[i].addr[j] != 0; j++) {
|
||||
if ((addr == addr_list[i].addr[j]) && (bus == addr_list[i].bus)) {
|
||||
index = i;
|
||||
goto Return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Return:
|
||||
return index;
|
||||
}
|
||||
|
||||
// 1Hz safety function called by main. Now just a check for lagging safety messages
|
||||
void safety_tick(const safety_hooks *hooks) {
|
||||
uint32_t ts = TIM2->CNT;
|
||||
if (hooks->addr_check != NULL) {
|
||||
for (int i=0; i < hooks->addr_check_len; i++) {
|
||||
uint32_t elapsed_time = get_ts_elapsed(ts, hooks->addr_check[i].last_timestamp);
|
||||
// lag threshold is max of: 1s and MAX_MISSED_MSGS * expected timestep.
|
||||
// Quite conservative to not risk false triggers.
|
||||
// 2s of lag is worse case, since the function is called at 1Hz
|
||||
bool lagging = elapsed_time > MAX(hooks->addr_check[i].expected_timestep * MAX_MISSED_MSGS, 1e6);
|
||||
hooks->addr_check[i].lagging = lagging;
|
||||
if (lagging) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void update_counter(AddrCheckStruct addr_list[], int index, uint8_t counter) {
|
||||
if (index != -1) {
|
||||
uint8_t expected_counter = (addr_list[index].last_counter + 1U) % (addr_list[index].max_counter + 1U);
|
||||
addr_list[index].wrong_counters += (expected_counter == counter) ? -1 : 1;
|
||||
addr_list[index].wrong_counters = MAX(MIN(addr_list[index].wrong_counters, MAX_WRONG_COUNTERS), 0);
|
||||
addr_list[index].last_counter = counter;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_msg_valid(AddrCheckStruct addr_list[], int index) {
|
||||
bool valid = true;
|
||||
if (index != -1) {
|
||||
if ((!addr_list[index].valid_checksum) || (addr_list[index].wrong_counters >= MAX_WRONG_COUNTERS)) {
|
||||
valid = false;
|
||||
controls_allowed = 0;
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
void update_addr_timestamp(AddrCheckStruct addr_list[], int index) {
|
||||
if (index != -1) {
|
||||
uint32_t ts = TIM2->CNT;
|
||||
addr_list[index].last_timestamp = ts;
|
||||
}
|
||||
}
|
||||
|
||||
bool addr_safety_check(CAN_FIFOMailBox_TypeDef *to_push,
|
||||
AddrCheckStruct *rx_checks,
|
||||
const int rx_checks_len,
|
||||
uint8_t (*get_checksum)(CAN_FIFOMailBox_TypeDef *to_push),
|
||||
uint8_t (*compute_checksum)(CAN_FIFOMailBox_TypeDef *to_push),
|
||||
uint8_t (*get_counter)(CAN_FIFOMailBox_TypeDef *to_push)) {
|
||||
|
||||
int index = get_addr_check_index(to_push, rx_checks, rx_checks_len);
|
||||
update_addr_timestamp(rx_checks, index);
|
||||
|
||||
if (index != -1) {
|
||||
// checksum check
|
||||
if ((get_checksum != NULL) && (compute_checksum != NULL)) {
|
||||
if (rx_checks[index].check_checksum) {
|
||||
uint8_t checksum = get_checksum(to_push);
|
||||
uint8_t checksum_comp = compute_checksum(to_push);
|
||||
rx_checks[index].valid_checksum = checksum_comp == checksum;
|
||||
}
|
||||
}
|
||||
|
||||
// counter check
|
||||
if (get_counter != NULL) {
|
||||
if (rx_checks[index].max_counter > 0U) {
|
||||
uint8_t counter = get_counter(to_push);
|
||||
update_counter(rx_checks, index, counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
return is_msg_valid(rx_checks, index);
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t id;
|
||||
const safety_hooks *hooks;
|
||||
@@ -74,11 +175,12 @@ typedef struct {
|
||||
|
||||
const safety_hook_config safety_hook_registry[] = {
|
||||
{SAFETY_SILENT, &nooutput_hooks},
|
||||
{SAFETY_HONDA, &honda_hooks},
|
||||
{SAFETY_HONDA_NIDEC, &honda_nidec_hooks},
|
||||
{SAFETY_TOYOTA, &toyota_hooks},
|
||||
{SAFETY_ELM327, &elm327_hooks},
|
||||
{SAFETY_GM, &gm_hooks},
|
||||
{SAFETY_HONDA_BOSCH, &honda_bosch_hooks},
|
||||
{SAFETY_HONDA_BOSCH_GIRAFFE, &honda_bosch_giraffe_hooks},
|
||||
{SAFETY_HONDA_BOSCH_HARNESS, &honda_bosch_harness_hooks},
|
||||
{SAFETY_HYUNDAI, &hyundai_hooks},
|
||||
{SAFETY_CHRYSLER, &chrysler_hooks},
|
||||
{SAFETY_SUBARU, &subaru_hooks},
|
||||
@@ -113,12 +215,6 @@ int set_safety_hooks(uint16_t mode, int16_t param) {
|
||||
return set_status;
|
||||
}
|
||||
|
||||
// compute the time elapsed (in microseconds) from 2 counter samples
|
||||
// case where ts < ts_last is ok: overflow is properly re-casted into uint32_t
|
||||
uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last) {
|
||||
return ts - ts_last;
|
||||
}
|
||||
|
||||
// convert a trimmed integer to signed 32 bit int
|
||||
int to_signed(int d, int bits) {
|
||||
int d_signed = d;
|
||||
|
||||
@@ -23,7 +23,7 @@ int cadillac_get_torque_idx(int addr, int array_size) {
|
||||
return MIN(MAX(addr - 0x151, 0), array_size); // 0x151 is id 0, 0x152 is id 1 and so on...
|
||||
}
|
||||
|
||||
static void cadillac_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int cadillac_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -51,6 +51,7 @@ static void cadillac_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
if ((addr == 0x152) || (addr == 0x154)) {
|
||||
cadillac_supercruise_on = (GET_BYTE(to_push, 4) & 0x10) != 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
@@ -58,7 +59,7 @@ static int cadillac_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (!addr_allowed(addr, bus, CADILLAC_TX_MSGS, sizeof(CADILLAC_TX_MSGS) / sizeof(CADILLAC_TX_MSGS[0]))) {
|
||||
if (!msg_allowed(addr, bus, CADILLAC_TX_MSGS, sizeof(CADILLAC_TX_MSGS) / sizeof(CADILLAC_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,13 +6,20 @@ const int CHRYSLER_MAX_RATE_DOWN = 3;
|
||||
const int CHRYSLER_MAX_TORQUE_ERROR = 80; // max torque cmd in excess of torque motor
|
||||
const AddrBus CHRYSLER_TX_MSGS[] = {{571, 0}, {658, 0}, {678, 0}};
|
||||
|
||||
// TODO: do checksum and counter checks
|
||||
AddrCheckStruct chrysler_rx_checks[] = {
|
||||
{.addr = {544}, .bus = 0, .expected_timestep = 10000U},
|
||||
{.addr = {500}, .bus = 0, .expected_timestep = 20000U},
|
||||
};
|
||||
const int CHRYSLER_RX_CHECK_LEN = sizeof(chrysler_rx_checks) / sizeof(chrysler_rx_checks[0]);
|
||||
|
||||
int chrysler_rt_torque_last = 0;
|
||||
int chrysler_desired_torque_last = 0;
|
||||
int chrysler_cruise_engaged_last = 0;
|
||||
uint32_t chrysler_ts_last = 0;
|
||||
struct sample_t chrysler_torque_meas; // last few torques measured
|
||||
|
||||
static void chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -36,10 +43,13 @@ static void chrysler_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
chrysler_cruise_engaged_last = cruise_engaged;
|
||||
}
|
||||
|
||||
// TODO: add gas pressed check
|
||||
|
||||
// check if stock camera ECU is on bus 0
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && (addr == 0x292)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
@@ -48,7 +58,7 @@ static int chrysler_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (!addr_allowed(addr, bus, CHRYSLER_TX_MSGS, sizeof(CHRYSLER_TX_MSGS) / sizeof(CHRYSLER_TX_MSGS[0]))) {
|
||||
if (!msg_allowed(addr, bus, CHRYSLER_TX_MSGS, sizeof(CHRYSLER_TX_MSGS) / sizeof(CHRYSLER_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
@@ -137,4 +147,6 @@ const safety_hooks chrysler_hooks = {
|
||||
.tx = chrysler_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = chrysler_fwd_hook,
|
||||
.addr_check = chrysler_rx_checks,
|
||||
.addr_check_len = sizeof(chrysler_rx_checks) / sizeof(chrysler_rx_checks[0]),
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
void default_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int default_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
UNUSED(to_push);
|
||||
return true;
|
||||
}
|
||||
|
||||
// *** no output safety mode ***
|
||||
|
||||
@@ -12,7 +12,7 @@ static int elm327_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
//Check valid 29 bit send addresses for ISO 15765-4
|
||||
//Check valid 11 bit send addresses for ISO 15765-4
|
||||
if ((addr != 0x18DB33F1) && ((addr & 0x1FFF00FF) != 0x18DA00F1) &&
|
||||
((addr != 0x7DF) && ((addr & 0x1FFFFFF8) != 0x7E0))) {
|
||||
((addr & 0x1FFFFF00) != 0x700)) {
|
||||
tx = 0;
|
||||
}
|
||||
return tx;
|
||||
|
||||
@@ -11,7 +11,7 @@ int ford_brake_prev = 0;
|
||||
int ford_gas_prev = 0;
|
||||
bool ford_moving = false;
|
||||
|
||||
static void ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
int addr = GET_ADDR(to_push);
|
||||
int bus = GET_BUS(to_push);
|
||||
@@ -58,6 +58,7 @@ static void ford_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && (addr == 0x3CA)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// all commands: just steering
|
||||
|
||||
@@ -23,6 +23,16 @@ const AddrBus GM_TX_MSGS[] = {{384, 0}, {1033, 0}, {1034, 0}, {715, 0}, {880, 0}
|
||||
{789, 2}, // ch bus
|
||||
{0x104c006c, 3}, {0x10400060, 3}}; // gmlan
|
||||
|
||||
// TODO: do checksum and counter checks. Add correct timestep, 0.1s for now.
|
||||
AddrCheckStruct gm_rx_checks[] = {
|
||||
{.addr = {388}, .bus = 0, .expected_timestep = 100000U},
|
||||
{.addr = {842}, .bus = 0, .expected_timestep = 100000U},
|
||||
{.addr = {481}, .bus = 0, .expected_timestep = 100000U},
|
||||
{.addr = {241}, .bus = 0, .expected_timestep = 100000U},
|
||||
{.addr = {417}, .bus = 0, .expected_timestep = 100000U},
|
||||
};
|
||||
const int GM_RX_CHECK_LEN = sizeof(gm_rx_checks) / sizeof(gm_rx_checks[0]);
|
||||
|
||||
int gm_brake_prev = 0;
|
||||
int gm_gas_prev = 0;
|
||||
bool gm_moving = false;
|
||||
@@ -31,7 +41,7 @@ int gm_desired_torque_last = 0;
|
||||
uint32_t gm_ts_last = 0;
|
||||
struct sample_t gm_torque_driver; // last few driver torques measured
|
||||
|
||||
static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -82,7 +92,7 @@ static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// exit controls on rising edge of gas press
|
||||
if (addr == 417) {
|
||||
int gas = GET_BYTE(to_push, 6);
|
||||
if (gas && !gm_gas_prev && long_controls_allowed) {
|
||||
if (gas && !gm_gas_prev) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
gm_gas_prev = gas;
|
||||
@@ -103,6 +113,7 @@ static void gm_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && ((addr == 384) || (addr == 715))) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// all commands: gas/regen, friction brake and steering
|
||||
@@ -117,7 +128,7 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (!addr_allowed(addr, bus, GM_TX_MSGS, sizeof(GM_TX_MSGS)/sizeof(GM_TX_MSGS[0]))) {
|
||||
if (!msg_allowed(addr, bus, GM_TX_MSGS, sizeof(GM_TX_MSGS)/sizeof(GM_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
@@ -134,7 +145,7 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
if (addr == 789) {
|
||||
int brake = ((GET_BYTE(to_send, 0) & 0xFU) << 8) + GET_BYTE(to_send, 1);
|
||||
brake = (0x1000 - brake) & 0xFFF;
|
||||
if (!current_controls_allowed || !long_controls_allowed) {
|
||||
if (!current_controls_allowed) {
|
||||
if (brake != 0) {
|
||||
tx = 0;
|
||||
}
|
||||
@@ -197,7 +208,7 @@ static int gm_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int gas_regen = ((GET_BYTE(to_send, 2) & 0x7FU) << 5) + ((GET_BYTE(to_send, 3) & 0xF8U) >> 3);
|
||||
// Disabled message is !engaged with gas
|
||||
// value that corresponds to max regen.
|
||||
if (!current_controls_allowed || !long_controls_allowed) {
|
||||
if (!current_controls_allowed) {
|
||||
bool apply = GET_BYTE(to_send, 0) & 1U;
|
||||
if (apply || (gas_regen != GM_MAX_REGEN)) {
|
||||
tx = 0;
|
||||
@@ -219,4 +230,6 @@ const safety_hooks gm_hooks = {
|
||||
.tx = gm_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = default_fwd_hook,
|
||||
.addr_check = gm_rx_checks,
|
||||
.addr_check_len = sizeof(gm_rx_checks) / sizeof(gm_rx_checks[0]),
|
||||
};
|
||||
|
||||
@@ -41,4 +41,3 @@ const safety_hooks gm_ascm_hooks = {
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = gm_ascm_fwd_hook,
|
||||
};
|
||||
|
||||
|
||||
+179
-108
@@ -7,109 +7,165 @@
|
||||
// brake rising edge
|
||||
// brake > 0mph
|
||||
const AddrBus HONDA_N_TX_MSGS[] = {{0xE4, 0}, {0x194, 0}, {0x1FA, 0}, {0x200, 0}, {0x30C, 0}, {0x33D, 0}};
|
||||
const AddrBus HONDA_BH_TX_MSGS[] = {{0xE4, 0}, {0x296, 1}, {0x33D, 0}}; // Bosch Harness
|
||||
const AddrBus HONDA_BG_TX_MSGS[] = {{0xE4, 2}, {0x296, 0}, {0x33D, 2}}; // Bosch Giraffe
|
||||
const AddrBus HONDA_BH_TX_MSGS[] = {{0xE4, 0}, {0x296, 1}, {0x33D, 0}}; // Bosch Harness
|
||||
const int HONDA_GAS_INTERCEPTOR_THRESHOLD = 328; // ratio between offset and gain from dbc file
|
||||
|
||||
// Nidec and Bosch giraffe have pt on bus 0
|
||||
AddrCheckStruct honda_rx_checks[] = {
|
||||
{.addr = {0x1A6, 0x296}, .bus = 0, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U},
|
||||
{.addr = { 0x158}, .bus = 0, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U},
|
||||
{.addr = { 0x17C}, .bus = 0, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U},
|
||||
};
|
||||
const int HONDA_RX_CHECKS_LEN = sizeof(honda_rx_checks) / sizeof(honda_rx_checks[0]);
|
||||
|
||||
// Bosch harness has pt on bus 1
|
||||
AddrCheckStruct honda_bh_rx_checks[] = {
|
||||
{.addr = {0x296}, .bus = 1, .check_checksum = true, .max_counter = 3U, .expected_timestep = 40000U},
|
||||
{.addr = {0x158}, .bus = 1, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U},
|
||||
{.addr = {0x17C}, .bus = 1, .check_checksum = true, .max_counter = 3U, .expected_timestep = 10000U},
|
||||
};
|
||||
const int HONDA_BH_RX_CHECKS_LEN = sizeof(honda_bh_rx_checks) / sizeof(honda_bh_rx_checks[0]);
|
||||
|
||||
int honda_brake = 0;
|
||||
int honda_gas_prev = 0;
|
||||
bool honda_brake_pressed_prev = false;
|
||||
bool honda_moving = false;
|
||||
bool honda_bosch_hardware = false;
|
||||
bool honda_alt_brake_msg = false;
|
||||
bool honda_fwd_brake = false;
|
||||
enum {HONDA_N_HW, HONDA_BG_HW, HONDA_BH_HW} honda_hw = HONDA_N_HW;
|
||||
|
||||
static void honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
int addr = GET_ADDR(to_push);
|
||||
static uint8_t honda_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int checksum_byte = GET_LEN(to_push) - 1;
|
||||
return (uint8_t)(GET_BYTE(to_push, checksum_byte)) & 0xFU;
|
||||
}
|
||||
|
||||
static uint8_t honda_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int len = GET_LEN(to_push);
|
||||
int bus = GET_BUS(to_push);
|
||||
uint8_t checksum = 0U;
|
||||
unsigned int addr = GET_ADDR(to_push);
|
||||
while (addr > 0U) {
|
||||
checksum += (addr & 0xFU); addr >>= 4;
|
||||
}
|
||||
for (int j = 0; (j < len); j++) {
|
||||
uint8_t byte = GET_BYTE(to_push, j);
|
||||
checksum += (byte & 0xFU) + (byte >> 4U);
|
||||
if (j == (len - 1)) {
|
||||
checksum -= (byte & 0xFU); // remove checksum in message
|
||||
}
|
||||
}
|
||||
return (8U - checksum) & 0xFU;
|
||||
}
|
||||
|
||||
// sample speed
|
||||
if (addr == 0x158) {
|
||||
// first 2 bytes
|
||||
honda_moving = GET_BYTE(to_push, 0) | GET_BYTE(to_push, 1);
|
||||
static uint8_t honda_get_counter(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int counter_byte = GET_LEN(to_push) - 1;
|
||||
return ((uint8_t)(GET_BYTE(to_push, counter_byte)) >> 4U) & 0x3U;
|
||||
}
|
||||
|
||||
static int honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
bool valid;
|
||||
if (honda_hw == HONDA_BH_HW) {
|
||||
valid = addr_safety_check(to_push, honda_bh_rx_checks, HONDA_BH_RX_CHECKS_LEN,
|
||||
honda_get_checksum, honda_compute_checksum, honda_get_counter);
|
||||
} else {
|
||||
valid = addr_safety_check(to_push, honda_rx_checks, HONDA_RX_CHECKS_LEN,
|
||||
honda_get_checksum, honda_compute_checksum, honda_get_counter);
|
||||
}
|
||||
|
||||
// state machine to enter and exit controls
|
||||
// 0x1A6 for the ILX, 0x296 for the Civic Touring
|
||||
if ((addr == 0x1A6) || (addr == 0x296)) {
|
||||
int button = (GET_BYTE(to_push, 0) & 0xE0) >> 5;
|
||||
switch (button) {
|
||||
case 2: // cancel
|
||||
if (valid) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
int len = GET_LEN(to_push);
|
||||
int bus = GET_BUS(to_push);
|
||||
|
||||
// sample speed
|
||||
if (addr == 0x158) {
|
||||
// first 2 bytes
|
||||
honda_moving = GET_BYTE(to_push, 0) | GET_BYTE(to_push, 1);
|
||||
}
|
||||
|
||||
// state machine to enter and exit controls
|
||||
// 0x1A6 for the ILX, 0x296 for the Civic Touring
|
||||
if ((addr == 0x1A6) || (addr == 0x296)) {
|
||||
int button = (GET_BYTE(to_push, 0) & 0xE0) >> 5;
|
||||
switch (button) {
|
||||
case 2: // cancel
|
||||
controls_allowed = 0;
|
||||
break;
|
||||
case 3: // set
|
||||
case 4: // resume
|
||||
controls_allowed = 1;
|
||||
break;
|
||||
default:
|
||||
break; // any other button is irrelevant
|
||||
}
|
||||
}
|
||||
|
||||
// user brake signal on 0x17C reports applied brake from computer brake on accord
|
||||
// and crv, which prevents the usual brake safety from working correctly. these
|
||||
// cars have a signal on 0x1BE which only detects user's brake being applied so
|
||||
// in these cases, this is used instead.
|
||||
// most hondas: 0x17C bit 53
|
||||
// accord, crv: 0x1BE bit 4
|
||||
// exit controls on rising edge of brake press or on brake press when speed > 0
|
||||
bool is_user_brake_msg = honda_alt_brake_msg ? ((addr) == 0x1BE) : ((addr) == 0x17C);
|
||||
if (is_user_brake_msg) {
|
||||
bool brake_pressed = honda_alt_brake_msg ? (GET_BYTE((to_push), 0) & 0x10) : (GET_BYTE((to_push), 6) & 0x20);
|
||||
if (brake_pressed && (!(honda_brake_pressed_prev) || honda_moving)) {
|
||||
controls_allowed = 0;
|
||||
break;
|
||||
case 3: // set
|
||||
case 4: // resume
|
||||
controls_allowed = 1;
|
||||
break;
|
||||
default:
|
||||
break; // any other button is irrelevant
|
||||
}
|
||||
honda_brake_pressed_prev = brake_pressed;
|
||||
}
|
||||
}
|
||||
|
||||
// user brake signal on 0x17C reports applied brake from computer brake on accord
|
||||
// and crv, which prevents the usual brake safety from working correctly. these
|
||||
// cars have a signal on 0x1BE which only detects user's brake being applied so
|
||||
// in these cases, this is used instead.
|
||||
// most hondas: 0x17C bit 53
|
||||
// accord, crv: 0x1BE bit 4
|
||||
// exit controls on rising edge of brake press or on brake press when speed > 0
|
||||
bool is_user_brake_msg = honda_alt_brake_msg ? ((addr) == 0x1BE) : ((addr) == 0x17C);
|
||||
if (is_user_brake_msg) {
|
||||
bool brake_pressed = honda_alt_brake_msg ? (GET_BYTE((to_push), 0) & 0x10) : (GET_BYTE((to_push), 6) & 0x20);
|
||||
if (brake_pressed && (!(honda_brake_pressed_prev) || honda_moving)) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
honda_brake_pressed_prev = brake_pressed;
|
||||
}
|
||||
|
||||
// exit controls on rising edge of gas press if interceptor (0x201 w/ len = 6)
|
||||
// length check because bosch hardware also uses this id (0x201 w/ len = 8)
|
||||
if ((addr == 0x201) && (len == 6)) {
|
||||
gas_interceptor_detected = 1;
|
||||
int gas_interceptor = GET_INTERCEPTOR(to_push);
|
||||
if ((gas_interceptor > HONDA_GAS_INTERCEPTOR_THRESHOLD) &&
|
||||
(gas_interceptor_prev <= HONDA_GAS_INTERCEPTOR_THRESHOLD) &&
|
||||
long_controls_allowed) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
gas_interceptor_prev = gas_interceptor;
|
||||
}
|
||||
|
||||
// exit controls on rising edge of gas press if no interceptor
|
||||
if (!gas_interceptor_detected) {
|
||||
if (addr == 0x17C) {
|
||||
int gas = GET_BYTE(to_push, 0);
|
||||
if (gas && !(honda_gas_prev) && long_controls_allowed) {
|
||||
// exit controls on rising edge of gas press if interceptor (0x201 w/ len = 6)
|
||||
// length check because bosch hardware also uses this id (0x201 w/ len = 8)
|
||||
if ((addr == 0x201) && (len == 6)) {
|
||||
gas_interceptor_detected = 1;
|
||||
int gas_interceptor = GET_INTERCEPTOR(to_push);
|
||||
if ((gas_interceptor > HONDA_GAS_INTERCEPTOR_THRESHOLD) &&
|
||||
(gas_interceptor_prev <= HONDA_GAS_INTERCEPTOR_THRESHOLD)) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
honda_gas_prev = gas;
|
||||
gas_interceptor_prev = gas_interceptor;
|
||||
}
|
||||
}
|
||||
if ((bus == 2) && (addr == 0x1FA)) {
|
||||
bool honda_stock_aeb = GET_BYTE(to_push, 3) & 0x20;
|
||||
int honda_stock_brake = (GET_BYTE(to_push, 0) << 2) + ((GET_BYTE(to_push, 1) >> 6) & 0x3);
|
||||
|
||||
// Forward AEB when stock braking is higher than openpilot braking
|
||||
// only stop forwarding when AEB event is over
|
||||
if (!honda_stock_aeb) {
|
||||
honda_fwd_brake = false;
|
||||
} else if (honda_stock_brake >= honda_brake) {
|
||||
honda_fwd_brake = true;
|
||||
} else {
|
||||
// Leave Honda forward brake as is
|
||||
// exit controls on rising edge of gas press if no interceptor
|
||||
if (!gas_interceptor_detected) {
|
||||
if (addr == 0x17C) {
|
||||
int gas = GET_BYTE(to_push, 0);
|
||||
if (gas && !honda_gas_prev) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
honda_gas_prev = gas;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((bus == 2) && (addr == 0x1FA)) {
|
||||
bool honda_stock_aeb = GET_BYTE(to_push, 3) & 0x20;
|
||||
int honda_stock_brake = (GET_BYTE(to_push, 0) << 2) + ((GET_BYTE(to_push, 1) >> 6) & 0x3);
|
||||
|
||||
// if steering controls messages are received on the destination bus, it's an indication
|
||||
// that the relay might be malfunctioning
|
||||
int bus_rdr_car = (board_has_relay()) ? 0 : 2; // radar bus, car side
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && ((addr == 0xE4) || (addr == 0x194))) {
|
||||
if ((honda_bosch_hardware && (bus == bus_rdr_car)) ||
|
||||
(!honda_bosch_hardware && (bus == 0))) {
|
||||
relay_malfunction = true;
|
||||
// Forward AEB when stock braking is higher than openpilot braking
|
||||
// only stop forwarding when AEB event is over
|
||||
if (!honda_stock_aeb) {
|
||||
honda_fwd_brake = false;
|
||||
} else if (honda_stock_brake >= honda_brake) {
|
||||
honda_fwd_brake = true;
|
||||
} else {
|
||||
// Leave Honda forward brake as is
|
||||
}
|
||||
}
|
||||
|
||||
// if steering controls messages are received on the destination bus, it's an indication
|
||||
// that the relay might be malfunctioning
|
||||
int bus_rdr_car = (honda_hw == HONDA_BH_HW) ? 0 : 2; // radar bus, car side
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && ((addr == 0xE4) || (addr == 0x194))) {
|
||||
if (((honda_hw != HONDA_N_HW) && (bus == bus_rdr_car)) ||
|
||||
((honda_hw == HONDA_N_HW) && (bus == 0))) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
// all commands: gas, brake and steering
|
||||
@@ -124,16 +180,12 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (honda_bosch_hardware) {
|
||||
if (board_has_relay() && !addr_allowed(addr, bus, HONDA_BH_TX_MSGS, sizeof(HONDA_BH_TX_MSGS)/sizeof(HONDA_BH_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
if (!board_has_relay() && !addr_allowed(addr, bus, HONDA_BG_TX_MSGS, sizeof(HONDA_BG_TX_MSGS)/sizeof(HONDA_BG_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
}
|
||||
if (!honda_bosch_hardware && !addr_allowed(addr, bus, HONDA_N_TX_MSGS, sizeof(HONDA_N_TX_MSGS)/sizeof(HONDA_N_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
if (honda_hw == HONDA_BG_HW) {
|
||||
tx = msg_allowed(addr, bus, HONDA_BG_TX_MSGS, sizeof(HONDA_BG_TX_MSGS)/sizeof(HONDA_BG_TX_MSGS[0]));
|
||||
} else if (honda_hw == HONDA_BH_HW) {
|
||||
tx = msg_allowed(addr, bus, HONDA_BH_TX_MSGS, sizeof(HONDA_BH_TX_MSGS)/sizeof(HONDA_BH_TX_MSGS[0]));
|
||||
} else {
|
||||
tx = msg_allowed(addr, bus, HONDA_N_TX_MSGS, sizeof(HONDA_N_TX_MSGS)/sizeof(HONDA_N_TX_MSGS[0]));
|
||||
}
|
||||
|
||||
if (relay_malfunction) {
|
||||
@@ -150,7 +202,7 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
// BRAKE: safety check
|
||||
if ((addr == 0x1FA) && (bus == 0)) {
|
||||
honda_brake = (GET_BYTE(to_send, 0) << 2) + ((GET_BYTE(to_send, 1) >> 6) & 0x3);
|
||||
if (!current_controls_allowed || !long_controls_allowed) {
|
||||
if (!current_controls_allowed) {
|
||||
if (honda_brake != 0) {
|
||||
tx = 0;
|
||||
}
|
||||
@@ -175,7 +227,7 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
// GAS: safety check
|
||||
if (addr == 0x200) {
|
||||
if (!current_controls_allowed || !long_controls_allowed) {
|
||||
if (!current_controls_allowed) {
|
||||
if (GET_BYTE(to_send, 0) || GET_BYTE(to_send, 1)) {
|
||||
tx = 0;
|
||||
}
|
||||
@@ -185,9 +237,8 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
// FORCE CANCEL: safety check only relevant when spamming the cancel button in Bosch HW
|
||||
// ensuring that only the cancel button press is sent (VAL 2) when controls are off.
|
||||
// This avoids unintended engagements while still allowing resume spam
|
||||
int bus_pt = ((board_has_relay()) && honda_bosch_hardware)? 1 : 0;
|
||||
if ((addr == 0x296) && honda_bosch_hardware &&
|
||||
!current_controls_allowed && (bus == bus_pt)) {
|
||||
int bus_pt = (honda_hw == HONDA_BH_HW)? 1 : 0;
|
||||
if ((addr == 0x296) && !current_controls_allowed && (bus == bus_pt)) {
|
||||
if (((GET_BYTE(to_send, 0) >> 5) & 0x7) != 2) {
|
||||
tx = 0;
|
||||
}
|
||||
@@ -197,23 +248,31 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
return tx;
|
||||
}
|
||||
|
||||
static void honda_init(int16_t param) {
|
||||
static void honda_nidec_init(int16_t param) {
|
||||
UNUSED(param);
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
honda_bosch_hardware = false;
|
||||
honda_hw = HONDA_N_HW;
|
||||
honda_alt_brake_msg = false;
|
||||
}
|
||||
|
||||
static void honda_bosch_init(int16_t param) {
|
||||
static void honda_bosch_giraffe_init(int16_t param) {
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
honda_bosch_hardware = true;
|
||||
honda_hw = HONDA_BG_HW;
|
||||
// Checking for alternate brake override from safety parameter
|
||||
honda_alt_brake_msg = (param == 1) ? true : false;
|
||||
}
|
||||
|
||||
static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
static void honda_bosch_harness_init(int16_t param) {
|
||||
controls_allowed = false;
|
||||
relay_malfunction = false;
|
||||
honda_hw = HONDA_BH_HW;
|
||||
// Checking for alternate brake override from safety parameter
|
||||
honda_alt_brake_msg = (param == 1) ? true : false;
|
||||
}
|
||||
|
||||
static int honda_nidec_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
// fwd from car to camera. also fwd certain msgs from camera to car
|
||||
// 0xE4 is steering on all cars except CRV and RDX, 0x194 for CRV and RDX,
|
||||
// 0x1FA is brake control, 0x30C is acc hud, 0x33D is lkas hud,
|
||||
@@ -229,9 +288,7 @@ static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
bool is_lkas_msg = (addr == 0xE4) || (addr == 0x194) || (addr == 0x33D);
|
||||
bool is_acc_hud_msg = addr == 0x30C;
|
||||
bool is_brake_msg = addr == 0x1FA;
|
||||
bool block_fwd = is_lkas_msg ||
|
||||
(is_acc_hud_msg && long_controls_allowed) ||
|
||||
(is_brake_msg && long_controls_allowed && !honda_fwd_brake);
|
||||
bool block_fwd = is_lkas_msg || is_acc_hud_msg || (is_brake_msg && !honda_fwd_brake);
|
||||
if (!block_fwd) {
|
||||
bus_fwd = 0;
|
||||
}
|
||||
@@ -242,8 +299,8 @@ static int honda_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
|
||||
static int honda_bosch_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
int bus_fwd = -1;
|
||||
int bus_rdr_cam = (board_has_relay()) ? 2 : 1; // radar bus, camera side
|
||||
int bus_rdr_car = (board_has_relay()) ? 0 : 2; // radar bus, car side
|
||||
int bus_rdr_cam = (honda_hw == HONDA_BH_HW) ? 2 : 1; // radar bus, camera side
|
||||
int bus_rdr_car = (honda_hw == HONDA_BH_HW) ? 0 : 2; // radar bus, car side
|
||||
|
||||
if (!relay_malfunction) {
|
||||
if (bus_num == bus_rdr_car) {
|
||||
@@ -260,18 +317,32 @@ static int honda_bosch_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
return bus_fwd;
|
||||
}
|
||||
|
||||
const safety_hooks honda_hooks = {
|
||||
.init = honda_init,
|
||||
const safety_hooks honda_nidec_hooks = {
|
||||
.init = honda_nidec_init,
|
||||
.rx = honda_rx_hook,
|
||||
.tx = honda_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = honda_fwd_hook,
|
||||
.fwd = honda_nidec_fwd_hook,
|
||||
.addr_check = honda_rx_checks,
|
||||
.addr_check_len = sizeof(honda_rx_checks) / sizeof(honda_rx_checks[0]),
|
||||
};
|
||||
|
||||
const safety_hooks honda_bosch_hooks = {
|
||||
.init = honda_bosch_init,
|
||||
const safety_hooks honda_bosch_giraffe_hooks = {
|
||||
.init = honda_bosch_giraffe_init,
|
||||
.rx = honda_rx_hook,
|
||||
.tx = honda_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = honda_bosch_fwd_hook,
|
||||
.addr_check = honda_rx_checks,
|
||||
.addr_check_len = sizeof(honda_rx_checks) / sizeof(honda_rx_checks[0]),
|
||||
};
|
||||
|
||||
const safety_hooks honda_bosch_harness_hooks = {
|
||||
.init = honda_bosch_harness_init,
|
||||
.rx = honda_rx_hook,
|
||||
.tx = honda_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = honda_bosch_fwd_hook,
|
||||
.addr_check = honda_bh_rx_checks,
|
||||
.addr_check_len = sizeof(honda_bh_rx_checks) / sizeof(honda_bh_rx_checks[0]),
|
||||
};
|
||||
|
||||
@@ -5,16 +5,22 @@ const int HYUNDAI_MAX_RATE_UP = 3;
|
||||
const int HYUNDAI_MAX_RATE_DOWN = 7;
|
||||
const int HYUNDAI_DRIVER_TORQUE_ALLOWANCE = 50;
|
||||
const int HYUNDAI_DRIVER_TORQUE_FACTOR = 2;
|
||||
|
||||
const AddrBus HYUNDAI_TX_MSGS[] = {{832, 0}, {1265, 0}};
|
||||
|
||||
// TODO: do checksum and counter checks
|
||||
AddrCheckStruct hyundai_rx_checks[] = {
|
||||
{.addr = {897}, .bus = 0, .expected_timestep = 10000U},
|
||||
{.addr = {1057}, .bus = 0, .expected_timestep = 20000U},
|
||||
};
|
||||
const int HYUNDAI_RX_CHECK_LEN = sizeof(hyundai_rx_checks) / sizeof(hyundai_rx_checks[0]);
|
||||
|
||||
int hyundai_rt_torque_last = 0;
|
||||
int hyundai_desired_torque_last = 0;
|
||||
int hyundai_cruise_engaged_last = 0;
|
||||
uint32_t hyundai_ts_last = 0;
|
||||
struct sample_t hyundai_torque_driver; // last few driver torques measured
|
||||
|
||||
static void hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -24,11 +30,6 @@ static void hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
update_sample(&hyundai_torque_driver, torque_driver_new);
|
||||
}
|
||||
|
||||
// check if stock camera ECU is on bus 0
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && (addr == 832)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
|
||||
// enter controls on rising edge of ACC, exit controls on ACC off
|
||||
if (addr == 1057) {
|
||||
// 2 bits: 13-14
|
||||
@@ -41,6 +42,14 @@ static void hyundai_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
}
|
||||
hyundai_cruise_engaged_last = cruise_engaged;
|
||||
}
|
||||
|
||||
// TODO: check gas pressed
|
||||
|
||||
// check if stock camera ECU is on bus 0
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && (addr == 832)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
@@ -49,7 +58,7 @@ static int hyundai_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (!addr_allowed(addr, bus, HYUNDAI_TX_MSGS, sizeof(HYUNDAI_TX_MSGS)/sizeof(HYUNDAI_TX_MSGS[0]))) {
|
||||
if (!msg_allowed(addr, bus, HYUNDAI_TX_MSGS, sizeof(HYUNDAI_TX_MSGS)/sizeof(HYUNDAI_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
@@ -140,4 +149,6 @@ const safety_hooks hyundai_hooks = {
|
||||
.tx = hyundai_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = hyundai_fwd_hook,
|
||||
.addr_check = hyundai_rx_checks,
|
||||
.addr_check_len = sizeof(hyundai_rx_checks) / sizeof(hyundai_rx_checks[0]),
|
||||
};
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
#define MAZDA_DRIVER_TORQUE_ALLOWANCE 15
|
||||
#define MAZDA_DRIVER_TORQUE_FACTOR 1
|
||||
|
||||
|
||||
int mazda_cruise_engaged_last = 0;
|
||||
int mazda_rt_torque_last = 0;
|
||||
int mazda_desired_torque_last = 0;
|
||||
@@ -30,7 +29,7 @@ uint32_t mazda_ts_last = 0;
|
||||
struct sample_t mazda_torque_driver; // last few driver torques measured
|
||||
|
||||
// track msgs coming from OP so that we know what CAM msgs to drop and what to forward
|
||||
void mazda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int mazda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -58,6 +57,7 @@ void mazda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == MAZDA_CAM) && (addr == MAZDA_WHEEL_SPEED)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mazda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
@@ -146,4 +146,5 @@ const safety_hooks mazda_hooks = {
|
||||
.tx = mazda_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = mazda_fwd_hook,
|
||||
// TODO: add addr safety checks
|
||||
};
|
||||
|
||||
@@ -10,13 +10,20 @@ const int SUBARU_DRIVER_TORQUE_FACTOR = 10;
|
||||
|
||||
const AddrBus SUBARU_TX_MSGS[] = {{0x122, 0}, {0x164, 0}, {0x221, 0}, {0x322, 0}};
|
||||
|
||||
// TODO: do checksum and counter checks after adding the signals to the outback dbc file
|
||||
AddrCheckStruct subaru_rx_checks[] = {
|
||||
{.addr = {0x119, 0x371}, .bus = 0, .expected_timestep = 20000U},
|
||||
{.addr = {0x240, 0x144}, .bus = 0, .expected_timestep = 50000U},
|
||||
};
|
||||
const int SUBARU_RX_CHECK_LEN = sizeof(subaru_rx_checks) / sizeof(subaru_rx_checks[0]);
|
||||
|
||||
int subaru_cruise_engaged_last = 0;
|
||||
int subaru_rt_torque_last = 0;
|
||||
int subaru_desired_torque_last = 0;
|
||||
uint32_t subaru_ts_last = 0;
|
||||
struct sample_t subaru_torque_driver; // last few driver torques measured
|
||||
|
||||
static void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -41,9 +48,12 @@ static void subaru_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
subaru_cruise_engaged_last = cruise_engaged;
|
||||
}
|
||||
|
||||
// TODO: enforce cancellation on gas pressed
|
||||
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && ((addr == 0x122) || (addr == 0x164))) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
@@ -51,7 +61,7 @@ static int subaru_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (!addr_allowed(addr, bus, SUBARU_TX_MSGS, sizeof(SUBARU_TX_MSGS) / sizeof(SUBARU_TX_MSGS[0]))) {
|
||||
if (!msg_allowed(addr, bus, SUBARU_TX_MSGS, sizeof(SUBARU_TX_MSGS) / sizeof(SUBARU_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
@@ -141,4 +151,6 @@ const safety_hooks subaru_hooks = {
|
||||
.tx = subaru_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = subaru_fwd_hook,
|
||||
.addr_check = subaru_rx_checks,
|
||||
.addr_check_len = sizeof(subaru_rx_checks) / sizeof(subaru_rx_checks[0]),
|
||||
};
|
||||
|
||||
@@ -44,7 +44,7 @@ void reset_gmlan_switch_timeout(void);
|
||||
void gmlan_switch_init(int timeout_enable);
|
||||
|
||||
|
||||
static void tesla_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int tesla_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
set_gmlan_digital_output(0); // #define GMLAN_HIGH 0
|
||||
reset_gmlan_switch_timeout(); //we're still in tesla safety mode, reset the timeout counter and make sure our output is enabled
|
||||
|
||||
@@ -120,6 +120,7 @@ static void tesla_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
tesla_controls_allowed_last = controls_allowed;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// all commands: gas/regen, friction brake and steering
|
||||
|
||||
@@ -18,11 +18,16 @@ const int TOYOTA_MIN_ACCEL = -3000; // 3.0 m/s2
|
||||
|
||||
const int TOYOTA_GAS_INTERCEPTOR_THRESHOLD = 475; // ratio between offset and gain from dbc file
|
||||
|
||||
// allowed DSU messages on bus 0 and 1
|
||||
const AddrBus TOYOTA_TX_MSGS[] = {{0x283, 0}, {0x2E6, 0}, {0x2E7, 0}, {0x33E, 0}, {0x344, 0}, {0x365, 0}, {0x366, 0}, {0x4CB, 0}, // DSU bus 0
|
||||
{0x128, 1}, {0x141, 1}, {0x160, 1}, {0x161, 1}, {0x470, 1}, // DSU bus 1
|
||||
{0x2E4, 0}, {0x411, 0}, {0x412, 0}, {0x343, 0}, {0x1D2, 0}, // LKAS + ACC
|
||||
{0x200, 0}}; // interceptor
|
||||
{0x128, 1}, {0x141, 1}, {0x160, 1}, {0x161, 1}, {0x470, 1}, // DSU bus 1
|
||||
{0x2E4, 0}, {0x411, 0}, {0x412, 0}, {0x343, 0}, {0x1D2, 0}, // LKAS + ACC
|
||||
{0x200, 0}}; // interceptor
|
||||
|
||||
AddrCheckStruct toyota_rx_checks[] = {
|
||||
{.addr = {0x260}, .bus = 0, .check_checksum = true, .max_counter = 0U, .expected_timestep = 20000U},
|
||||
{.addr = {0x1D2}, .bus = 0, .check_checksum = true, .max_counter = 0U, .expected_timestep = 30000U},
|
||||
};
|
||||
const int TOYOTA_RX_CHECKS_LEN = sizeof(toyota_rx_checks) / sizeof(toyota_rx_checks[0]);
|
||||
|
||||
// global actuation limit states
|
||||
int toyota_dbc_eps_torque_factor = 100; // conversion factor for STEER_TORQUE_EPS in %: see dbc file
|
||||
@@ -36,65 +41,84 @@ int toyota_gas_prev = 0;
|
||||
struct sample_t toyota_torque_meas; // last 3 motor torques produced by the eps
|
||||
|
||||
|
||||
static void toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
int bus = GET_BUS(to_push);
|
||||
static uint8_t toyota_compute_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
// get eps motor torque (0.66 factor in dbc)
|
||||
if (addr == 0x260) {
|
||||
int torque_meas_new = (GET_BYTE(to_push, 5) << 8) | GET_BYTE(to_push, 6);
|
||||
torque_meas_new = to_signed(torque_meas_new, 16);
|
||||
|
||||
// scale by dbc_factor
|
||||
torque_meas_new = (torque_meas_new * toyota_dbc_eps_torque_factor) / 100;
|
||||
|
||||
// update array of sample
|
||||
update_sample(&toyota_torque_meas, torque_meas_new);
|
||||
|
||||
// increase torque_meas by 1 to be conservative on rounding
|
||||
toyota_torque_meas.min--;
|
||||
toyota_torque_meas.max++;
|
||||
int len = GET_LEN(to_push);
|
||||
uint8_t checksum = (uint8_t)(addr) + (uint8_t)((unsigned int)(addr) >> 8U) + (uint8_t)(len);
|
||||
for (int i = 0; i < (len - 1); i++) {
|
||||
checksum += (uint8_t)GET_BYTE(to_push, i);
|
||||
}
|
||||
return checksum;
|
||||
}
|
||||
|
||||
// enter controls on rising edge of ACC, exit controls on ACC off
|
||||
if (addr == 0x1D2) {
|
||||
// 5th bit is CRUISE_ACTIVE
|
||||
int cruise_engaged = GET_BYTE(to_push, 0) & 0x20;
|
||||
if (!cruise_engaged) {
|
||||
controls_allowed = 1;
|
||||
static uint8_t toyota_get_checksum(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int checksum_byte = GET_LEN(to_push) - 1;
|
||||
return (uint8_t)(GET_BYTE(to_push, checksum_byte));
|
||||
}
|
||||
|
||||
static int toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
|
||||
bool valid = addr_safety_check(to_push, toyota_rx_checks, TOYOTA_RX_CHECKS_LEN,
|
||||
toyota_get_checksum, toyota_compute_checksum, NULL);
|
||||
if (valid) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
// get eps motor torque (0.66 factor in dbc)
|
||||
if (addr == 0x260) {
|
||||
int torque_meas_new = (GET_BYTE(to_push, 5) << 8) | GET_BYTE(to_push, 6);
|
||||
torque_meas_new = to_signed(torque_meas_new, 16);
|
||||
|
||||
// scale by dbc_factor
|
||||
torque_meas_new = (torque_meas_new * toyota_dbc_eps_torque_factor) / 100;
|
||||
|
||||
// update array of sample
|
||||
update_sample(&toyota_torque_meas, torque_meas_new);
|
||||
|
||||
// increase torque_meas by 1 to be conservative on rounding
|
||||
toyota_torque_meas.min--;
|
||||
toyota_torque_meas.max++;
|
||||
}
|
||||
if (cruise_engaged && !toyota_cruise_engaged_last) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
toyota_cruise_engaged_last = cruise_engaged;
|
||||
}
|
||||
|
||||
// exit controls on rising edge of interceptor gas press
|
||||
if (addr == 0x201) {
|
||||
gas_interceptor_detected = 1;
|
||||
int gas_interceptor = GET_INTERCEPTOR(to_push);
|
||||
if ((gas_interceptor > TOYOTA_GAS_INTERCEPTOR_THRESHOLD) &&
|
||||
(gas_interceptor_prev <= TOYOTA_GAS_INTERCEPTOR_THRESHOLD) &&
|
||||
long_controls_allowed) {
|
||||
controls_allowed = 1;
|
||||
// enter controls on rising edge of ACC, exit controls on ACC off
|
||||
if (addr == 0x1D2) {
|
||||
// 5th bit is CRUISE_ACTIVE
|
||||
int cruise_engaged = GET_BYTE(to_push, 0) & 0x20;
|
||||
if (!cruise_engaged) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
if (cruise_engaged && !toyota_cruise_engaged_last) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
toyota_cruise_engaged_last = cruise_engaged;
|
||||
}
|
||||
gas_interceptor_prev = gas_interceptor;
|
||||
}
|
||||
|
||||
// exit controls on rising edge of gas press
|
||||
if (addr == 0x2C1) {
|
||||
int gas = GET_BYTE(to_push, 6) & 0xFF;
|
||||
if ((gas > 0) && (toyota_gas_prev == 0) && !gas_interceptor_detected && long_controls_allowed) {
|
||||
controls_allowed = 1;
|
||||
// exit controls on rising edge of interceptor gas press
|
||||
if (addr == 0x201) {
|
||||
gas_interceptor_detected = 1;
|
||||
int gas_interceptor = GET_INTERCEPTOR(to_push);
|
||||
if ((gas_interceptor > TOYOTA_GAS_INTERCEPTOR_THRESHOLD) &&
|
||||
(gas_interceptor_prev <= TOYOTA_GAS_INTERCEPTOR_THRESHOLD)) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
gas_interceptor_prev = gas_interceptor;
|
||||
}
|
||||
toyota_gas_prev = gas;
|
||||
}
|
||||
|
||||
// 0x2E4 is lkas cmd. If it is on bus 0, then relay is unexpectedly closed
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (addr == 0x2E4) && (bus == 0)) {
|
||||
relay_malfunction = true;
|
||||
// exit controls on rising edge of gas press
|
||||
if (addr == 0x2C1) {
|
||||
int gas = GET_BYTE(to_push, 6) & 0xFF;
|
||||
if ((gas > 0) && (toyota_gas_prev == 0) && !gas_interceptor_detected) {
|
||||
controls_allowed = 1;
|
||||
}
|
||||
toyota_gas_prev = gas;
|
||||
}
|
||||
|
||||
// 0x2E4 is lkas cmd. If it is on bus 0, then relay is unexpectedly closed
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (addr == 0x2E4) && (bus == 0)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
@@ -103,7 +127,7 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int addr = GET_ADDR(to_send);
|
||||
int bus = GET_BUS(to_send);
|
||||
|
||||
if (!addr_allowed(addr, bus, TOYOTA_TX_MSGS, sizeof(TOYOTA_TX_MSGS)/sizeof(TOYOTA_TX_MSGS[0]))) {
|
||||
if (!msg_allowed(addr, bus, TOYOTA_TX_MSGS, sizeof(TOYOTA_TX_MSGS)/sizeof(TOYOTA_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
@@ -116,7 +140,7 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
// GAS PEDAL: safety check
|
||||
if (addr == 0x200) {
|
||||
if (!controls_allowed || !long_controls_allowed) {
|
||||
if (!controls_allowed) {
|
||||
if (GET_BYTE(to_send, 0) || GET_BYTE(to_send, 1)) {
|
||||
tx = 0;
|
||||
}
|
||||
@@ -127,7 +151,7 @@ static int toyota_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
if (addr == 0x343) {
|
||||
int desired_accel = (GET_BYTE(to_send, 0) << 8) | GET_BYTE(to_send, 1);
|
||||
desired_accel = to_signed(desired_accel, 16);
|
||||
if (!controls_allowed || !long_controls_allowed) {
|
||||
if (!controls_allowed) {
|
||||
if (desired_accel != 0) {
|
||||
tx = 0;
|
||||
}
|
||||
@@ -210,7 +234,7 @@ static int toyota_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd) {
|
||||
int is_lkas_msg = ((addr == 0x2E4) || (addr == 0x412) || (addr == 0x191));
|
||||
// in TSS2 the camera does ACC as well, so filter 0x343
|
||||
int is_acc_msg = (addr == 0x343);
|
||||
int block_msg = is_lkas_msg || (is_acc_msg && long_controls_allowed);
|
||||
int block_msg = is_lkas_msg || is_acc_msg;
|
||||
if (!block_msg) {
|
||||
bus_fwd = 0;
|
||||
}
|
||||
@@ -225,4 +249,6 @@ const safety_hooks toyota_hooks = {
|
||||
.tx = toyota_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = toyota_fwd_hook,
|
||||
.addr_check = toyota_rx_checks,
|
||||
.addr_check_len = sizeof(toyota_rx_checks)/sizeof(toyota_rx_checks[0]),
|
||||
};
|
||||
|
||||
@@ -31,9 +31,9 @@ uint32_t ts_angle_last = 0;
|
||||
int controls_allowed_last = 0;
|
||||
|
||||
|
||||
static void toyota_ipas_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int toyota_ipas_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// check standard toyota stuff as well
|
||||
toyota_rx_hook(to_push);
|
||||
bool valid = toyota_rx_hook(to_push);
|
||||
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -95,6 +95,7 @@ static void toyota_ipas_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
(ipas_state==5))) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
static int toyota_ipas_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
@@ -17,13 +17,22 @@ const int VOLKSWAGEN_DRIVER_TORQUE_FACTOR = 3;
|
||||
// MSG_GRA_ACC_01 is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration
|
||||
const AddrBus VOLKSWAGEN_TX_MSGS[] = {{MSG_HCA_01, 0}, {MSG_GRA_ACC_01, 0}, {MSG_GRA_ACC_01, 2}, {MSG_LDW_02, 0}};
|
||||
|
||||
struct sample_t volkswagen_torque_driver; // last few driver torques measured
|
||||
// TODO: do checksum and counter checks
|
||||
AddrCheckStruct volkswagen_rx_checks[] = {
|
||||
{.addr = {MSG_EPS_01}, .bus = 0, .expected_timestep = 10000U},
|
||||
{.addr = {MSG_ACC_06}, .bus = 0, .expected_timestep = 20000U},
|
||||
{.addr = {MSG_MOTOR_20}, .bus = 0, .expected_timestep = 20000U},
|
||||
};
|
||||
|
||||
const int VOLKSWAGEN_RX_CHECK_LEN = sizeof(volkswagen_rx_checks) / sizeof(volkswagen_rx_checks[0]);
|
||||
|
||||
struct sample_t volkswagen_torque_driver; // last few driver torques measured
|
||||
int volkswagen_rt_torque_last = 0;
|
||||
int volkswagen_desired_torque_last = 0;
|
||||
uint32_t volkswagen_ts_last = 0;
|
||||
int volkswagen_gas_prev = 0;
|
||||
|
||||
static void volkswagen_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
static int volkswagen_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int bus = GET_BUS(to_push);
|
||||
int addr = GET_ADDR(to_push);
|
||||
|
||||
@@ -50,7 +59,7 @@ static void volkswagen_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// exit controls on rising edge of gas press. Bits [12-20)
|
||||
if (addr == MSG_MOTOR_20) {
|
||||
int gas = (GET_BYTES_04(to_push) >> 12) & 0xFF;
|
||||
if ((gas > 0) && (volkswagen_gas_prev == 0) && long_controls_allowed) {
|
||||
if ((gas > 0) && (volkswagen_gas_prev == 0)) {
|
||||
controls_allowed = 0;
|
||||
}
|
||||
volkswagen_gas_prev = gas;
|
||||
@@ -59,6 +68,7 @@ static void volkswagen_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
if ((safety_mode_cnt > RELAY_TRNS_TIMEOUT) && (bus == 0) && (addr == MSG_HCA_01)) {
|
||||
relay_malfunction = true;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int volkswagen_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
@@ -66,7 +76,7 @@ static int volkswagen_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
int bus = GET_BUS(to_send);
|
||||
int tx = 1;
|
||||
|
||||
if (!addr_allowed(addr, bus, VOLKSWAGEN_TX_MSGS, sizeof(VOLKSWAGEN_TX_MSGS)/sizeof(VOLKSWAGEN_TX_MSGS[0]))) {
|
||||
if (!msg_allowed(addr, bus, VOLKSWAGEN_TX_MSGS, sizeof(VOLKSWAGEN_TX_MSGS)/sizeof(VOLKSWAGEN_TX_MSGS[0]))) {
|
||||
tx = 0;
|
||||
}
|
||||
|
||||
@@ -174,4 +184,6 @@ const safety_hooks volkswagen_hooks = {
|
||||
.tx = volkswagen_tx_hook,
|
||||
.tx_lin = nooutput_tx_lin_hook,
|
||||
.fwd = volkswagen_fwd_hook,
|
||||
.addr_check = volkswagen_rx_checks,
|
||||
.addr_check_len = sizeof(volkswagen_rx_checks) / sizeof(volkswagen_rx_checks[0]),
|
||||
};
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
const int MAX_WRONG_COUNTERS = 5;
|
||||
const uint8_t MAX_MISSED_MSGS = 10U;
|
||||
|
||||
// sample struct that keeps 3 samples in memory
|
||||
struct sample_t {
|
||||
int values[6];
|
||||
@@ -16,7 +19,23 @@ typedef struct {
|
||||
int bus;
|
||||
} AddrBus;
|
||||
|
||||
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
// params and flags about checksum, counter and frequency checks for each monitored address
|
||||
typedef struct {
|
||||
// const params
|
||||
const int addr[3]; // check either messages (e.g. honda steer). Array MUST terminate with a zero to know its length.
|
||||
const int bus; // bus where to expect the addr. Temp hack: -1 means skip the bus check
|
||||
const bool check_checksum; // true is checksum check is performed
|
||||
const uint8_t max_counter; // maximum value of the counter. 0 means that the counter check is skipped
|
||||
const uint32_t expected_timestep; // expected time between message updates [us]
|
||||
// dynamic flags
|
||||
bool valid_checksum; // true if and only if checksum check is passed
|
||||
int wrong_counters; // counter of wrong counters, saturated between 0 and MAX_WRONG_COUNTERS
|
||||
uint8_t last_counter; // last counter value
|
||||
uint32_t last_timestamp; // micro-s
|
||||
bool lagging; // true if and only if the time between updates is excessive
|
||||
} AddrCheckStruct;
|
||||
|
||||
int safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_send);
|
||||
int safety_tx_lin_hook(int lin_num, uint8_t *data, int len);
|
||||
uint32_t get_ts_elapsed(uint32_t ts, uint32_t ts_last);
|
||||
@@ -30,10 +49,20 @@ bool driver_limit_check(int val, int val_last, struct sample_t *val_driver,
|
||||
const int MAX_ALLOWANCE, const int DRIVER_FACTOR);
|
||||
bool rt_rate_limit_check(int val, int val_last, const int MAX_RT_DELTA);
|
||||
float interpolate(struct lookup_t xy, float x);
|
||||
bool addr_allowed(int addr, int bus, const AddrBus addr_list[], int len);
|
||||
bool msg_allowed(int addr, int bus, const AddrBus addr_list[], int len);
|
||||
int get_addr_check_index(CAN_FIFOMailBox_TypeDef *to_push, AddrCheckStruct addr_list[], const int len);
|
||||
void update_counter(AddrCheckStruct addr_list[], int index, uint8_t counter);
|
||||
void update_addr_timestamp(AddrCheckStruct addr_list[], int index);
|
||||
bool is_msg_valid(AddrCheckStruct addr_list[], int index);
|
||||
bool addr_safety_check(CAN_FIFOMailBox_TypeDef *to_push,
|
||||
AddrCheckStruct *addr_check,
|
||||
const int addr_check_len,
|
||||
uint8_t (*get_checksum)(CAN_FIFOMailBox_TypeDef *to_push),
|
||||
uint8_t (*compute_checksum)(CAN_FIFOMailBox_TypeDef *to_push),
|
||||
uint8_t (*get_counter)(CAN_FIFOMailBox_TypeDef *to_push));
|
||||
|
||||
typedef void (*safety_hook_init)(int16_t param);
|
||||
typedef void (*rx_hook)(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
typedef int (*rx_hook)(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
typedef int (*tx_hook)(CAN_FIFOMailBox_TypeDef *to_send);
|
||||
typedef int (*tx_lin_hook)(int lin_num, uint8_t *data, int len);
|
||||
typedef int (*fwd_hook)(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd);
|
||||
@@ -44,17 +73,18 @@ typedef struct {
|
||||
tx_hook tx;
|
||||
tx_lin_hook tx_lin;
|
||||
fwd_hook fwd;
|
||||
AddrCheckStruct *addr_check;
|
||||
const int addr_check_len;
|
||||
} safety_hooks;
|
||||
|
||||
void safety_tick(const safety_hooks *hooks);
|
||||
|
||||
// This can be set by the safety hooks
|
||||
bool controls_allowed = false;
|
||||
bool relay_malfunction = false;
|
||||
bool gas_interceptor_detected = false;
|
||||
int gas_interceptor_prev = 0;
|
||||
|
||||
// This is set by USB command 0xdf
|
||||
bool long_controls_allowed = true;
|
||||
|
||||
// time since safety mode has been changed
|
||||
uint32_t safety_mode_cnt = 0U;
|
||||
// allow 1s of transition timeout after relay changes state before assessing malfunctioning
|
||||
|
||||
@@ -65,11 +65,13 @@ int usb_cb_control_msg(USB_Setup_TypeDef *setup, uint8_t *resp, bool hardwired)
|
||||
// so it's blocked over wifi
|
||||
switch (setup->b.wValue.w) {
|
||||
case 0:
|
||||
#ifdef ALLOW_DEBUG
|
||||
// TODO: put this back when it's no longer a "devkit"
|
||||
//#ifdef ALLOW_DEBUG
|
||||
#if 1
|
||||
if (hardwired) {
|
||||
#else
|
||||
// no more bootstub on UNO
|
||||
if (hardwired && hw_type != HW_TYPE_UNO) {
|
||||
// no more bootstub on UNO once OTP block is flashed
|
||||
if (hardwired && ((hw_type != HW_TYPE_UNO) || (!is_provisioned()))) {
|
||||
#endif
|
||||
puts("-> entering bootloader\n");
|
||||
enter_bootloader_mode = ENTER_BOOTLOADER_MAGIC;
|
||||
|
||||
@@ -22,32 +22,32 @@
|
||||
<ProjectGuid>{D99E2FCD-21A4-4065-949A-31E34E0E69D1}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>ECUsimCLI</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -22,32 +22,32 @@
|
||||
<ProjectGuid>{96E0E646-EE76-444D-9A77-A0CD7F781DEB}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>ECUsimDLL</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -20,7 +20,7 @@ ______/\\\\\\\\\\\____/\\\\\\\\\_______/\\\\\\\\\\\\\\\______/\\\\\\\\\\________
|
||||
|
||||
# Installing J2534 driver:
|
||||
|
||||
[Download](https://github.com/commaai/panda/files/1742802/panda.J2534.driver.install.zip)
|
||||
[Download](https://github.com/commaai/panda/files/4017364/panda.J2534.driver.install.zip)
|
||||
|
||||
Depending on what version of windows you are on, you may need to separately install the WinUSB driver (see next section).
|
||||
|
||||
|
||||
@@ -22,32 +22,32 @@
|
||||
<ProjectGuid>{5528AEFB-638D-49AF-B9D4-965154E7D531}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>panda</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -14,21 +14,21 @@
|
||||
<ProjectGuid>{7912F978-B48C-4C5D-8BFD-5D1E22158E47}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>pandaJ2534DLLTest</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
<ProjectName>Tests</ProjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
<UseOfMfc>false</UseOfMfc>
|
||||
|
||||
@@ -21,7 +21,7 @@ public:
|
||||
}
|
||||
|
||||
this->next_part = (this->next_part + 1) % 0x10;
|
||||
unsigned int payload_len = MIN(expected_size - msg.size(), max_packet_size);
|
||||
unsigned int payload_len = min(expected_size - msg.size(), max_packet_size);
|
||||
if (piece.size() < payload_len) {
|
||||
//A frame was received that could have held more data.
|
||||
//No examples of this protocol show that happening, so
|
||||
|
||||
@@ -170,7 +170,7 @@ DWORD PandaJ2534Device::msg_tx_thread() {
|
||||
} else { //Ran out of things that need to be sent now. Sleep!
|
||||
auto time_diff = std::chrono::duration_cast<std::chrono::milliseconds>
|
||||
(this->task_queue.front()->expire - std::chrono::steady_clock::now());
|
||||
sleepDuration = MAX(1, time_diff.count());
|
||||
sleepDuration = max(1, time_diff.count());
|
||||
goto break_flow_ctrl_loop;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,19 +14,19 @@
|
||||
<ProjectGuid>{A2BB18A5-F26B-48D6-BBB5-B83D64473C77}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>pandaJ2534DLL</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -22,32 +22,32 @@
|
||||
<ProjectGuid>{691DB635-C272-4B98-897E-0505B970DCA9}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>panda_playground</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
namespace panda {
|
||||
typedef enum _PANDA_SAFETY_MODE : uint16_t {
|
||||
SAFETY_SILENT = 0,
|
||||
SAFETY_HONDA = 1,
|
||||
SAFETY_HONDA_NIDEC = 1,
|
||||
SAFETY_ALLOUTPUT = 17,
|
||||
} PANDA_SAFETY_MODE;
|
||||
|
||||
@@ -78,13 +78,23 @@ namespace panda {
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct _PANDA_HEALTH {
|
||||
uint32_t uptime;
|
||||
uint32_t voltage;
|
||||
uint32_t current;
|
||||
uint8_t started;
|
||||
uint32_t can_rx_errs;
|
||||
uint32_t can_send_errs;
|
||||
uint32_t can_fwd_errs;
|
||||
uint32_t gmlan_send_errs;
|
||||
uint32_t faults;
|
||||
uint8_t ignition_line;
|
||||
uint8_t ignition_can;
|
||||
uint8_t controls_allowed;
|
||||
uint8_t gas_interceptor_detected;
|
||||
uint8_t started_signal_detected;
|
||||
uint8_t started_alt;
|
||||
uint8_t car_harness_status;
|
||||
uint8_t usb_power_mode;
|
||||
uint8_t safety_mode;
|
||||
uint8_t fault_status;
|
||||
uint8_t power_save_enabled;
|
||||
} PANDA_HEALTH, *PPANDA_HEALTH;
|
||||
|
||||
typedef struct _PANDA_CAN_MSG {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
;An list of the registry keys has been maintained here: https://stackoverflow.com/a/34209692/627525
|
||||
|
||||
|
||||
;Microsoft Visual C++ 2015 Redistributable (x86) - 14.0.24123
|
||||
!define VCRuntimeRegKey "SOFTWARE\Classes\Installer\Dependencies\{206898cc-4b41-4d98-ac28-9f9ae57f91fe}"
|
||||
;Microsoft Visual C++ 2015-2019 Redistributable (x86) - 14.24.28127
|
||||
!define VCRuntimeRegKey "Installer\Dependencies\VC,redist.x86,x86,14.24,bundle"
|
||||
!define VCRuntimeSetupPath "redist\"
|
||||
!define VCRuntimeSetupFile "vc_redist.x86.exe"
|
||||
+24
-22
@@ -23,14 +23,14 @@ BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")
|
||||
DEBUG = os.getenv("PANDADEBUG") is not None
|
||||
|
||||
# *** wifi mode ***
|
||||
def build_st(target, mkfile="Makefile"):
|
||||
def build_st(target, mkfile="Makefile", clean=True):
|
||||
from panda import BASEDIR
|
||||
cmd = 'cd %s && make -f %s clean && make -f %s %s >/dev/null' % (os.path.join(BASEDIR, "board"), mkfile, mkfile, target)
|
||||
|
||||
clean_cmd = "make -f %s clean" % mkfile if clean else ":"
|
||||
cmd = 'cd %s && %s && make -f %s %s' % (os.path.join(BASEDIR, "board"), clean_cmd, mkfile, target)
|
||||
try:
|
||||
_ = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
|
||||
except subprocess.CalledProcessError:
|
||||
#output = exception.output
|
||||
#returncode = exception.returncode
|
||||
raise
|
||||
|
||||
def parse_can_buffer(dat):
|
||||
@@ -111,11 +111,11 @@ class Panda(object):
|
||||
|
||||
# matches cereal.car.CarParams.SafetyModel
|
||||
SAFETY_SILENT = 0
|
||||
SAFETY_HONDA = 1
|
||||
SAFETY_HONDA_NIDEC = 1
|
||||
SAFETY_TOYOTA = 2
|
||||
SAFETY_ELM327 = 3
|
||||
SAFETY_GM = 4
|
||||
SAFETY_HONDA_BOSCH = 5
|
||||
SAFETY_HONDA_BOSCH_GIRAFFE = 5
|
||||
SAFETY_FORD = 6
|
||||
SAFETY_CADILLAC = 7
|
||||
SAFETY_HYUNDAI = 8
|
||||
@@ -128,6 +128,7 @@ class Panda(object):
|
||||
SAFETY_ALLOUTPUT = 17
|
||||
SAFETY_GM_ASCM = 18
|
||||
SAFETY_NOOUTPUT = 19
|
||||
SAFETY_HONDA_BOSCH_HARNESS = 20
|
||||
|
||||
SERIAL_DEBUG = 0
|
||||
SERIAL_ESP = 1
|
||||
@@ -346,25 +347,26 @@ class Panda(object):
|
||||
# ******************* health *******************
|
||||
|
||||
def health(self):
|
||||
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xd2, 0, 0, 37)
|
||||
a = struct.unpack("IIIIIIIBBBBBBBBB", dat)
|
||||
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xd2, 0, 0, 41)
|
||||
a = struct.unpack("IIIIIIIIBBBBBBBBB", dat)
|
||||
return {
|
||||
"uptime": a[0],
|
||||
"voltage": a[1],
|
||||
"current": a[2],
|
||||
"can_send_errs": a[3],
|
||||
"can_fwd_errs": a[4],
|
||||
"gmlan_send_errs": a[5],
|
||||
"faults": a[6],
|
||||
"ignition_line": a[7],
|
||||
"ignition_can": a[8],
|
||||
"controls_allowed": a[9],
|
||||
"gas_interceptor_detected": a[10],
|
||||
"car_harness_status": a[11],
|
||||
"usb_power_mode": a[12],
|
||||
"safety_mode": a[13],
|
||||
"fault_status": a[14],
|
||||
"power_save_enabled": a[15]
|
||||
"can_rx_errs": a[3],
|
||||
"can_send_errs": a[4],
|
||||
"can_fwd_errs": a[5],
|
||||
"gmlan_send_errs": a[6],
|
||||
"faults": a[7],
|
||||
"ignition_line": a[8],
|
||||
"ignition_can": a[9],
|
||||
"controls_allowed": a[10],
|
||||
"gas_interceptor_detected": a[11],
|
||||
"car_harness_status": a[12],
|
||||
"usb_power_mode": a[13],
|
||||
"safety_mode": a[14],
|
||||
"fault_status": a[15],
|
||||
"power_save_enabled": a[16]
|
||||
}
|
||||
|
||||
# ******************* control *******************
|
||||
@@ -388,7 +390,7 @@ class Panda(object):
|
||||
def get_signature(self):
|
||||
part_1 = self._handle.controlRead(Panda.REQUEST_IN, 0xd3, 0, 0, 0x40)
|
||||
part_2 = self._handle.controlRead(Panda.REQUEST_IN, 0xd4, 0, 0, 0x40)
|
||||
return part_1 + part_2
|
||||
return bytes(part_1 + part_2)
|
||||
|
||||
def get_type(self):
|
||||
return self._handle.controlRead(Panda.REQUEST_IN, 0xc1, 0, 0, 0x40)
|
||||
|
||||
+33
-14
@@ -268,17 +268,19 @@ _negative_response_codes = {
|
||||
0x93: 'voltage too low',
|
||||
}
|
||||
|
||||
|
||||
class CanClient():
|
||||
def __init__(self, can_send: Callable[[Tuple[int, bytes, int]], None], can_recv: Callable[[], List[Tuple[int, int, bytes, int]]], tx_addr: int, rx_addr: int, bus: int, debug: bool=False):
|
||||
def __init__(self, can_send: Callable[[Tuple[int, bytes, int]], None], can_recv: Callable[[], List[Tuple[int, int, bytes, int]]], tx_addr: int, rx_addr: int, bus: int, sub_addr: int=None, debug: bool=False):
|
||||
self.tx = can_send
|
||||
self.rx = can_recv
|
||||
self.tx_addr = tx_addr
|
||||
self.rx_addr = rx_addr
|
||||
self.sub_addr = sub_addr
|
||||
self.bus = bus
|
||||
self.debug = debug
|
||||
|
||||
def _recv_filter(self, bus, addr):
|
||||
# handle functionl addresses (switch to first addr to respond)
|
||||
# handle functional addresses (switch to first addr to respond)
|
||||
if self.tx_addr == 0x7DF:
|
||||
is_response = addr >= 0x7E8 and addr <= 0x7EF
|
||||
if is_response:
|
||||
@@ -303,8 +305,14 @@ class CanClient():
|
||||
else:
|
||||
for rx_addr, rx_ts, rx_data, rx_bus in msgs or []:
|
||||
if self._recv_filter(rx_bus, rx_addr) and len(rx_data) > 0:
|
||||
rx_data = bytes(rx_data) # convert bytearray to bytes
|
||||
rx_data = bytes(rx_data) # convert bytearray to bytes
|
||||
|
||||
if self.debug: print(f"CAN-RX: {hex(rx_addr)} - 0x{bytes.hex(rx_data)}")
|
||||
|
||||
# Cut off sub addr in first byte
|
||||
if self.sub_addr is not None:
|
||||
rx_data = rx_data[1:]
|
||||
|
||||
msg_array.append(rx_data)
|
||||
# break when non-full buffer is processed
|
||||
if len(msgs) < 254:
|
||||
@@ -316,15 +324,23 @@ class CanClient():
|
||||
if delay and not first:
|
||||
if self.debug: print(f"CAN-TX: delay - {delay}")
|
||||
time.sleep(delay)
|
||||
|
||||
if self.sub_addr is not None:
|
||||
msg = bytes([self.sub_addr]) + msg
|
||||
|
||||
if self.debug: print(f"CAN-TX: {hex(self.tx_addr)} - 0x{bytes.hex(msg)}")
|
||||
assert len(msg) <= 8
|
||||
|
||||
self.tx(self.tx_addr, msg, self.bus)
|
||||
first = False
|
||||
|
||||
|
||||
class IsoTpMessage():
|
||||
def __init__(self, can_client: CanClient, timeout: float=1, debug: bool=False):
|
||||
def __init__(self, can_client: CanClient, timeout: float=1, debug: bool=False, max_len: int=8):
|
||||
self._can_client = can_client
|
||||
self.timeout = timeout
|
||||
self.debug = debug
|
||||
self.max_len = max_len
|
||||
|
||||
def send(self, dat: bytes) -> None:
|
||||
# throw away any stale data
|
||||
@@ -347,12 +363,12 @@ class IsoTpMessage():
|
||||
if self.tx_len < 8:
|
||||
# single frame (send all bytes)
|
||||
if self.debug: print("ISO-TP: TX - single frame")
|
||||
msg = (bytes([self.tx_len]) + self.tx_dat).ljust(8, b"\x00")
|
||||
msg = (bytes([self.tx_len]) + self.tx_dat).ljust(self.max_len, b"\x00")
|
||||
self.tx_done = True
|
||||
else:
|
||||
# first frame (send first 6 bytes)
|
||||
if self.debug: print("ISO-TP: TX - first frame")
|
||||
msg = (struct.pack("!H", 0x1000 | self.tx_len) + self.tx_dat[:6]).ljust(8, b"\x00")
|
||||
msg = (struct.pack("!H", 0x1000 | self.tx_len) + self.tx_dat[:6]).ljust(self.max_len, b"\x00")
|
||||
self._can_client.send([msg])
|
||||
|
||||
def recv(self) -> bytes:
|
||||
@@ -390,7 +406,7 @@ class IsoTpMessage():
|
||||
if self.debug: print(f"ISO-TP: RX - first frame - idx={self.rx_idx} done={self.rx_done}")
|
||||
if self.debug: print(f"ISO-TP: TX - flow control continue")
|
||||
# send flow control message (send all bytes)
|
||||
msg = b"\x30\x00\x00".ljust(8, b"\x00")
|
||||
msg = b"\x30\x00\x00".ljust(self.max_len, b"\x00")
|
||||
self._can_client.send([msg])
|
||||
return
|
||||
|
||||
@@ -400,7 +416,7 @@ class IsoTpMessage():
|
||||
self.rx_idx += 1
|
||||
assert self.rx_idx & 0xF == rx_data[0] & 0xF, "isotp - rx: invalid consecutive frame index"
|
||||
rx_size = self.rx_len - len(self.rx_dat)
|
||||
self.rx_dat += rx_data[1:1+min(rx_size, 7)]
|
||||
self.rx_dat += rx_data[1:1+rx_size]
|
||||
if self.rx_len == len(self.rx_dat):
|
||||
self.rx_done = True
|
||||
if self.debug: print(f"ISO-TP: RX - consecutive frame - idx={self.rx_idx} done={self.rx_done}")
|
||||
@@ -417,15 +433,17 @@ class IsoTpMessage():
|
||||
# scale is 1 milliseconds if first bit == 0, 100 micro seconds if first bit == 1
|
||||
delay_div = 1000. if rx_data[2] & 0x80 == 0 else 10000.
|
||||
delay_sec = delay_ts / delay_div
|
||||
|
||||
# first frame = 6 bytes, each consecutive frame = 7 bytes
|
||||
start = 6 + self.tx_idx * 7
|
||||
num_bytes = self.max_len - 1
|
||||
start = 6 + self.tx_idx * num_bytes
|
||||
count = rx_data[1]
|
||||
end = start + count * 7 if count > 0 else self.tx_len
|
||||
end = start + count * num_bytes if count > 0 else self.tx_len
|
||||
tx_msgs = []
|
||||
for i in range(start, end, 7):
|
||||
for i in range(start, end, num_bytes):
|
||||
self.tx_idx += 1
|
||||
# consecutive tx messages
|
||||
msg = (bytes([0x20 | (self.tx_idx & 0xF)]) + self.tx_dat[i:i+7]).ljust(8, b"\x00")
|
||||
msg = (bytes([0x20 | (self.tx_idx & 0xF)]) + self.tx_dat[i:i+num_bytes]).ljust(self.max_len, b"\x00")
|
||||
tx_msgs.append(msg)
|
||||
# send consecutive tx messages
|
||||
self._can_client.send(tx_msgs, delay=delay_sec)
|
||||
@@ -445,13 +463,14 @@ def get_rx_addr_for_tx_addr(tx_addr):
|
||||
if tx_addr < 0xFFF8:
|
||||
# standard 11 bit response addr (add 8)
|
||||
return tx_addr + 8
|
||||
|
||||
|
||||
if tx_addr > 0x10000000 and tx_addr < 0xFFFFFFFF:
|
||||
# standard 29 bit response addr (flip last two bytes)
|
||||
return (tx_addr & 0xFFFF0000) + (tx_addr<<8 & 0xFF00) + (tx_addr>>8 & 0xFF)
|
||||
|
||||
raise ValueError("invalid tx_addr: {}".format(tx_addr))
|
||||
|
||||
|
||||
class UdsClient():
|
||||
def __init__(self, panda, tx_addr: int, rx_addr: int=None, bus: int=0, timeout: float=1, debug: bool=False):
|
||||
self.bus = bus
|
||||
@@ -714,7 +733,7 @@ class UdsClient():
|
||||
if dtc_report_type == DTC_REPORT_TYPE.NUMBER_OF_DTC_BY_SEVERITY_MASK_RECORD or \
|
||||
dtc_report_type == DTC_REPORT_TYPE.DTC_BY_SEVERITY_MASK_RECORD:
|
||||
data += bytes([dtc_severity_mask_type, dtc_status_mask_type])
|
||||
|
||||
|
||||
resp = self._uds_request(SERVICE_TYPE.READ_DTC_INFORMATION, subfunction=dtc_report_type, data=data)
|
||||
|
||||
# TODO: parse response
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import time
|
||||
from panda import PandaSerial
|
||||
from .helpers import reset_pandas, test_all_gps_pandas, panda_connect_and_init
|
||||
|
||||
# Reset the pandas before running tests
|
||||
def aaaa_reset_before_tests():
|
||||
reset_pandas()
|
||||
|
||||
@test_all_gps_pandas
|
||||
@panda_connect_and_init
|
||||
def test_gps_version(p):
|
||||
serial = PandaSerial(p, 1, 9600)
|
||||
# Reset and check twice to make sure the enabling works
|
||||
for i in range(2):
|
||||
# Reset GPS
|
||||
p.set_esp_power(0)
|
||||
time.sleep(0.5)
|
||||
p.set_esp_power(1)
|
||||
time.sleep(1)
|
||||
|
||||
# Read startup message and check if version is contained
|
||||
dat = serial.read(0x1000) # Read one full panda DMA buffer. This should include the startup message
|
||||
assert b'HPG 1.40ROV' in dat
|
||||
@@ -1,9 +1,5 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import random
|
||||
import subprocess
|
||||
import requests
|
||||
import _thread
|
||||
import faulthandler
|
||||
from functools import wraps
|
||||
@@ -19,6 +15,7 @@ SPEED_GMLAN = 33.3
|
||||
BUS_SPEEDS = [(0, SPEED_NORMAL), (1, SPEED_NORMAL), (2, SPEED_NORMAL), (3, SPEED_GMLAN)]
|
||||
TIMEOUT = 30
|
||||
GEN2_HW_TYPES = [Panda.HW_TYPE_BLACK_PANDA, Panda.HW_TYPE_UNO]
|
||||
GPS_HW_TYPES = [Panda.HW_TYPE_GREY_PANDA, Panda.HW_TYPE_BLACK_PANDA, Panda.HW_TYPE_UNO]
|
||||
|
||||
# Enable fault debug
|
||||
faulthandler.enable(all_threads=False)
|
||||
@@ -52,6 +49,9 @@ test_all_pandas = parameterized(
|
||||
test_all_gen2_pandas = parameterized(
|
||||
list(map(lambda x: x[0], filter(lambda x: x[1] in GEN2_HW_TYPES, _panda_serials)))
|
||||
)
|
||||
test_all_gps_pandas = parameterized(
|
||||
list(map(lambda x: x[0], filter(lambda x: x[1] in GPS_HW_TYPES, _panda_serials)))
|
||||
)
|
||||
test_white_and_grey = parameterized([
|
||||
param(panda_type=Panda.HW_TYPE_WHITE_PANDA),
|
||||
param(panda_type=Panda.HW_TYPE_GREY_PANDA)
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import subprocess
|
||||
import requests
|
||||
from panda import Panda
|
||||
FNULL = open(os.devnull, 'w')
|
||||
def _connect_wifi(dongle_id, pw, insecure_okay=False):
|
||||
ssid = "panda-" + dongle_id
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
# Advisory: union types can be used
|
||||
misra.19.2
|
||||
# Advisory: casting from void pointer to type pointer is ok. Done by STM libraries as well
|
||||
misra.11.4
|
||||
# Advisory: casting from void pointer to type pointer is ok. Done by STM libraries as well
|
||||
misra.11.5
|
||||
# Advisory: as stated in the Misra document, use of goto statements in accordance to 15.2 and 15.3 is ok
|
||||
misra.15.1
|
||||
# Advisory: union types can be used
|
||||
misra.19.2
|
||||
# Required: it's ok re-defining potentially reserved Macro names. Not likely to cause confusion
|
||||
misra.21.1
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
|
||||
MAX_WRONG_COUNTERS = 5
|
||||
|
||||
def make_msg(bus, addr, length=8):
|
||||
to_send = libpandasafety_py.ffi.new('CAN_FIFOMailBox_TypeDef *')
|
||||
if addr >= 0x800:
|
||||
|
||||
@@ -30,14 +30,10 @@ typedef struct
|
||||
uint32_t CNT;
|
||||
} TIM_TypeDef;
|
||||
|
||||
bool board_has_relay(void);
|
||||
|
||||
void set_controls_allowed(bool c);
|
||||
bool get_controls_allowed(void);
|
||||
void set_relay_malfunction(bool c);
|
||||
bool get_relay_malfunction(void);
|
||||
void set_long_controls_allowed(bool c);
|
||||
bool get_long_controls_allowed(void);
|
||||
void set_gas_interceptor_detected(bool c);
|
||||
bool get_gas_interceptor_detetcted(void);
|
||||
int get_gas_interceptor_prev(void);
|
||||
@@ -45,7 +41,7 @@ int get_hw_type(void);
|
||||
void set_timer(uint32_t t);
|
||||
void reset_angle_control(void);
|
||||
|
||||
void safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_send);
|
||||
int safety_rx_hook(CAN_FIFOMailBox_TypeDef *to_send);
|
||||
int safety_tx_hook(CAN_FIFOMailBox_TypeDef *to_push);
|
||||
int safety_fwd_hook(int bus_num, CAN_FIFOMailBox_TypeDef *to_fwd);
|
||||
int set_safety_hooks(uint16_t mode, int16_t param);
|
||||
@@ -64,8 +60,8 @@ bool get_honda_brake_pressed_prev(void);
|
||||
int get_honda_gas_prev(void);
|
||||
void set_honda_fwd_brake(bool);
|
||||
void set_honda_alt_brake_msg(bool);
|
||||
void set_honda_bosch_hardware(bool);
|
||||
int get_honda_bosch_hardware(void);
|
||||
void set_honda_hw(int);
|
||||
int get_honda_hw(void);
|
||||
|
||||
void init_tests_cadillac(void);
|
||||
void set_cadillac_desired_torque_last(int t);
|
||||
|
||||
@@ -47,11 +47,6 @@ TIM_TypeDef *TIM2 = &timer;
|
||||
// from main_declarations.h
|
||||
uint8_t hw_type = HW_TYPE_UNKNOWN;
|
||||
|
||||
// from board.h
|
||||
bool board_has_relay(void) {
|
||||
return hw_type == HW_TYPE_BLACK_PANDA || hw_type == HW_TYPE_UNO;
|
||||
}
|
||||
|
||||
// from config.h
|
||||
#define MIN(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
@@ -86,10 +81,6 @@ void set_relay_malfunction(bool c){
|
||||
relay_malfunction = c;
|
||||
}
|
||||
|
||||
void set_long_controls_allowed(bool c){
|
||||
long_controls_allowed = c;
|
||||
}
|
||||
|
||||
void set_gas_interceptor_detected(bool c){
|
||||
gas_interceptor_detected = c;
|
||||
}
|
||||
@@ -106,10 +97,6 @@ bool get_relay_malfunction(void){
|
||||
return relay_malfunction;
|
||||
}
|
||||
|
||||
bool get_long_controls_allowed(void){
|
||||
return long_controls_allowed;
|
||||
}
|
||||
|
||||
bool get_gas_interceptor_detected(void){
|
||||
return gas_interceptor_detected;
|
||||
}
|
||||
@@ -257,12 +244,12 @@ void set_honda_alt_brake_msg(bool c){
|
||||
honda_alt_brake_msg = c;
|
||||
}
|
||||
|
||||
void set_honda_bosch_hardware(bool c){
|
||||
honda_bosch_hardware = c;
|
||||
void set_honda_hw(int c){
|
||||
honda_hw = c;
|
||||
}
|
||||
|
||||
int get_honda_bosch_hardware(void) {
|
||||
return honda_bosch_hardware;
|
||||
int get_honda_hw(void) {
|
||||
return honda_hw;
|
||||
}
|
||||
|
||||
void set_honda_fwd_brake(bool c){
|
||||
|
||||
@@ -141,15 +141,10 @@ class TestGmSafety(unittest.TestCase):
|
||||
self.safety.safety_rx_hook(self._brake_msg(False))
|
||||
|
||||
def test_disengage_on_gas(self):
|
||||
for long_controls_allowed in [0, 1]:
|
||||
self.safety.set_long_controls_allowed(long_controls_allowed)
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._gas_msg(True))
|
||||
if long_controls_allowed:
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
else:
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(self._gas_msg(False))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._gas_msg(True))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(self._gas_msg(False))
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(True))
|
||||
@@ -159,28 +154,22 @@ class TestGmSafety(unittest.TestCase):
|
||||
self.safety.safety_rx_hook(self._gas_msg(False))
|
||||
|
||||
def test_brake_safety_check(self):
|
||||
for long_controls_allowed in [0, 1]:
|
||||
self.safety.set_long_controls_allowed(long_controls_allowed)
|
||||
for enabled in [0, 1]:
|
||||
for b in range(0, 500):
|
||||
self.safety.set_controls_allowed(enabled)
|
||||
if abs(b) > MAX_BRAKE or ((not enabled or not long_controls_allowed) and b != 0):
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_brake_msg(b)))
|
||||
else:
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._send_brake_msg(b)))
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
for enabled in [0, 1]:
|
||||
for b in range(0, 500):
|
||||
self.safety.set_controls_allowed(enabled)
|
||||
if abs(b) > MAX_BRAKE or (not enabled and b != 0):
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_brake_msg(b)))
|
||||
else:
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._send_brake_msg(b)))
|
||||
|
||||
def test_gas_safety_check(self):
|
||||
for long_controls_allowed in [0, 1]:
|
||||
self.safety.set_long_controls_allowed(long_controls_allowed)
|
||||
for enabled in [0, 1]:
|
||||
for g in range(0, 2**12-1):
|
||||
self.safety.set_controls_allowed(enabled)
|
||||
if abs(g) > MAX_GAS or ((not enabled or not long_controls_allowed) and g != MAX_REGEN):
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_gas_msg(g)))
|
||||
else:
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._send_gas_msg(g)))
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
for enabled in [0, 1]:
|
||||
for g in range(0, 2**12-1):
|
||||
self.safety.set_controls_allowed(enabled)
|
||||
if abs(g) > MAX_GAS or (not enabled and g != MAX_REGEN):
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._send_gas_msg(g)))
|
||||
else:
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._send_gas_msg(g)))
|
||||
|
||||
def test_steer_safety_check(self):
|
||||
for enabled in [0, 1]:
|
||||
|
||||
@@ -3,36 +3,66 @@ import unittest
|
||||
import numpy as np
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import test_relay_malfunction, make_msg, test_manually_enable_controls_allowed, test_spam_can_buses
|
||||
from panda.tests.safety.common import test_relay_malfunction, make_msg, \
|
||||
test_manually_enable_controls_allowed, \
|
||||
test_spam_can_buses, MAX_WRONG_COUNTERS
|
||||
|
||||
MAX_BRAKE = 255
|
||||
|
||||
INTERCEPTOR_THRESHOLD = 328
|
||||
TX_MSGS = [[0xE4, 0], [0x194, 0], [0x1FA, 0], [0x200, 0], [0x30C, 0], [0x33D, 0]]
|
||||
|
||||
HONDA_N_HW = 0
|
||||
HONDA_BG_HW = 1
|
||||
HONDA_BH_HW = 2
|
||||
|
||||
def honda_checksum(msg, addr, len_msg):
|
||||
checksum = 0
|
||||
while addr > 0:
|
||||
checksum += addr
|
||||
addr >>= 4
|
||||
for i in range (0, 2*len_msg):
|
||||
if i < 8:
|
||||
checksum += (msg.RDLR >> (4 * i))
|
||||
else:
|
||||
checksum += (msg.RDHR >> (4 * (i - 8)))
|
||||
return (8 - checksum) & 0xF
|
||||
|
||||
|
||||
class TestHondaSafety(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
cls.safety = libpandasafety_py.libpandasafety
|
||||
cls.safety.set_safety_hooks(Panda.SAFETY_HONDA, 0)
|
||||
cls.safety.set_safety_hooks(Panda.SAFETY_HONDA_NIDEC, 0)
|
||||
cls.safety.init_tests_honda()
|
||||
cls.cnt_speed = 0
|
||||
cls.cnt_gas = 0
|
||||
cls.cnt_button = 0
|
||||
|
||||
def _speed_msg(self, speed):
|
||||
to_send = make_msg(0, 0x158)
|
||||
to_send[0].RDLR = speed
|
||||
to_send[0].RDHR |= (self.cnt_speed % 4) << 28
|
||||
to_send[0].RDHR |= honda_checksum(to_send[0], 0x158, 8) << 24
|
||||
self.cnt_speed += 1
|
||||
return to_send
|
||||
|
||||
def _button_msg(self, buttons, msg):
|
||||
has_relay = self.safety.board_has_relay()
|
||||
honda_bosch_hardware = self.safety.get_honda_bosch_hardware()
|
||||
bus = 1 if has_relay and honda_bosch_hardware else 0
|
||||
to_send = make_msg(bus, msg)
|
||||
def _button_msg(self, buttons, addr):
|
||||
honda_hw = self.safety.get_honda_hw()
|
||||
bus = 1 if honda_hw == HONDA_BH_HW else 0
|
||||
to_send = make_msg(bus, addr)
|
||||
to_send[0].RDLR = buttons << 5
|
||||
to_send[0].RDHR |= (self.cnt_button % 4) << 28
|
||||
to_send[0].RDHR |= honda_checksum(to_send[0], addr, 8) << 24
|
||||
self.cnt_button += 1
|
||||
return to_send
|
||||
|
||||
def _brake_msg(self, brake):
|
||||
to_send = make_msg(0, 0x17C)
|
||||
to_send[0].RDHR = 0x200000 if brake else 0
|
||||
to_send[0].RDHR |= (self.cnt_gas % 4) << 28
|
||||
to_send[0].RDHR |= honda_checksum(to_send[0], 0x17C, 8) << 24
|
||||
self.cnt_gas += 1
|
||||
return to_send
|
||||
|
||||
def _alt_brake_msg(self, brake):
|
||||
@@ -43,6 +73,9 @@ class TestHondaSafety(unittest.TestCase):
|
||||
def _gas_msg(self, gas):
|
||||
to_send = make_msg(0, 0x17C)
|
||||
to_send[0].RDLR = 1 if gas else 0
|
||||
to_send[0].RDHR |= (self.cnt_gas % 4) << 28
|
||||
to_send[0].RDHR |= honda_checksum(to_send[0], 0x17C, 8) << 24
|
||||
self.cnt_gas += 1
|
||||
return to_send
|
||||
|
||||
def _send_brake_msg(self, brake):
|
||||
@@ -63,6 +96,7 @@ class TestHondaSafety(unittest.TestCase):
|
||||
return to_send
|
||||
|
||||
def test_spam_can_buses(self):
|
||||
self.safety.set_honda_hw(HONDA_N_HW)
|
||||
test_spam_can_buses(self, TX_MSGS)
|
||||
|
||||
def test_relay_malfunction(self):
|
||||
@@ -151,16 +185,10 @@ class TestHondaSafety(unittest.TestCase):
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_disengage_on_gas(self):
|
||||
for long_controls_allowed in [0, 1]:
|
||||
self.safety.set_long_controls_allowed(long_controls_allowed)
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
if long_controls_allowed:
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
else:
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
@@ -169,17 +197,14 @@ class TestHondaSafety(unittest.TestCase):
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_disengage_on_gas_interceptor(self):
|
||||
for long_controls_allowed in [0, 1]:
|
||||
for g in range(0, 0x1000):
|
||||
self.safety.set_long_controls_allowed(long_controls_allowed)
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(g, 0x201))
|
||||
remain_enabled = (not long_controls_allowed or g <= INTERCEPTOR_THRESHOLD)
|
||||
self.assertEqual(remain_enabled, self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
for g in range(0, 0x1000):
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(g, 0x201))
|
||||
remain_enabled = g <= INTERCEPTOR_THRESHOLD
|
||||
self.assertEqual(remain_enabled, self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_allow_engage_with_gas_interceptor_pressed(self):
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
|
||||
@@ -192,33 +217,27 @@ class TestHondaSafety(unittest.TestCase):
|
||||
def test_brake_safety_check(self):
|
||||
for fwd_brake in [False, True]:
|
||||
self.safety.set_honda_fwd_brake(fwd_brake)
|
||||
for long_controls_allowed in [0, 1]:
|
||||
self.safety.set_long_controls_allowed(long_controls_allowed)
|
||||
for brake in np.arange(0, MAX_BRAKE + 10, 1):
|
||||
for controls_allowed in [True, False]:
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
if fwd_brake:
|
||||
send = False # block openpilot brake msg when fwd'ing stock msg
|
||||
elif controls_allowed and long_controls_allowed:
|
||||
send = MAX_BRAKE >= brake >= 0
|
||||
else:
|
||||
send = brake == 0
|
||||
self.assertEqual(send, self.safety.safety_tx_hook(self._send_brake_msg(brake)))
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
for brake in np.arange(0, MAX_BRAKE + 10, 1):
|
||||
for controls_allowed in [True, False]:
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
if fwd_brake:
|
||||
send = False # block openpilot brake msg when fwd'ing stock msg
|
||||
elif controls_allowed:
|
||||
send = MAX_BRAKE >= brake >= 0
|
||||
else:
|
||||
send = brake == 0
|
||||
self.assertEqual(send, self.safety.safety_tx_hook(self._send_brake_msg(brake)))
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
|
||||
def test_gas_interceptor_safety_check(self):
|
||||
for long_controls_allowed in [0, 1]:
|
||||
self.safety.set_long_controls_allowed(long_controls_allowed)
|
||||
for gas in np.arange(0, 4000, 100):
|
||||
for controls_allowed in [True, False]:
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
if controls_allowed and long_controls_allowed:
|
||||
send = True
|
||||
else:
|
||||
send = gas == 0
|
||||
self.assertEqual(send, self.safety.safety_tx_hook(self._send_interceptor_msg(gas, 0x200)))
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
for gas in np.arange(0, 4000, 100):
|
||||
for controls_allowed in [True, False]:
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
if controls_allowed:
|
||||
send = True
|
||||
else:
|
||||
send = gas == 0
|
||||
self.assertEqual(send, self.safety.safety_tx_hook(self._send_interceptor_msg(gas, 0x200)))
|
||||
|
||||
def test_steer_safety_check(self):
|
||||
self.safety.set_controls_allowed(0)
|
||||
@@ -230,48 +249,88 @@ class TestHondaSafety(unittest.TestCase):
|
||||
SET_BTN = 3
|
||||
CANCEL_BTN = 2
|
||||
BUTTON_MSG = 0x296
|
||||
self.safety.set_honda_bosch_hardware(1)
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._button_msg(CANCEL_BTN, BUTTON_MSG)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._button_msg(SET_BTN, BUTTON_MSG)))
|
||||
# do not block resume if we are engaged already
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
|
||||
for hw in [HONDA_BG_HW, HONDA_BH_HW]:
|
||||
self.safety.set_honda_hw(hw)
|
||||
self.safety.set_controls_allowed(0)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._button_msg(CANCEL_BTN, BUTTON_MSG)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
|
||||
self.assertFalse(self.safety.safety_tx_hook(self._button_msg(SET_BTN, BUTTON_MSG)))
|
||||
# do not block resume if we are engaged already
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._button_msg(RESUME_BTN, BUTTON_MSG)))
|
||||
|
||||
def test_rx_hook(self):
|
||||
# checksum checks
|
||||
SET_BTN = 3
|
||||
for msg in ["btn1", "btn2", "gas", "speed"]:
|
||||
self.safety.set_controls_allowed(1)
|
||||
if msg == "btn1":
|
||||
to_push = self._button_msg(SET_BTN, 0x1A6)
|
||||
if msg == "btn2":
|
||||
to_push = self._button_msg(SET_BTN, 0x296)
|
||||
if msg == "gas":
|
||||
to_push = self._gas_msg(0)
|
||||
if msg == "speed":
|
||||
to_push = self._speed_msg(0)
|
||||
self.assertTrue(self.safety.safety_rx_hook(to_push))
|
||||
to_push[0].RDHR = 0
|
||||
self.assertFalse(self.safety.safety_rx_hook(to_push))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
# counter
|
||||
# reset wrong_counters to zero by sending valid messages
|
||||
for i in range(MAX_WRONG_COUNTERS + 1):
|
||||
self.cnt_speed = 0
|
||||
self.cnt_gas = 0
|
||||
self.cnt_button = 0
|
||||
if i < MAX_WRONG_COUNTERS:
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._button_msg(SET_BTN, 0x1A6))
|
||||
self.safety.safety_rx_hook(self._speed_msg(0))
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
else:
|
||||
self.assertFalse(self.safety.safety_rx_hook(self._button_msg(SET_BTN, 0x1A6)))
|
||||
self.assertFalse(self.safety.safety_rx_hook(self._speed_msg(0)))
|
||||
self.assertFalse(self.safety.safety_rx_hook(self._gas_msg(0)))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
# restore counters for future tests with a couple of good messages
|
||||
for i in range(2):
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.safety.safety_rx_hook(self._button_msg(SET_BTN, 0x1A6))
|
||||
self.safety.safety_rx_hook(self._speed_msg(0))
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.safety_rx_hook(self._button_msg(SET_BTN, 0x1A6))
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
|
||||
def test_fwd_hook(self):
|
||||
buss = list(range(0x0, 0x3))
|
||||
msgs = list(range(0x1, 0x800))
|
||||
long_controls_allowed = [0, 1]
|
||||
fwd_brake = [False, True]
|
||||
|
||||
self.safety.set_honda_bosch_hardware(0)
|
||||
self.safety.set_honda_hw(HONDA_N_HW)
|
||||
|
||||
for f in fwd_brake:
|
||||
self.safety.set_honda_fwd_brake(f)
|
||||
for l in long_controls_allowed:
|
||||
self.safety.set_long_controls_allowed(l)
|
||||
blocked_msgs = [0xE4, 0x194, 0x33D]
|
||||
if l:
|
||||
blocked_msgs += [0x30C]
|
||||
if not f:
|
||||
blocked_msgs += [0x1FA]
|
||||
for b in buss:
|
||||
for m in msgs:
|
||||
if b == 0:
|
||||
fwd_bus = 2
|
||||
elif b == 1:
|
||||
fwd_bus = -1
|
||||
elif b == 2:
|
||||
fwd_bus = -1 if m in blocked_msgs else 0
|
||||
blocked_msgs = [0xE4, 0x194, 0x33D]
|
||||
blocked_msgs += [0x30C]
|
||||
if not f:
|
||||
blocked_msgs += [0x1FA]
|
||||
for b in buss:
|
||||
for m in msgs:
|
||||
if b == 0:
|
||||
fwd_bus = 2
|
||||
elif b == 1:
|
||||
fwd_bus = -1
|
||||
elif b == 2:
|
||||
fwd_bus = -1 if m in blocked_msgs else 0
|
||||
|
||||
# assume len 8
|
||||
self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
|
||||
# assume len 8
|
||||
self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
|
||||
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
self.safety.set_honda_fwd_brake(False)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -3,6 +3,7 @@ import unittest
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests.safety.common import make_msg, test_spam_can_buses
|
||||
from panda.tests.safety.test_honda import HONDA_BG_HW, HONDA_BH_HW
|
||||
|
||||
MAX_BRAKE = 255
|
||||
|
||||
@@ -14,35 +15,35 @@ class TestHondaSafety(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
cls.safety = libpandasafety_py.libpandasafety
|
||||
cls.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH, 0)
|
||||
cls.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH_GIRAFFE, 0)
|
||||
cls.safety.init_tests_honda()
|
||||
|
||||
def test_spam_can_buses(self):
|
||||
if self.safety.board_has_relay():
|
||||
test_spam_can_buses(self, H_TX_MSGS)
|
||||
else:
|
||||
test_spam_can_buses(self, G_TX_MSGS)
|
||||
for hw in [HONDA_BG_HW, HONDA_BH_HW]:
|
||||
self.safety.set_honda_hw(hw)
|
||||
test_spam_can_buses(self, H_TX_MSGS if hw == HONDA_BH_HW else G_TX_MSGS)
|
||||
|
||||
def test_fwd_hook(self):
|
||||
buss = range(0x0, 0x3)
|
||||
msgs = range(0x1, 0x800)
|
||||
has_relay = self.safety.board_has_relay()
|
||||
bus_rdr_cam = 2 if has_relay else 1
|
||||
bus_rdr_car = 0 if has_relay else 2
|
||||
bus_pt = 1 if has_relay else 0
|
||||
for hw in [HONDA_BG_HW, HONDA_BH_HW]:
|
||||
self.safety.set_honda_hw(hw)
|
||||
bus_rdr_cam = 2 if hw == HONDA_BH_HW else 1
|
||||
bus_rdr_car = 0 if hw == HONDA_BH_HW else 2
|
||||
bus_pt = 1 if hw == HONDA_BH_HW else 0
|
||||
|
||||
blocked_msgs = [0xE4, 0x33D]
|
||||
for b in buss:
|
||||
for m in msgs:
|
||||
if b == bus_pt:
|
||||
fwd_bus = -1
|
||||
elif b == bus_rdr_cam:
|
||||
fwd_bus = -1 if m in blocked_msgs else bus_rdr_car
|
||||
elif b == bus_rdr_car:
|
||||
fwd_bus = bus_rdr_cam
|
||||
blocked_msgs = [0xE4, 0x33D]
|
||||
for b in buss:
|
||||
for m in msgs:
|
||||
if b == bus_pt:
|
||||
fwd_bus = -1
|
||||
elif b == bus_rdr_cam:
|
||||
fwd_bus = -1 if m in blocked_msgs else bus_rdr_car
|
||||
elif b == bus_rdr_car:
|
||||
fwd_bus = bus_rdr_cam
|
||||
|
||||
# assume len 8
|
||||
self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
|
||||
# assume len 8
|
||||
self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -36,6 +36,16 @@ def sign(a):
|
||||
else:
|
||||
return -1
|
||||
|
||||
def toyota_checksum(msg, addr, len_msg):
|
||||
checksum = (len_msg + addr + (addr >> 8))
|
||||
for i in range(len_msg):
|
||||
if i < 4:
|
||||
checksum += (msg.RDLR >> (8 * i))
|
||||
else:
|
||||
checksum += (msg.RDHR >> (8 * (i - 4)))
|
||||
return checksum & 0xff
|
||||
|
||||
|
||||
class TestToyotaSafety(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
@@ -51,7 +61,8 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
def _torque_meas_msg(self, torque):
|
||||
t = twos_comp(torque, 16)
|
||||
to_send = make_msg(0, 0x260)
|
||||
to_send[0].RDHR = t | ((t & 0xFF) << 16)
|
||||
to_send[0].RDHR = (t & 0xff00) | ((t & 0xFF) << 16)
|
||||
to_send[0].RDHR = to_send[0].RDHR | (toyota_checksum(to_send[0], 0x260, 8) << 24)
|
||||
return to_send
|
||||
|
||||
def _torque_msg(self, torque):
|
||||
@@ -81,6 +92,7 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
def _pcm_cruise_msg(self, cruise_on):
|
||||
to_send = make_msg(0, 0x1D2)
|
||||
to_send[0].RDLR = cruise_on << 5
|
||||
to_send[0].RDHR = to_send[0].RDHR | (toyota_checksum(to_send[0], 0x1D2, 8) << 24)
|
||||
return to_send
|
||||
|
||||
def test_spam_can_buses(self):
|
||||
@@ -120,16 +132,10 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_disengage_on_gas(self):
|
||||
for long_controls_allowed in [0, 1]:
|
||||
self.safety.set_long_controls_allowed(long_controls_allowed)
|
||||
self.safety.safety_rx_hook(self._send_gas_msg(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._send_gas_msg(1))
|
||||
if long_controls_allowed:
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
else:
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._send_gas_msg(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._send_gas_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.safety_rx_hook(self._send_gas_msg(1))
|
||||
@@ -140,17 +146,14 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
|
||||
def test_disengage_on_gas_interceptor(self):
|
||||
for long_controls_allowed in [0, 1]:
|
||||
for g in range(0, 0x1000):
|
||||
self.safety.set_long_controls_allowed(long_controls_allowed)
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(g, 0x201))
|
||||
remain_enabled = (not long_controls_allowed or g <= INTERCEPTOR_THRESHOLD)
|
||||
self.assertEqual(remain_enabled, self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
for g in range(0, 0x1000):
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(g, 0x201))
|
||||
remain_enabled = g <= INTERCEPTOR_THRESHOLD
|
||||
self.assertEqual(remain_enabled, self.safety.get_controls_allowed())
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0, 0x201))
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_allow_engage_with_gas_interceptor_pressed(self):
|
||||
self.safety.safety_rx_hook(self._send_interceptor_msg(0x1000, 0x201))
|
||||
@@ -161,17 +164,14 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
self.safety.set_gas_interceptor_detected(False)
|
||||
|
||||
def test_accel_actuation_limits(self):
|
||||
for long_controls_allowed in [0, 1]:
|
||||
self.safety.set_long_controls_allowed(long_controls_allowed)
|
||||
for accel in np.arange(MIN_ACCEL - 1000, MAX_ACCEL + 1000, 100):
|
||||
for controls_allowed in [True, False]:
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
if controls_allowed and long_controls_allowed:
|
||||
send = MIN_ACCEL <= accel <= MAX_ACCEL
|
||||
else:
|
||||
send = accel == 0
|
||||
self.assertEqual(send, self.safety.safety_tx_hook(self._accel_msg(accel)))
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
for accel in np.arange(MIN_ACCEL - 1000, MAX_ACCEL + 1000, 100):
|
||||
for controls_allowed in [True, False]:
|
||||
self.safety.set_controls_allowed(controls_allowed)
|
||||
if controls_allowed:
|
||||
send = MIN_ACCEL <= accel <= MAX_ACCEL
|
||||
else:
|
||||
send = accel == 0
|
||||
self.assertEqual(send, self.safety.safety_tx_hook(self._accel_msg(accel)))
|
||||
|
||||
def test_torque_absolute_limits(self):
|
||||
for controls_allowed in [True, False]:
|
||||
@@ -271,30 +271,38 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
self.safety.set_controls_allowed(1)
|
||||
self.assertTrue(self.safety.safety_tx_hook(self._send_interceptor_msg(0x1000, 0x200)))
|
||||
|
||||
def test_rx_hook(self):
|
||||
# checksum checks
|
||||
for msg in ["trq", "pcm"]:
|
||||
self.safety.set_controls_allowed(1)
|
||||
if msg == "trq":
|
||||
to_push = self._torque_meas_msg(0)
|
||||
if msg == "pcm":
|
||||
to_push = self._pcm_cruise_msg(1)
|
||||
self.assertTrue(self.safety.safety_rx_hook(to_push))
|
||||
to_push[0].RDHR = 0
|
||||
self.assertFalse(self.safety.safety_rx_hook(to_push))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_fwd_hook(self):
|
||||
|
||||
buss = list(range(0x0, 0x3))
|
||||
msgs = list(range(0x1, 0x800))
|
||||
long_controls_allowed = [0, 1]
|
||||
|
||||
for lca in long_controls_allowed:
|
||||
self.safety.set_long_controls_allowed(lca)
|
||||
blocked_msgs = [0x2E4, 0x412, 0x191]
|
||||
if lca:
|
||||
blocked_msgs += [0x343]
|
||||
for b in buss:
|
||||
for m in msgs:
|
||||
if b == 0:
|
||||
fwd_bus = 2
|
||||
elif b == 1:
|
||||
fwd_bus = -1
|
||||
elif b == 2:
|
||||
fwd_bus = -1 if m in blocked_msgs else 0
|
||||
blocked_msgs = [0x2E4, 0x412, 0x191]
|
||||
blocked_msgs += [0x343]
|
||||
for b in buss:
|
||||
for m in msgs:
|
||||
if b == 0:
|
||||
fwd_bus = 2
|
||||
elif b == 1:
|
||||
fwd_bus = -1
|
||||
elif b == 2:
|
||||
fwd_bus = -1 if m in blocked_msgs else 0
|
||||
|
||||
# assume len 8
|
||||
self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
|
||||
# assume len 8
|
||||
self.assertEqual(fwd_bus, self.safety.safety_fwd_hook(b, make_msg(b, m, 8)))
|
||||
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -3,7 +3,8 @@ import unittest
|
||||
import numpy as np
|
||||
from panda import Panda
|
||||
from panda.tests.safety import libpandasafety_py
|
||||
from panda.tests. safety.common import make_msg
|
||||
from panda.tests.safety.common import make_msg
|
||||
from panda.tests.safety.test_toyota import toyota_checksum
|
||||
|
||||
IPAS_OVERRIDE_THRESHOLD = 200
|
||||
|
||||
@@ -23,6 +24,7 @@ def sign(a):
|
||||
else:
|
||||
return -1
|
||||
|
||||
|
||||
class TestToyotaSafety(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUp(cls):
|
||||
@@ -34,6 +36,7 @@ class TestToyotaSafety(unittest.TestCase):
|
||||
to_send = make_msg(0, 0x260)
|
||||
t = twos_comp(torque, 16)
|
||||
to_send[0].RDLR = t | ((t & 0xFF) << 16)
|
||||
to_send[0].RDHR = to_send[0].RDHR | (toyota_checksum(to_send[0], 0x260, 8) << 24)
|
||||
return to_send
|
||||
|
||||
def _torque_driver_msg_array(self, torque):
|
||||
|
||||
@@ -87,16 +87,10 @@ class TestVolkswagenSafety(unittest.TestCase):
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_disengage_on_gas(self):
|
||||
for long_controls_allowed in [0, 1]:
|
||||
self.safety.set_long_controls_allowed(long_controls_allowed)
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
if long_controls_allowed:
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
else:
|
||||
self.assertTrue(self.safety.get_controls_allowed())
|
||||
self.safety.set_long_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._gas_msg(0))
|
||||
self.safety.set_controls_allowed(True)
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
self.assertFalse(self.safety.get_controls_allowed())
|
||||
|
||||
def test_allow_engage_with_gas_pressed(self):
|
||||
self.safety.safety_rx_hook(self._gas_msg(1))
|
||||
|
||||
@@ -11,7 +11,7 @@ def to_signed(d, bits):
|
||||
|
||||
def is_steering_msg(mode, addr):
|
||||
ret = False
|
||||
if mode == Panda.SAFETY_HONDA or mode == Panda.SAFETY_HONDA_BOSCH:
|
||||
if mode in [Panda.SAFETY_HONDA_NIDEC, Panda.SAFETY_HONDA_BOSCH_GIRAFFE, Panda.SAFETY_HONDA_BOSCH_HARNESS]:
|
||||
ret = (addr == 0xE4) or (addr == 0x194) or (addr == 0x33D)
|
||||
elif mode == Panda.SAFETY_TOYOTA:
|
||||
ret = addr == 0x2E4
|
||||
@@ -27,7 +27,7 @@ def is_steering_msg(mode, addr):
|
||||
|
||||
def get_steer_torque(mode, to_send):
|
||||
ret = 0
|
||||
if mode == Panda.SAFETY_HONDA or mode == Panda.SAFETY_HONDA_BOSCH:
|
||||
if mode in [Panda.SAFETY_HONDA_NIDEC, Panda.SAFETY_HONDA_BOSCH_GIRAFFE, Panda.SAFETY_HONDA_BOSCH_HARNESS]:
|
||||
ret = to_send.RDLR & 0xFFFF0000
|
||||
elif mode == Panda.SAFETY_TOYOTA:
|
||||
ret = (to_send.RDLR & 0xFF00) | ((to_send.RDLR >> 16) & 0xFF)
|
||||
@@ -45,7 +45,7 @@ def get_steer_torque(mode, to_send):
|
||||
return ret
|
||||
|
||||
def set_desired_torque_last(safety, mode, torque):
|
||||
if mode == Panda.SAFETY_HONDA or mode == Panda.SAFETY_HONDA_BOSCH:
|
||||
if mode in [Panda.SAFETY_HONDA_NIDEC, Panda.SAFETY_HONDA_BOSCH_GIRAFFE, Panda.SAFETY_HONDA_BOSCH_HARNESS]:
|
||||
pass # honda safety mode doesn't enforce a rate on steering msgs
|
||||
elif mode == Panda.SAFETY_TOYOTA:
|
||||
safety.set_toyota_desired_torque_last(torque)
|
||||
|
||||
@@ -16,8 +16,9 @@ def replay_drive(lr, safety_mode, param):
|
||||
if "SEGMENT" in os.environ:
|
||||
init_segment(safety, lr, mode)
|
||||
|
||||
tx_tot, tx_blocked, tx_controls, tx_controls_blocked = 0, 0, 0, 0
|
||||
rx_tot, rx_invalid, tx_tot, tx_blocked, tx_controls, tx_controls_blocked = 0, 0, 0, 0, 0, 0
|
||||
blocked_addrs = set()
|
||||
invalid_addrs = set()
|
||||
start_t = None
|
||||
|
||||
for msg in lr:
|
||||
@@ -44,15 +45,24 @@ def replay_drive(lr, safety_mode, param):
|
||||
if canmsg.src >= 128:
|
||||
continue
|
||||
to_push = package_can_msg(canmsg)
|
||||
safety.safety_rx_hook(to_push)
|
||||
recv = safety.safety_rx_hook(to_push)
|
||||
if not recv:
|
||||
rx_invalid += 1
|
||||
invalid_addrs.add(canmsg.address)
|
||||
rx_tot += 1
|
||||
|
||||
print("\nRX")
|
||||
print("total rx msgs:", rx_tot)
|
||||
print("invalid rx msgs:", rx_invalid)
|
||||
print("invalid addrs:", invalid_addrs)
|
||||
print("\nTX")
|
||||
print("total openpilot msgs:", tx_tot)
|
||||
print("total msgs with controls allowed:", tx_controls)
|
||||
print("blocked msgs:", tx_blocked)
|
||||
print("blocked with controls allowed:", tx_controls_blocked)
|
||||
print("blocked addrs:", blocked_addrs)
|
||||
|
||||
return tx_controls_blocked == 0
|
||||
return tx_controls_blocked == 0 and rx_invalid == 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
mode = int(sys.argv[2])
|
||||
|
||||
@@ -14,7 +14,7 @@ logs = [
|
||||
("2425568437959f9d|2019-12-22--16-24-37.bz2", Panda.SAFETY_HONDA_NIDEC, 0), # HONDA.CIVIC (fcw presents: 0x1FA blocked as expected)
|
||||
("38bfd238edecbcd7|2019-06-07--10-15-25.bz2", Panda.SAFETY_TOYOTA, 66), # TOYOTA.PRIUS
|
||||
("f89c604cf653e2bf|2018-09-29--13-46-50.bz2", Panda.SAFETY_GM, 0), # GM.VOLT
|
||||
("0375fdf7b1ce594d|2019-05-21--20-10-33.bz2", Panda.SAFETY_HONDA_BOSCH, 1), # HONDA.ACCORD
|
||||
("0375fdf7b1ce594d|2019-05-21--20-10-33.bz2", Panda.SAFETY_HONDA_BOSCH_GIRAFFE, 1), # HONDA.ACCORD
|
||||
("02ec6bea180a4d36|2019-04-17--11-21-35.bz2", Panda.SAFETY_HYUNDAI, 0), # HYUNDAI.SANTA_FE
|
||||
("6fb4948a7ebe670e|2019-11-12--00-35-53.bz2", Panda.SAFETY_CHRYSLER, 0), # CHRYSLER.PACIFICA_2018_HYBRID
|
||||
("791340bc01ed993d|2019-04-08--10-26-00.bz2", Panda.SAFETY_SUBARU, 0), # SUBARU.IMPREZA
|
||||
|
||||
Reference in New Issue
Block a user