Merge branch 'devel' of https://github.com/commaai/openpilot into devel-en

This commit is contained in:
dragonpilot
2020-01-17 22:31:23 +10:00
195 changed files with 5662 additions and 4369 deletions
+5 -3
View File
@@ -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
View File
@@ -1 +1 @@
v1.7.0
v1.7.3
+23 -1
View File
@@ -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,
+2 -1
View File
@@ -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
View File
@@ -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;
}
+6
View File
@@ -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
View File
@@ -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;
+3 -2
View File
@@ -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;
}
+14 -2
View File
@@ -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]),
};
+2 -1
View File
@@ -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 ***
+1 -1
View File
@@ -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;
+2 -1
View File
@@ -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
+18 -5
View File
@@ -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]),
};
-1
View File
@@ -41,4 +41,3 @@ const safety_hooks gm_ascm_hooks = {
.tx_lin = nooutput_tx_lin_hook,
.fwd = gm_ascm_fwd_hook,
};
+179 -108
View File
@@ -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]),
};
+19 -8
View File
@@ -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]),
};
+3 -2
View File
@@ -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
};
+14 -2
View File
@@ -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]),
};
+2 -1
View File
@@ -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
+83 -57
View File
@@ -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]),
};
+3 -2
View File
@@ -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) {
+16 -4
View File
@@ -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]),
};
+36 -6
View File
@@ -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
+5 -3
View File
@@ -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>
+1 -1
View File
@@ -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).
+5 -5
View File
@@ -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>
+14 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
+23
View File
@@ -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
+4 -4
View File
@@ -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)
+5
View File
@@ -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
+4 -2
View File
@@ -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
+2
View File
@@ -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:
+3 -7
View File
@@ -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);
+4 -17
View File
@@ -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){
+18 -29
View File
@@ -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]:
+140 -81
View File
@@ -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()
+21 -20
View File
@@ -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__":
+58 -50
View File
@@ -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__":
+4 -1
View File
@@ -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):
+4 -10
View File
@@ -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))
+3 -3
View File
@@ -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)
+13 -3
View File
@@ -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