diff --git a/__init__.py b/__init__.py index 665682521f..6c391bb38d 100644 --- a/__init__.py +++ b/__init__.py @@ -3,7 +3,7 @@ from .python.serial import PandaSerial # noqa: F401 from .python.canhandle import CanHandle # noqa: F401 from .python.utils import logger # noqa: F401 -from .python import (Panda, PandaDFU, uds, isotp, # noqa: F401 +from .python import (Panda, PandaDFU, isotp, # noqa: F401 pack_can_buffer, unpack_can_buffer, calculate_checksum, DLC_TO_LEN, LEN_TO_DLC, ALTERNATIVE_EXPERIENCE, CANPACKET_HEAD_SIZE) diff --git a/board/safety.h b/board/safety.h index 913109957c..5ecbc5c95f 100644 --- a/board/safety.h +++ b/board/safety.h @@ -4,26 +4,26 @@ #include "can.h" // include the safety policies. -#include "safety/safety_defaults.h" -#include "safety/safety_honda.h" -#include "safety/safety_toyota.h" -#include "safety/safety_tesla.h" -#include "safety/safety_gm.h" -#include "safety/safety_ford.h" -#include "safety/safety_hyundai.h" -#include "safety/safety_chrysler.h" -#include "safety/safety_subaru.h" -#include "safety/safety_subaru_preglobal.h" -#include "safety/safety_mazda.h" -#include "safety/safety_nissan.h" -#include "safety/safety_volkswagen_mqb.h" -#include "safety/safety_volkswagen_pq.h" -#include "safety/safety_elm327.h" -#include "safety/safety_body.h" +#include "../../opendbc/safety/safety_defaults.h" +#include "../../opendbc/safety/safety_honda.h" +#include "../../opendbc/safety/safety_toyota.h" +#include "../../opendbc/safety/safety_tesla.h" +#include "../../opendbc/safety/safety_gm.h" +#include "../../opendbc/safety/safety_ford.h" +#include "../../opendbc/safety/safety_hyundai.h" +#include "../../opendbc/safety/safety_chrysler.h" +#include "../../opendbc/safety/safety_subaru.h" +#include "../../opendbc/safety/safety_subaru_preglobal.h" +#include "../../opendbc/safety/safety_mazda.h" +#include "../../opendbc/safety/safety_nissan.h" +#include "../../opendbc/safety/safety_volkswagen_mqb.h" +#include "../../opendbc/safety/safety_volkswagen_pq.h" +#include "../../opendbc/safety/safety_elm327.h" +#include "../../opendbc/safety/safety_body.h" // CAN-FD only safety modes #ifdef CANFD -#include "safety/safety_hyundai_canfd.h" +#include "../../opendbc/safety/safety_hyundai_canfd.h" #endif // from cereal.car.CarParams.SafetyModel diff --git a/board/safety/safety_body.h b/board/safety/safety_body.h deleted file mode 100644 index fcba1b577a..0000000000 --- a/board/safety/safety_body.h +++ /dev/null @@ -1,50 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -static void body_rx_hook(const CANPacket_t *to_push) { - // body is never at standstill - vehicle_moving = true; - - if (GET_ADDR(to_push) == 0x201U) { - controls_allowed = true; - } -} - -static bool body_tx_hook(const CANPacket_t *to_send) { - bool tx = true; - int addr = GET_ADDR(to_send); - int len = GET_LEN(to_send); - - if (!controls_allowed && (addr != 0x1)) { - tx = false; - } - - // Allow going into CAN flashing mode for base & knee even if controls are not allowed - bool flash_msg = ((addr == 0x250) || (addr == 0x350)) && (len == 8); - if (!controls_allowed && (GET_BYTES(to_send, 0, 4) == 0xdeadfaceU) && (GET_BYTES(to_send, 4, 4) == 0x0ab00b1eU) && flash_msg) { - tx = true; - } - - return tx; -} - -static safety_config body_init(uint16_t param) { - static RxCheck body_rx_checks[] = { - {.msg = {{0x201, 0, 8, .check_checksum = false, .max_counter = 0U, .frequency = 100U}, { 0 }, { 0 }}}, - }; - - static const CanMsg BODY_TX_MSGS[] = {{0x250, 0, 8}, {0x250, 0, 6}, {0x251, 0, 5}, // body - {0x350, 0, 8}, {0x350, 0, 6}, {0x351, 0, 5}, // knee - {0x1, 0, 8}}; // CAN flasher - - UNUSED(param); - return BUILD_SAFETY_CFG(body_rx_checks, BODY_TX_MSGS); -} - -const safety_hooks body_hooks = { - .init = body_init, - .rx = body_rx_hook, - .tx = body_tx_hook, - .fwd = default_fwd_hook, -}; diff --git a/board/safety/safety_chrysler.h b/board/safety/safety_chrysler.h deleted file mode 100644 index 2bbc942715..0000000000 --- a/board/safety/safety_chrysler.h +++ /dev/null @@ -1,304 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -typedef struct { - const int EPS_2; - const int ESP_1; - const int ESP_8; - const int ECM_5; - const int DAS_3; - const int DAS_6; - const int LKAS_COMMAND; - const int CRUISE_BUTTONS; -} ChryslerAddrs; - -typedef enum { - CHRYSLER_RAM_DT, - CHRYSLER_RAM_HD, - CHRYSLER_PACIFICA, // plus Jeep -} ChryslerPlatform; -static ChryslerPlatform chrysler_platform; -static const ChryslerAddrs *chrysler_addrs; - -static uint32_t chrysler_get_checksum(const CANPacket_t *to_push) { - int checksum_byte = GET_LEN(to_push) - 1U; - return (uint8_t)(GET_BYTE(to_push, checksum_byte)); -} - -static uint32_t chrysler_compute_checksum(const CANPacket_t *to_push) { - // TODO: clean this up - // http://illmatics.com/Remote%20Car%20Hacking.pdf - uint8_t checksum = 0xFFU; - int len = GET_LEN(to_push); - for (int j = 0; j < (len - 1); j++) { - uint8_t shift = 0x80U; - uint8_t curr = (uint8_t)GET_BYTE(to_push, j); - for (int i=0; i<8; i++) { - uint8_t bit_sum = curr & shift; - uint8_t temp_chk = checksum & 0x80U; - if (bit_sum != 0U) { - bit_sum = 0x1C; - if (temp_chk != 0U) { - bit_sum = 1; - } - checksum = checksum << 1; - temp_chk = checksum | 1U; - bit_sum ^= temp_chk; - } else { - if (temp_chk != 0U) { - bit_sum = 0x1D; - } - checksum = checksum << 1; - bit_sum ^= checksum; - } - checksum = bit_sum; - shift = shift >> 1; - } - } - return (uint8_t)(~checksum); -} - -static uint8_t chrysler_get_counter(const CANPacket_t *to_push) { - return (uint8_t)(GET_BYTE(to_push, 6) >> 4); -} - -static void chrysler_rx_hook(const CANPacket_t *to_push) { - const int bus = GET_BUS(to_push); - const int addr = GET_ADDR(to_push); - - // Measured EPS torque - if ((bus == 0) && (addr == chrysler_addrs->EPS_2)) { - int torque_meas_new = ((GET_BYTE(to_push, 4) & 0x7U) << 8) + GET_BYTE(to_push, 5) - 1024U; - update_sample(&torque_meas, torque_meas_new); - } - - // enter controls on rising edge of ACC, exit controls on ACC off - const int das_3_bus = (chrysler_platform == CHRYSLER_PACIFICA) ? 0 : 2; - if ((bus == das_3_bus) && (addr == chrysler_addrs->DAS_3)) { - bool cruise_engaged = GET_BIT(to_push, 21U); - pcm_cruise_check(cruise_engaged); - } - - // TODO: use the same message for both - // update vehicle moving - if ((chrysler_platform != CHRYSLER_PACIFICA) && (bus == 0) && (addr == chrysler_addrs->ESP_8)) { - vehicle_moving = ((GET_BYTE(to_push, 4) << 8) + GET_BYTE(to_push, 5)) != 0U; - } - if ((chrysler_platform == CHRYSLER_PACIFICA) && (bus == 0) && (addr == 514)) { - int speed_l = (GET_BYTE(to_push, 0) << 4) + (GET_BYTE(to_push, 1) >> 4); - int speed_r = (GET_BYTE(to_push, 2) << 4) + (GET_BYTE(to_push, 3) >> 4); - vehicle_moving = (speed_l != 0) || (speed_r != 0); - } - - // exit controls on rising edge of gas press - if ((bus == 0) && (addr == chrysler_addrs->ECM_5)) { - gas_pressed = GET_BYTE(to_push, 0U) != 0U; - } - - // exit controls on rising edge of brake press - if ((bus == 0) && (addr == chrysler_addrs->ESP_1)) { - brake_pressed = ((GET_BYTE(to_push, 0U) & 0xFU) >> 2U) == 1U; - } - - generic_rx_checks((bus == 0) && (addr == chrysler_addrs->LKAS_COMMAND)); -} - -static bool chrysler_tx_hook(const CANPacket_t *to_send) { - const SteeringLimits CHRYSLER_STEERING_LIMITS = { - .max_steer = 261, - .max_rt_delta = 112, - .max_rt_interval = 250000, - .max_rate_up = 3, - .max_rate_down = 3, - .max_torque_error = 80, - .type = TorqueMotorLimited, - }; - - const SteeringLimits CHRYSLER_RAM_DT_STEERING_LIMITS = { - .max_steer = 350, - .max_rt_delta = 112, - .max_rt_interval = 250000, - .max_rate_up = 6, - .max_rate_down = 6, - .max_torque_error = 80, - .type = TorqueMotorLimited, - }; - - const SteeringLimits CHRYSLER_RAM_HD_STEERING_LIMITS = { - .max_steer = 361, - .max_rt_delta = 182, - .max_rt_interval = 250000, - .max_rate_up = 14, - .max_rate_down = 14, - .max_torque_error = 80, - .type = TorqueMotorLimited, - }; - - bool tx = true; - int addr = GET_ADDR(to_send); - - // STEERING - if (addr == chrysler_addrs->LKAS_COMMAND) { - int start_byte = (chrysler_platform == CHRYSLER_PACIFICA) ? 0 : 1; - int desired_torque = ((GET_BYTE(to_send, start_byte) & 0x7U) << 8) | GET_BYTE(to_send, start_byte + 1); - desired_torque -= 1024; - - const SteeringLimits limits = (chrysler_platform == CHRYSLER_PACIFICA) ? CHRYSLER_STEERING_LIMITS : - (chrysler_platform == CHRYSLER_RAM_DT) ? CHRYSLER_RAM_DT_STEERING_LIMITS : CHRYSLER_RAM_HD_STEERING_LIMITS; - - bool steer_req = (chrysler_platform == CHRYSLER_PACIFICA) ? GET_BIT(to_send, 4U) : (GET_BYTE(to_send, 3) & 0x7U) == 2U; - if (steer_torque_cmd_checks(desired_torque, steer_req, limits)) { - tx = false; - } - } - - // FORCE CANCEL: only the cancel button press is allowed - if (addr == chrysler_addrs->CRUISE_BUTTONS) { - const bool is_cancel = GET_BYTE(to_send, 0) == 1U; - const bool is_resume = GET_BYTE(to_send, 0) == 0x10U; - const bool allowed = is_cancel || (is_resume && controls_allowed); - if (!allowed) { - tx = false; - } - } - - return tx; -} - -static int chrysler_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - - // forward to camera - if (bus_num == 0) { - bus_fwd = 2; - } - - // forward all messages from camera except LKAS messages - const bool is_lkas = ((addr == chrysler_addrs->LKAS_COMMAND) || (addr == chrysler_addrs->DAS_6)); - if ((bus_num == 2) && !is_lkas){ - bus_fwd = 0; - } - - return bus_fwd; -} - -static safety_config chrysler_init(uint16_t param) { - - const uint32_t CHRYSLER_PARAM_RAM_DT = 1U; // set for Ram DT platform - - // CAN messages for Chrysler/Jeep platforms - static const ChryslerAddrs CHRYSLER_ADDRS = { - .EPS_2 = 0x220, // EPS driver input torque - .ESP_1 = 0x140, // Brake pedal and vehicle speed - .ESP_8 = 0x11C, // Brake pedal and vehicle speed - .ECM_5 = 0x22F, // Throttle position sensor - .DAS_3 = 0x1F4, // ACC engagement states from DASM - .DAS_6 = 0x2A6, // LKAS HUD and auto headlight control from DASM - .LKAS_COMMAND = 0x292, // LKAS controls from DASM - .CRUISE_BUTTONS = 0x23B, // Cruise control buttons - }; - - // CAN messages for the 5th gen RAM DT platform - static const ChryslerAddrs CHRYSLER_RAM_DT_ADDRS = { - .EPS_2 = 0x31, // EPS driver input torque - .ESP_1 = 0x83, // Brake pedal and vehicle speed - .ESP_8 = 0x79, // Brake pedal and vehicle speed - .ECM_5 = 0x9D, // Throttle position sensor - .DAS_3 = 0x99, // ACC engagement states from DASM - .DAS_6 = 0xFA, // LKAS HUD and auto headlight control from DASM - .LKAS_COMMAND = 0xA6, // LKAS controls from DASM - .CRUISE_BUTTONS = 0xB1, // Cruise control buttons - }; - - static RxCheck chrysler_ram_dt_rx_checks[] = { - {.msg = {{CHRYSLER_RAM_DT_ADDRS.EPS_2, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{CHRYSLER_RAM_DT_ADDRS.ESP_1, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{CHRYSLER_RAM_DT_ADDRS.ESP_8, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{CHRYSLER_RAM_DT_ADDRS.ECM_5, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{CHRYSLER_RAM_DT_ADDRS.DAS_3, 2, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - }; - - static RxCheck chrysler_rx_checks[] = { - {.msg = {{CHRYSLER_ADDRS.EPS_2, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{CHRYSLER_ADDRS.ESP_1, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - //{.msg = {{ESP_8, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}}}, - {.msg = {{514, 0, 8, .check_checksum = false, .max_counter = 0U, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{CHRYSLER_ADDRS.ECM_5, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{CHRYSLER_ADDRS.DAS_3, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - }; - - static const CanMsg CHRYSLER_TX_MSGS[] = { - {CHRYSLER_ADDRS.CRUISE_BUTTONS, 0, 3}, - {CHRYSLER_ADDRS.LKAS_COMMAND, 0, 6}, - {CHRYSLER_ADDRS.DAS_6, 0, 8}, - }; - - static const CanMsg CHRYSLER_RAM_DT_TX_MSGS[] = { - {CHRYSLER_RAM_DT_ADDRS.CRUISE_BUTTONS, 2, 3}, - {CHRYSLER_RAM_DT_ADDRS.LKAS_COMMAND, 0, 8}, - {CHRYSLER_RAM_DT_ADDRS.DAS_6, 0, 8}, - }; - -#ifdef ALLOW_DEBUG - // CAN messages for the 5th gen RAM HD platform - static const ChryslerAddrs CHRYSLER_RAM_HD_ADDRS = { - .EPS_2 = 0x220, // EPS driver input torque - .ESP_1 = 0x140, // Brake pedal and vehicle speed - .ESP_8 = 0x11C, // Brake pedal and vehicle speed - .ECM_5 = 0x22F, // Throttle position sensor - .DAS_3 = 0x1F4, // ACC engagement states from DASM - .DAS_6 = 0x275, // LKAS HUD and auto headlight control from DASM - .LKAS_COMMAND = 0x276, // LKAS controls from DASM - .CRUISE_BUTTONS = 0x23A, // Cruise control buttons - }; - - static RxCheck chrysler_ram_hd_rx_checks[] = { - {.msg = {{CHRYSLER_RAM_HD_ADDRS.EPS_2, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{CHRYSLER_RAM_HD_ADDRS.ESP_1, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{CHRYSLER_RAM_HD_ADDRS.ESP_8, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{CHRYSLER_RAM_HD_ADDRS.ECM_5, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{CHRYSLER_RAM_HD_ADDRS.DAS_3, 2, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - }; - - static const CanMsg CHRYSLER_RAM_HD_TX_MSGS[] = { - {CHRYSLER_RAM_HD_ADDRS.CRUISE_BUTTONS, 2, 3}, - {CHRYSLER_RAM_HD_ADDRS.LKAS_COMMAND, 0, 8}, - {CHRYSLER_RAM_HD_ADDRS.DAS_6, 0, 8}, - }; - - const uint32_t CHRYSLER_PARAM_RAM_HD = 2U; // set for Ram HD platform - bool enable_ram_hd = GET_FLAG(param, CHRYSLER_PARAM_RAM_HD); -#endif - - safety_config ret; - - bool enable_ram_dt = GET_FLAG(param, CHRYSLER_PARAM_RAM_DT); - - if (enable_ram_dt) { - chrysler_platform = CHRYSLER_RAM_DT; - chrysler_addrs = &CHRYSLER_RAM_DT_ADDRS; - ret = BUILD_SAFETY_CFG(chrysler_ram_dt_rx_checks, CHRYSLER_RAM_DT_TX_MSGS); -#ifdef ALLOW_DEBUG - } else if (enable_ram_hd) { - chrysler_platform = CHRYSLER_RAM_HD; - chrysler_addrs = &CHRYSLER_RAM_HD_ADDRS; - ret = BUILD_SAFETY_CFG(chrysler_ram_hd_rx_checks, CHRYSLER_RAM_HD_TX_MSGS); -#endif - } else { - chrysler_platform = CHRYSLER_PACIFICA; - chrysler_addrs = &CHRYSLER_ADDRS; - ret = BUILD_SAFETY_CFG(chrysler_rx_checks, CHRYSLER_TX_MSGS); - } - return ret; -} - -const safety_hooks chrysler_hooks = { - .init = chrysler_init, - .rx = chrysler_rx_hook, - .tx = chrysler_tx_hook, - .fwd = chrysler_fwd_hook, - .get_counter = chrysler_get_counter, - .get_checksum = chrysler_get_checksum, - .compute_checksum = chrysler_compute_checksum, -}; diff --git a/board/safety/safety_defaults.h b/board/safety/safety_defaults.h deleted file mode 100644 index 6716b57b3c..0000000000 --- a/board/safety/safety_defaults.h +++ /dev/null @@ -1,73 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -void default_rx_hook(const CANPacket_t *to_push) { - UNUSED(to_push); -} - -// *** no output safety mode *** - -static safety_config nooutput_init(uint16_t param) { - UNUSED(param); - return (safety_config){NULL, 0, NULL, 0}; -} - -static bool nooutput_tx_hook(const CANPacket_t *to_send) { - UNUSED(to_send); - return false; -} - -static int default_fwd_hook(int bus_num, int addr) { - UNUSED(bus_num); - UNUSED(addr); - return -1; -} - -const safety_hooks nooutput_hooks = { - .init = nooutput_init, - .rx = default_rx_hook, - .tx = nooutput_tx_hook, - .fwd = default_fwd_hook, -}; - -// *** all output safety mode *** - -// Enables passthrough mode where relay is open and bus 0 gets forwarded to bus 2 and vice versa -static bool alloutput_passthrough = false; - -static safety_config alloutput_init(uint16_t param) { - // Enables passthrough mode where relay is open and bus 0 gets forwarded to bus 2 and vice versa - const uint16_t ALLOUTPUT_PARAM_PASSTHROUGH = 1; - controls_allowed = true; - alloutput_passthrough = GET_FLAG(param, ALLOUTPUT_PARAM_PASSTHROUGH); - return (safety_config){NULL, 0, NULL, 0}; -} - -static bool alloutput_tx_hook(const CANPacket_t *to_send) { - UNUSED(to_send); - return true; -} - -static int alloutput_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - UNUSED(addr); - - if (alloutput_passthrough) { - if (bus_num == 0) { - bus_fwd = 2; - } - if (bus_num == 2) { - bus_fwd = 0; - } - } - - return bus_fwd; -} - -const safety_hooks alloutput_hooks = { - .init = alloutput_init, - .rx = default_rx_hook, - .tx = alloutput_tx_hook, - .fwd = alloutput_fwd_hook, -}; diff --git a/board/safety/safety_elm327.h b/board/safety/safety_elm327.h deleted file mode 100644 index 83efd826b9..0000000000 --- a/board/safety/safety_elm327.h +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include "safety_declarations.h" -#include "safety_defaults.h" - -static bool elm327_tx_hook(const CANPacket_t *to_send) { - const int GM_CAMERA_DIAG_ADDR = 0x24B; - - bool tx = true; - int addr = GET_ADDR(to_send); - int len = GET_LEN(to_send); - - // All ISO 15765-4 messages must be 8 bytes long - if (len != 8) { - tx = false; - } - - // 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 & 0x1FFFFF00) != 0x600) && ((addr & 0x1FFFFF00) != 0x700) && - (addr != GM_CAMERA_DIAG_ADDR)) { - tx = false; - } - - // GM camera uses non-standard diagnostic address, this has no control message address collisions - if ((addr == GM_CAMERA_DIAG_ADDR) && (len == 8)) { - // Only allow known frame types for ISO 15765-2 - if ((GET_BYTE(to_send, 0) & 0xF0U) > 0x30U) { - tx = false; - } - } - return tx; -} - -// If current_board->has_obd and safety_param == 0, bus 1 is multiplexed to the OBD-II port -const safety_hooks elm327_hooks = { - .init = nooutput_init, - .rx = default_rx_hook, - .tx = elm327_tx_hook, - .fwd = default_fwd_hook, -}; diff --git a/board/safety/safety_ford.h b/board/safety/safety_ford.h deleted file mode 100644 index 5b19dd9ca5..0000000000 --- a/board/safety/safety_ford.h +++ /dev/null @@ -1,435 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -// Safety-relevant CAN messages for Ford vehicles. -#define FORD_EngBrakeData 0x165 // RX from PCM, for driver brake pedal and cruise state -#define FORD_EngVehicleSpThrottle 0x204 // RX from PCM, for driver throttle input -#define FORD_DesiredTorqBrk 0x213 // RX from ABS, for standstill state -#define FORD_BrakeSysFeatures 0x415 // RX from ABS, for vehicle speed -#define FORD_EngVehicleSpThrottle2 0x202 // RX from PCM, for second vehicle speed -#define FORD_Yaw_Data_FD1 0x91 // RX from RCM, for yaw rate -#define FORD_Steering_Data_FD1 0x083 // TX by OP, various driver switches and LKAS/CC buttons -#define FORD_ACCDATA 0x186 // TX by OP, ACC controls -#define FORD_ACCDATA_3 0x18A // TX by OP, ACC/TJA user interface -#define FORD_Lane_Assist_Data1 0x3CA // TX by OP, Lane Keep Assist -#define FORD_LateralMotionControl 0x3D3 // TX by OP, Lateral Control message -#define FORD_LateralMotionControl2 0x3D6 // TX by OP, alternate Lateral Control message -#define FORD_IPMA_Data 0x3D8 // TX by OP, IPMA and LKAS user interface - -// CAN bus numbers. -#define FORD_MAIN_BUS 0U -#define FORD_CAM_BUS 2U - -static uint8_t ford_get_counter(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - - uint8_t cnt = 0; - if (addr == FORD_BrakeSysFeatures) { - // Signal: VehVActlBrk_No_Cnt - cnt = (GET_BYTE(to_push, 2) >> 2) & 0xFU; - } else if (addr == FORD_Yaw_Data_FD1) { - // Signal: VehRollYaw_No_Cnt - cnt = GET_BYTE(to_push, 5); - } else { - } - return cnt; -} - -static uint32_t ford_get_checksum(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - - uint8_t chksum = 0; - if (addr == FORD_BrakeSysFeatures) { - // Signal: VehVActlBrk_No_Cs - chksum = GET_BYTE(to_push, 3); - } else if (addr == FORD_Yaw_Data_FD1) { - // Signal: VehRollYawW_No_Cs - chksum = GET_BYTE(to_push, 4); - } else { - } - return chksum; -} - -static uint32_t ford_compute_checksum(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - - uint8_t chksum = 0; - if (addr == FORD_BrakeSysFeatures) { - chksum += GET_BYTE(to_push, 0) + GET_BYTE(to_push, 1); // Veh_V_ActlBrk - chksum += GET_BYTE(to_push, 2) >> 6; // VehVActlBrk_D_Qf - chksum += (GET_BYTE(to_push, 2) >> 2) & 0xFU; // VehVActlBrk_No_Cnt - chksum = 0xFFU - chksum; - } else if (addr == FORD_Yaw_Data_FD1) { - chksum += GET_BYTE(to_push, 0) + GET_BYTE(to_push, 1); // VehRol_W_Actl - chksum += GET_BYTE(to_push, 2) + GET_BYTE(to_push, 3); // VehYaw_W_Actl - chksum += GET_BYTE(to_push, 5); // VehRollYaw_No_Cnt - chksum += GET_BYTE(to_push, 6) >> 6; // VehRolWActl_D_Qf - chksum += (GET_BYTE(to_push, 6) >> 4) & 0x3U; // VehYawWActl_D_Qf - chksum = 0xFFU - chksum; - } else { - } - - return chksum; -} - -static bool ford_get_quality_flag_valid(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - - bool valid = false; - if (addr == FORD_BrakeSysFeatures) { - valid = (GET_BYTE(to_push, 2) >> 6) == 0x3U; // VehVActlBrk_D_Qf - } else if (addr == FORD_EngVehicleSpThrottle2) { - valid = ((GET_BYTE(to_push, 4) >> 5) & 0x3U) == 0x3U; // VehVActlEng_D_Qf - } else if (addr == FORD_Yaw_Data_FD1) { - valid = ((GET_BYTE(to_push, 6) >> 4) & 0x3U) == 0x3U; // VehYawWActl_D_Qf - } else { - } - return valid; -} - -static bool ford_longitudinal = false; - -#define FORD_INACTIVE_CURVATURE 1000U -#define FORD_INACTIVE_CURVATURE_RATE 4096U -#define FORD_INACTIVE_PATH_OFFSET 512U -#define FORD_INACTIVE_PATH_ANGLE 1000U - -#define FORD_CANFD_INACTIVE_CURVATURE_RATE 1024U - -#define FORD_MAX_SPEED_DELTA 2.0 // m/s - -static bool ford_lkas_msg_check(int addr) { - return (addr == FORD_ACCDATA_3) - || (addr == FORD_Lane_Assist_Data1) - || (addr == FORD_LateralMotionControl) - || (addr == FORD_LateralMotionControl2) - || (addr == FORD_IPMA_Data); -} - -// Curvature rate limits -static const SteeringLimits FORD_STEERING_LIMITS = { - .max_steer = 1000, - .angle_deg_to_can = 50000, // 1 / (2e-5) rad to can - .max_angle_error = 100, // 0.002 * FORD_STEERING_LIMITS.angle_deg_to_can - .angle_rate_up_lookup = { - {5., 25., 25.}, - {0.00045, 0.0001, 0.0001} - }, - .angle_rate_down_lookup = { - {5., 25., 25.}, - {0.00045, 0.00015, 0.00015} - }, - - // no blending at low speed due to lack of torque wind-up and inaccurate current curvature - .angle_error_min_speed = 10.0, // m/s - - .enforce_angle_error = true, - .inactive_angle_is_zero = true, -}; - -static void ford_rx_hook(const CANPacket_t *to_push) { - if (GET_BUS(to_push) == FORD_MAIN_BUS) { - int addr = GET_ADDR(to_push); - - // Update in motion state from standstill signal - if (addr == FORD_DesiredTorqBrk) { - // Signal: VehStop_D_Stat - vehicle_moving = ((GET_BYTE(to_push, 3) >> 3) & 0x3U) != 1U; - } - - // Update vehicle speed - if (addr == FORD_BrakeSysFeatures) { - // Signal: Veh_V_ActlBrk - UPDATE_VEHICLE_SPEED(((GET_BYTE(to_push, 0) << 8) | GET_BYTE(to_push, 1)) * 0.01 / 3.6); - } - - // Check vehicle speed against a second source - if (addr == FORD_EngVehicleSpThrottle2) { - // Disable controls if speeds from ABS and PCM ECUs are too far apart. - // Signal: Veh_V_ActlEng - float filtered_pcm_speed = ((GET_BYTE(to_push, 6) << 8) | GET_BYTE(to_push, 7)) * 0.01 / 3.6; - bool is_invalid_speed = ABS(filtered_pcm_speed - ((float)vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR)) > FORD_MAX_SPEED_DELTA; - if (is_invalid_speed) { - controls_allowed = false; - } - } - - // Update vehicle yaw rate - if (addr == FORD_Yaw_Data_FD1) { - // Signal: VehYaw_W_Actl - float ford_yaw_rate = (((GET_BYTE(to_push, 2) << 8U) | GET_BYTE(to_push, 3)) * 0.0002) - 6.5; - float current_curvature = ford_yaw_rate / MAX(vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR, 0.1); - // convert current curvature into units on CAN for comparison with desired curvature - update_sample(&angle_meas, ROUND(current_curvature * FORD_STEERING_LIMITS.angle_deg_to_can)); - } - - // Update gas pedal - if (addr == FORD_EngVehicleSpThrottle) { - // Pedal position: (0.1 * val) in percent - // Signal: ApedPos_Pc_ActlArb - gas_pressed = (((GET_BYTE(to_push, 0) & 0x03U) << 8) | GET_BYTE(to_push, 1)) > 0U; - } - - // Update brake pedal and cruise state - if (addr == FORD_EngBrakeData) { - // Signal: BpedDrvAppl_D_Actl - brake_pressed = ((GET_BYTE(to_push, 0) >> 4) & 0x3U) == 2U; - - // Signal: CcStat_D_Actl - unsigned int cruise_state = GET_BYTE(to_push, 1) & 0x07U; - bool cruise_engaged = (cruise_state == 4U) || (cruise_state == 5U); - pcm_cruise_check(cruise_engaged); - } - - // If steering controls messages are received on the destination bus, it's an indication - // that the relay might be malfunctioning. - bool stock_ecu_detected = ford_lkas_msg_check(addr); - if (ford_longitudinal) { - stock_ecu_detected = stock_ecu_detected || (addr == FORD_ACCDATA); - } - generic_rx_checks(stock_ecu_detected); - } - -} - -static bool ford_tx_hook(const CANPacket_t *to_send) { - const LongitudinalLimits FORD_LONG_LIMITS = { - // acceleration cmd limits (used for brakes) - // Signal: AccBrkTot_A_Rq - .max_accel = 5641, // 1.9999 m/s^s - .min_accel = 4231, // -3.4991 m/s^2 - .inactive_accel = 5128, // -0.0008 m/s^2 - - // gas cmd limits - // Signal: AccPrpl_A_Rq & AccPrpl_A_Pred - .max_gas = 700, // 2.0 m/s^2 - .min_gas = 450, // -0.5 m/s^2 - .inactive_gas = 0, // -5.0 m/s^2 - }; - - bool tx = true; - - int addr = GET_ADDR(to_send); - - // Safety check for ACCDATA accel and brake requests - if (addr == FORD_ACCDATA) { - // Signal: AccPrpl_A_Rq - int gas = ((GET_BYTE(to_send, 6) & 0x3U) << 8) | GET_BYTE(to_send, 7); - // Signal: AccPrpl_A_Pred - int gas_pred = ((GET_BYTE(to_send, 2) & 0x3U) << 8) | GET_BYTE(to_send, 3); - // Signal: AccBrkTot_A_Rq - int accel = ((GET_BYTE(to_send, 0) & 0x1FU) << 8) | GET_BYTE(to_send, 1); - // Signal: CmbbDeny_B_Actl - bool cmbb_deny = GET_BIT(to_send, 37U); - - // Signal: AccBrkPrchg_B_Rq & AccBrkDecel_B_Rq - bool brake_actuation = GET_BIT(to_send, 54U) || GET_BIT(to_send, 55U); - - bool violation = false; - violation |= longitudinal_accel_checks(accel, FORD_LONG_LIMITS); - violation |= longitudinal_gas_checks(gas, FORD_LONG_LIMITS); - violation |= longitudinal_gas_checks(gas_pred, FORD_LONG_LIMITS); - - // Safety check for stock AEB - violation |= cmbb_deny; // do not prevent stock AEB actuation - - violation |= !get_longitudinal_allowed() && brake_actuation; - - if (violation) { - tx = false; - } - } - - // Safety check for Steering_Data_FD1 button signals - // Note: Many other signals in this message are not relevant to safety (e.g. blinkers, wiper switches, high beam) - // which we passthru in OP. - if (addr == FORD_Steering_Data_FD1) { - // Violation if resume button is pressed while controls not allowed, or - // if cancel button is pressed when cruise isn't engaged. - bool violation = false; - violation |= GET_BIT(to_send, 8U) && !cruise_engaged_prev; // Signal: CcAslButtnCnclPress (cancel) - violation |= GET_BIT(to_send, 25U) && !controls_allowed; // Signal: CcAsllButtnResPress (resume) - - if (violation) { - tx = false; - } - } - - // Safety check for Lane_Assist_Data1 action - if (addr == FORD_Lane_Assist_Data1) { - // Do not allow steering using Lane_Assist_Data1 (Lane-Departure Aid). - // This message must be sent for Lane Centering to work, and can include - // values such as the steering angle or lane curvature for debugging, - // but the action (LkaActvStats_D2_Req) must be set to zero. - unsigned int action = GET_BYTE(to_send, 0) >> 5; - if (action != 0U) { - tx = false; - } - } - - // Safety check for LateralMotionControl action - if (addr == FORD_LateralMotionControl) { - // Signal: LatCtl_D_Rq - bool steer_control_enabled = ((GET_BYTE(to_send, 4) >> 2) & 0x7U) != 0U; - unsigned int raw_curvature = (GET_BYTE(to_send, 0) << 3) | (GET_BYTE(to_send, 1) >> 5); - unsigned int raw_curvature_rate = ((GET_BYTE(to_send, 1) & 0x1FU) << 8) | GET_BYTE(to_send, 2); - unsigned int raw_path_angle = (GET_BYTE(to_send, 3) << 3) | (GET_BYTE(to_send, 4) >> 5); - unsigned int raw_path_offset = (GET_BYTE(to_send, 5) << 2) | (GET_BYTE(to_send, 6) >> 6); - - // These signals are not yet tested with the current safety limits - bool violation = (raw_curvature_rate != FORD_INACTIVE_CURVATURE_RATE) || (raw_path_angle != FORD_INACTIVE_PATH_ANGLE) || (raw_path_offset != FORD_INACTIVE_PATH_OFFSET); - - // Check angle error and steer_control_enabled - int desired_curvature = raw_curvature - FORD_INACTIVE_CURVATURE; // /FORD_STEERING_LIMITS.angle_deg_to_can to get real curvature - violation |= steer_angle_cmd_checks(desired_curvature, steer_control_enabled, FORD_STEERING_LIMITS); - - if (violation) { - tx = false; - } - } - - // Safety check for LateralMotionControl2 action - if (addr == FORD_LateralMotionControl2) { - // Signal: LatCtl_D2_Rq - bool steer_control_enabled = ((GET_BYTE(to_send, 0) >> 4) & 0x7U) != 0U; - unsigned int raw_curvature = (GET_BYTE(to_send, 2) << 3) | (GET_BYTE(to_send, 3) >> 5); - unsigned int raw_curvature_rate = (GET_BYTE(to_send, 6) << 3) | (GET_BYTE(to_send, 7) >> 5); - unsigned int raw_path_angle = ((GET_BYTE(to_send, 3) & 0x1FU) << 6) | (GET_BYTE(to_send, 4) >> 2); - unsigned int raw_path_offset = ((GET_BYTE(to_send, 4) & 0x3U) << 8) | GET_BYTE(to_send, 5); - - // These signals are not yet tested with the current safety limits - bool violation = (raw_curvature_rate != FORD_CANFD_INACTIVE_CURVATURE_RATE) || (raw_path_angle != FORD_INACTIVE_PATH_ANGLE) || (raw_path_offset != FORD_INACTIVE_PATH_OFFSET); - - // Check angle error and steer_control_enabled - int desired_curvature = raw_curvature - FORD_INACTIVE_CURVATURE; // /FORD_STEERING_LIMITS.angle_deg_to_can to get real curvature - violation |= steer_angle_cmd_checks(desired_curvature, steer_control_enabled, FORD_STEERING_LIMITS); - - if (violation) { - tx = false; - } - } - - return tx; -} - -static int ford_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - - switch (bus_num) { - case FORD_MAIN_BUS: { - // Forward all traffic from bus 0 onward - bus_fwd = FORD_CAM_BUS; - break; - } - case FORD_CAM_BUS: { - if (ford_lkas_msg_check(addr)) { - // Block stock LKAS and UI messages - bus_fwd = -1; - } else if (ford_longitudinal && (addr == FORD_ACCDATA)) { - // Block stock ACC message - bus_fwd = -1; - } else { - // Forward remaining traffic - bus_fwd = FORD_MAIN_BUS; - } - break; - } - default: { - // No other buses should be in use; fallback to do-not-forward - bus_fwd = -1; - break; - } - } - - return bus_fwd; -} - -static safety_config ford_init(uint16_t param) { - bool ford_canfd = false; - - // warning: quality flags are not yet checked in openpilot's CAN parser, - // this may be the cause of blocked messages - static RxCheck ford_rx_checks[] = { - {.msg = {{FORD_BrakeSysFeatures, 0, 8, .check_checksum = true, .max_counter = 15U, .quality_flag=true, .frequency = 50U}, { 0 }, { 0 }}}, - // FORD_EngVehicleSpThrottle2 has a counter that either randomly skips or by 2, likely ECU bug - // Some hybrid models also experience a bug where this checksum mismatches for one or two frames under heavy acceleration with ACC - // It has been confirmed that the Bronco Sport's camera only disallows ACC for bad quality flags, not counters or checksums, so we match that - {.msg = {{FORD_EngVehicleSpThrottle2, 0, 8, .check_checksum = false, .quality_flag=true, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{FORD_Yaw_Data_FD1, 0, 8, .check_checksum = true, .max_counter = 255U, .quality_flag=true, .frequency = 100U}, { 0 }, { 0 }}}, - // These messages have no counter or checksum - {.msg = {{FORD_EngBrakeData, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, - {.msg = {{FORD_EngVehicleSpThrottle, 0, 8, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{FORD_DesiredTorqBrk, 0, 8, .frequency = 50U}, { 0 }, { 0 }}}, - }; - - static const CanMsg FORD_CANFD_LONG_TX_MSGS[] = { - {FORD_Steering_Data_FD1, 0, 8}, - {FORD_Steering_Data_FD1, 2, 8}, - {FORD_ACCDATA, 0, 8}, - {FORD_ACCDATA_3, 0, 8}, - {FORD_Lane_Assist_Data1, 0, 8}, - {FORD_LateralMotionControl2, 0, 8}, - {FORD_IPMA_Data, 0, 8}, - }; - - static const CanMsg FORD_CANFD_STOCK_TX_MSGS[] = { - {FORD_Steering_Data_FD1, 0, 8}, - {FORD_Steering_Data_FD1, 2, 8}, - {FORD_ACCDATA_3, 0, 8}, - {FORD_Lane_Assist_Data1, 0, 8}, - {FORD_LateralMotionControl2, 0, 8}, - {FORD_IPMA_Data, 0, 8}, - }; - - static const CanMsg FORD_STOCK_TX_MSGS[] = { - {FORD_Steering_Data_FD1, 0, 8}, - {FORD_Steering_Data_FD1, 2, 8}, - {FORD_ACCDATA_3, 0, 8}, - {FORD_Lane_Assist_Data1, 0, 8}, - {FORD_LateralMotionControl, 0, 8}, - {FORD_IPMA_Data, 0, 8}, - }; - - static const CanMsg FORD_LONG_TX_MSGS[] = { - {FORD_Steering_Data_FD1, 0, 8}, - {FORD_Steering_Data_FD1, 2, 8}, - {FORD_ACCDATA, 0, 8}, - {FORD_ACCDATA_3, 0, 8}, - {FORD_Lane_Assist_Data1, 0, 8}, - {FORD_LateralMotionControl, 0, 8}, - {FORD_IPMA_Data, 0, 8}, - }; - - UNUSED(param); -#ifdef ALLOW_DEBUG - const uint16_t FORD_PARAM_LONGITUDINAL = 1; - const uint16_t FORD_PARAM_CANFD = 2; - ford_longitudinal = GET_FLAG(param, FORD_PARAM_LONGITUDINAL); - ford_canfd = GET_FLAG(param, FORD_PARAM_CANFD); -#endif - - safety_config ret; - // FIXME: cppcheck thinks that ford_canfd is always false. This is not true - // if ALLOW_DEBUG is defined but cppcheck is run without ALLOW_DEBUG - // cppcheck-suppress knownConditionTrueFalse - if (ford_canfd) { - ret = ford_longitudinal ? BUILD_SAFETY_CFG(ford_rx_checks, FORD_CANFD_LONG_TX_MSGS) : \ - BUILD_SAFETY_CFG(ford_rx_checks, FORD_CANFD_STOCK_TX_MSGS); - } else { - ret = ford_longitudinal ? BUILD_SAFETY_CFG(ford_rx_checks, FORD_LONG_TX_MSGS) : \ - BUILD_SAFETY_CFG(ford_rx_checks, FORD_STOCK_TX_MSGS); - } - return ret; -} - -const safety_hooks ford_hooks = { - .init = ford_init, - .rx = ford_rx_hook, - .tx = ford_tx_hook, - .fwd = ford_fwd_hook, - .get_counter = ford_get_counter, - .get_checksum = ford_get_checksum, - .compute_checksum = ford_compute_checksum, - .get_quality_flag_valid = ford_get_quality_flag_valid, -}; diff --git a/board/safety/safety_gm.h b/board/safety/safety_gm.h deleted file mode 100644 index f0902a921a..0000000000 --- a/board/safety/safety_gm.h +++ /dev/null @@ -1,259 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -static const LongitudinalLimits *gm_long_limits; - -enum { - GM_BTN_UNPRESS = 1, - GM_BTN_RESUME = 2, - GM_BTN_SET = 3, - GM_BTN_CANCEL = 6, -}; - -typedef enum { - GM_ASCM, - GM_CAM -} GmHardware; -static GmHardware gm_hw = GM_ASCM; -static bool gm_cam_long = false; -static bool gm_pcm_cruise = false; - -static void gm_rx_hook(const CANPacket_t *to_push) { - - const int GM_STANDSTILL_THRSLD = 10; // 0.311kph - - - - if (GET_BUS(to_push) == 0U) { - int addr = GET_ADDR(to_push); - - if (addr == 0x184) { - int torque_driver_new = ((GET_BYTE(to_push, 6) & 0x7U) << 8) | GET_BYTE(to_push, 7); - torque_driver_new = to_signed(torque_driver_new, 11); - // update array of samples - update_sample(&torque_driver, torque_driver_new); - } - - // sample rear wheel speeds - if (addr == 0x34A) { - int left_rear_speed = (GET_BYTE(to_push, 0) << 8) | GET_BYTE(to_push, 1); - int right_rear_speed = (GET_BYTE(to_push, 2) << 8) | GET_BYTE(to_push, 3); - vehicle_moving = (left_rear_speed > GM_STANDSTILL_THRSLD) || (right_rear_speed > GM_STANDSTILL_THRSLD); - } - - // ACC steering wheel buttons (GM_CAM is tied to the PCM) - if ((addr == 0x1E1) && !gm_pcm_cruise) { - int button = (GET_BYTE(to_push, 5) & 0x70U) >> 4; - - // enter controls on falling edge of set or rising edge of resume (avoids fault) - bool set = (button != GM_BTN_SET) && (cruise_button_prev == GM_BTN_SET); - bool res = (button == GM_BTN_RESUME) && (cruise_button_prev != GM_BTN_RESUME); - if (set || res) { - controls_allowed = true; - } - - // exit controls on cancel press - if (button == GM_BTN_CANCEL) { - controls_allowed = false; - } - - cruise_button_prev = button; - } - - // Reference for brake pressed signals: - // https://github.com/commaai/openpilot/blob/master/selfdrive/car/gm/carstate.py - if ((addr == 0xBE) && (gm_hw == GM_ASCM)) { - brake_pressed = GET_BYTE(to_push, 1) >= 8U; - } - - if ((addr == 0xC9) && (gm_hw == GM_CAM)) { - brake_pressed = GET_BIT(to_push, 40U); - } - - if (addr == 0x1C4) { - gas_pressed = GET_BYTE(to_push, 5) != 0U; - - // enter controls on rising edge of ACC, exit controls when ACC off - if (gm_pcm_cruise) { - bool cruise_engaged = (GET_BYTE(to_push, 1) >> 5) != 0U; - pcm_cruise_check(cruise_engaged); - } - } - - if (addr == 0xBD) { - regen_braking = (GET_BYTE(to_push, 0) >> 4) != 0U; - } - - bool stock_ecu_detected = (addr == 0x180); // ASCMLKASteeringCmd - - // Check ASCMGasRegenCmd only if we're blocking it - if (!gm_pcm_cruise && (addr == 0x2CB)) { - stock_ecu_detected = true; - } - generic_rx_checks(stock_ecu_detected); - } -} - -static bool gm_tx_hook(const CANPacket_t *to_send) { - const SteeringLimits GM_STEERING_LIMITS = { - .max_steer = 300, - .max_rate_up = 10, - .max_rate_down = 15, - .driver_torque_allowance = 65, - .driver_torque_factor = 4, - .max_rt_delta = 128, - .max_rt_interval = 250000, - .type = TorqueDriverLimited, - }; - - bool tx = true; - int addr = GET_ADDR(to_send); - - // BRAKE: safety check - if (addr == 0x315) { - int brake = ((GET_BYTE(to_send, 0) & 0xFU) << 8) + GET_BYTE(to_send, 1); - brake = (0x1000 - brake) & 0xFFF; - if (longitudinal_brake_checks(brake, *gm_long_limits)) { - tx = false; - } - } - - // LKA STEER: safety check - if (addr == 0x180) { - int desired_torque = ((GET_BYTE(to_send, 0) & 0x7U) << 8) + GET_BYTE(to_send, 1); - desired_torque = to_signed(desired_torque, 11); - - bool steer_req = GET_BIT(to_send, 3U); - - if (steer_torque_cmd_checks(desired_torque, steer_req, GM_STEERING_LIMITS)) { - tx = false; - } - } - - // GAS/REGEN: safety check - if (addr == 0x2CB) { - bool apply = GET_BIT(to_send, 0U); - int gas_regen = ((GET_BYTE(to_send, 2) & 0x7FU) << 5) + ((GET_BYTE(to_send, 3) & 0xF8U) >> 3); - - bool violation = false; - // Allow apply bit in pre-enabled and overriding states - violation |= !controls_allowed && apply; - violation |= longitudinal_gas_checks(gas_regen, *gm_long_limits); - - if (violation) { - tx = false; - } - } - - // BUTTONS: used for resume spamming and cruise cancellation with stock longitudinal - if ((addr == 0x1E1) && gm_pcm_cruise) { - int button = (GET_BYTE(to_send, 5) >> 4) & 0x7U; - - bool allowed_cancel = (button == 6) && cruise_engaged_prev; - if (!allowed_cancel) { - tx = false; - } - } - - return tx; -} - -static int gm_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - - if (gm_hw == GM_CAM) { - if (bus_num == 0) { - // block PSCMStatus; forwarded through openpilot to hide an alert from the camera - bool is_pscm_msg = (addr == 0x184); - if (!is_pscm_msg) { - bus_fwd = 2; - } - } - - if (bus_num == 2) { - // block lkas message and acc messages if gm_cam_long, forward all others - bool is_lkas_msg = (addr == 0x180); - bool is_acc_msg = (addr == 0x315) || (addr == 0x2CB) || (addr == 0x370); - bool block_msg = is_lkas_msg || (is_acc_msg && gm_cam_long); - if (!block_msg) { - bus_fwd = 0; - } - } - } - - return bus_fwd; -} - -static safety_config gm_init(uint16_t param) { - const uint16_t GM_PARAM_HW_CAM = 1; - - static const LongitudinalLimits GM_ASCM_LONG_LIMITS = { - .max_gas = 3072, - .min_gas = 1404, - .inactive_gas = 1404, - .max_brake = 400, - }; - - static const CanMsg GM_ASCM_TX_MSGS[] = {{0x180, 0, 4}, {0x409, 0, 7}, {0x40A, 0, 7}, {0x2CB, 0, 8}, {0x370, 0, 6}, // pt bus - {0xA1, 1, 7}, {0x306, 1, 8}, {0x308, 1, 7}, {0x310, 1, 2}, // obs bus - {0x315, 2, 5}}; // ch bus - - - static const LongitudinalLimits GM_CAM_LONG_LIMITS = { - .max_gas = 3400, - .min_gas = 1514, - .inactive_gas = 1554, - .max_brake = 400, - }; - - static const CanMsg GM_CAM_LONG_TX_MSGS[] = {{0x180, 0, 4}, {0x315, 0, 5}, {0x2CB, 0, 8}, {0x370, 0, 6}, // pt bus - {0x184, 2, 8}}; // camera bus - - - // TODO: do checksum and counter checks. Add correct timestep, 0.1s for now. - static RxCheck gm_rx_checks[] = { - {.msg = {{0x184, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, - {.msg = {{0x34A, 0, 5, .frequency = 10U}, { 0 }, { 0 }}}, - {.msg = {{0x1E1, 0, 7, .frequency = 10U}, { 0 }, { 0 }}}, - {.msg = {{0xBE, 0, 6, .frequency = 10U}, // Volt, Silverado, Acadia Denali - {0xBE, 0, 7, .frequency = 10U}, // Bolt EUV - {0xBE, 0, 8, .frequency = 10U}}}, // Escalade - {.msg = {{0x1C4, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, - {.msg = {{0xC9, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, - }; - - static const CanMsg GM_CAM_TX_MSGS[] = {{0x180, 0, 4}, // pt bus - {0x1E1, 2, 7}, {0x184, 2, 8}}; // camera bus - - gm_hw = GET_FLAG(param, GM_PARAM_HW_CAM) ? GM_CAM : GM_ASCM; - - if (gm_hw == GM_ASCM) { - gm_long_limits = &GM_ASCM_LONG_LIMITS; - } else if (gm_hw == GM_CAM) { - gm_long_limits = &GM_CAM_LONG_LIMITS; - } else { - } - -#ifdef ALLOW_DEBUG - const uint16_t GM_PARAM_HW_CAM_LONG = 2; - gm_cam_long = GET_FLAG(param, GM_PARAM_HW_CAM_LONG); -#endif - gm_pcm_cruise = (gm_hw == GM_CAM) && !gm_cam_long; - - safety_config ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_ASCM_TX_MSGS); - if (gm_hw == GM_CAM) { - // FIXME: cppcheck thinks that gm_cam_long is always false. This is not true - // if ALLOW_DEBUG is defined but cppcheck is run without ALLOW_DEBUG - // cppcheck-suppress knownConditionTrueFalse - ret = gm_cam_long ? BUILD_SAFETY_CFG(gm_rx_checks, GM_CAM_LONG_TX_MSGS) : BUILD_SAFETY_CFG(gm_rx_checks, GM_CAM_TX_MSGS); - } - return ret; -} - -const safety_hooks gm_hooks = { - .init = gm_init, - .rx = gm_rx_hook, - .tx = gm_tx_hook, - .fwd = gm_fwd_hook, -}; diff --git a/board/safety/safety_honda.h b/board/safety/safety_honda.h deleted file mode 100644 index 60ccea1e16..0000000000 --- a/board/safety/safety_honda.h +++ /dev/null @@ -1,461 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -// All common address checks except SCM_BUTTONS which isn't on one Nidec safety configuration -#define HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(pt_bus) \ - {.msg = {{0x1A6, (pt_bus), 8, .check_checksum = true, .max_counter = 3U, .frequency = 25U}, /* SCM_BUTTONS */ \ - {0x296, (pt_bus), 4, .check_checksum = true, .max_counter = 3U, .frequency = 25U}, { 0 }}}, \ - {.msg = {{0x158, (pt_bus), 8, .check_checksum = true, .max_counter = 3U, .frequency = 100U}, { 0 }, { 0 }}}, /* ENGINE_DATA */ \ - {.msg = {{0x17C, (pt_bus), 8, .check_checksum = true, .max_counter = 3U, .frequency = 100U}, { 0 }, { 0 }}}, /* POWERTRAIN_DATA */ \ - -#define HONDA_COMMON_RX_CHECKS(pt_bus) \ - HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(pt_bus) \ - {.msg = {{0x326, (pt_bus), 8, .check_checksum = true, .max_counter = 3U, .frequency = 10U}, { 0 }, { 0 }}}, /* SCM_FEEDBACK */ \ - -// Alternate brake message is used on some Honda Bosch, and Honda Bosch radarless (where PT bus is 0) -#define HONDA_ALT_BRAKE_ADDR_CHECK(pt_bus) \ - {.msg = {{0x1BE, (pt_bus), 3, .check_checksum = true, .max_counter = 3U, .frequency = 50U}, { 0 }, { 0 }}}, /* BRAKE_MODULE */ \ - - -// Nidec and bosch radarless has the powertrain bus on bus 0 -static RxCheck honda_common_rx_checks[] = { - HONDA_COMMON_RX_CHECKS(0) -}; - -enum { - HONDA_BTN_NONE = 0, - HONDA_BTN_MAIN = 1, - HONDA_BTN_CANCEL = 2, - HONDA_BTN_SET = 3, - HONDA_BTN_RESUME = 4, -}; - -static int honda_brake = 0; -static bool honda_brake_switch_prev = false; -static bool honda_alt_brake_msg = false; -static bool honda_fwd_brake = false; -static bool honda_bosch_long = false; -static bool honda_bosch_radarless = false; -typedef enum {HONDA_NIDEC, HONDA_BOSCH} HondaHw; -static HondaHw honda_hw = HONDA_NIDEC; - - -static int honda_get_pt_bus(void) { - return ((honda_hw == HONDA_BOSCH) && !honda_bosch_radarless) ? 1 : 0; -} - -static uint32_t honda_get_checksum(const CANPacket_t *to_push) { - int checksum_byte = GET_LEN(to_push) - 1U; - return (uint8_t)(GET_BYTE(to_push, checksum_byte)) & 0xFU; -} - -static uint32_t honda_compute_checksum(const CANPacket_t *to_push) { - int len = GET_LEN(to_push); - uint8_t checksum = 0U; - unsigned int addr = GET_ADDR(to_push); - while (addr > 0U) { - checksum += (uint8_t)(addr & 0xFU); addr >>= 4; - } - for (int j = 0; j < len; j++) { - uint8_t byte = GET_BYTE(to_push, j); - checksum += (uint8_t)(byte & 0xFU) + (byte >> 4U); - if (j == (len - 1)) { - checksum -= (byte & 0xFU); // remove checksum in message - } - } - return (uint8_t)((8U - checksum) & 0xFU); -} - -static uint8_t honda_get_counter(const CANPacket_t *to_push) { - int counter_byte = GET_LEN(to_push) - 1U; - return (GET_BYTE(to_push, counter_byte) >> 4U) & 0x3U; -} - -static void honda_rx_hook(const CANPacket_t *to_push) { - const bool pcm_cruise = ((honda_hw == HONDA_BOSCH) && !honda_bosch_long) || (honda_hw == HONDA_NIDEC); - int pt_bus = honda_get_pt_bus(); - - int addr = GET_ADDR(to_push); - int bus = GET_BUS(to_push); - - // sample speed - if (addr == 0x158) { - // first 2 bytes - vehicle_moving = GET_BYTE(to_push, 0) | GET_BYTE(to_push, 1); - } - - // check ACC main state - // 0x326 for all Bosch and some Nidec, 0x1A6 for some Nidec - if ((addr == 0x326) || (addr == 0x1A6)) { - acc_main_on = GET_BIT(to_push, ((addr == 0x326) ? 28U : 47U)); - if (!acc_main_on) { - controls_allowed = false; - } - } - - // enter controls when PCM enters cruise state - if (pcm_cruise && (addr == 0x17C)) { - const bool cruise_engaged = GET_BIT(to_push, 38U); - // engage on rising edge - if (cruise_engaged && !cruise_engaged_prev) { - controls_allowed = true; - } - - // Since some Nidec cars can brake down to 0 after the PCM disengages, - // we don't disengage when the PCM does. - if (!cruise_engaged && (honda_hw != HONDA_NIDEC)) { - controls_allowed = false; - } - cruise_engaged_prev = cruise_engaged; - } - - // state machine to enter and exit controls for button enabling - // 0x1A6 for the ILX, 0x296 for the Civic Touring - if (((addr == 0x1A6) || (addr == 0x296)) && (bus == pt_bus)) { - int button = (GET_BYTE(to_push, 0) & 0xE0U) >> 5; - - // enter controls on the falling edge of set or resume - bool set = (button != HONDA_BTN_SET) && (cruise_button_prev == HONDA_BTN_SET); - bool res = (button != HONDA_BTN_RESUME) && (cruise_button_prev == HONDA_BTN_RESUME); - if (acc_main_on && !pcm_cruise && (set || res)) { - controls_allowed = true; - } - - // exit controls once main or cancel are pressed - if ((button == HONDA_BTN_MAIN) || (button == HONDA_BTN_CANCEL)) { - controls_allowed = false; - } - cruise_button_prev = button; - } - - // 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 - // accord, crv: 0x1BE - if (honda_alt_brake_msg) { - if (addr == 0x1BE) { - brake_pressed = GET_BIT(to_push, 4U); - } - } else { - if (addr == 0x17C) { - // also if brake switch is 1 for two CAN frames, as brake pressed is delayed - const bool brake_switch = GET_BIT(to_push, 32U); - brake_pressed = (GET_BIT(to_push, 53U)) || (brake_switch && honda_brake_switch_prev); - honda_brake_switch_prev = brake_switch; - } - } - - if (addr == 0x17C) { - gas_pressed = GET_BYTE(to_push, 0) != 0U; - } - - // disable stock Honda AEB in alternative experience - if (!(alternative_experience & ALT_EXP_DISABLE_STOCK_AEB)) { - if ((bus == 2) && (addr == 0x1FA)) { - bool honda_stock_aeb = GET_BIT(to_push, 29U); - int honda_stock_brake = (GET_BYTE(to_push, 0) << 2) | (GET_BYTE(to_push, 1) >> 6); - - // 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 - } - } - } - - int bus_rdr_car = (honda_hw == HONDA_BOSCH) ? 0 : 2; // radar bus, car side - bool stock_ecu_detected = false; - - // If steering controls messages are received on the destination bus, it's an indication - // that the relay might be malfunctioning - if ((addr == 0xE4) || (addr == 0x194)) { - if (((honda_hw != HONDA_NIDEC) && (bus == bus_rdr_car)) || ((honda_hw == HONDA_NIDEC) && (bus == 0))) { - stock_ecu_detected = true; - } - } - // If Honda Bosch longitudinal mode is selected we need to ensure the radar is turned off - // Verify this by ensuring ACC_CONTROL (0x1DF) is not received on the PT bus - if (honda_bosch_long && !honda_bosch_radarless && (bus == pt_bus) && (addr == 0x1DF)) { - stock_ecu_detected = true; - } - - generic_rx_checks(stock_ecu_detected); - -} - -static bool honda_tx_hook(const CANPacket_t *to_send) { - - const LongitudinalLimits HONDA_BOSCH_LONG_LIMITS = { - .max_accel = 200, // accel is used for brakes - .min_accel = -350, - - .max_gas = 2000, - .inactive_gas = -30000, - }; - - const LongitudinalLimits HONDA_NIDEC_LONG_LIMITS = { - .max_gas = 198, // 0xc6 - .max_brake = 255, - - .inactive_speed = 0, - }; - - bool tx = true; - int addr = GET_ADDR(to_send); - int bus = GET_BUS(to_send); - - int bus_pt = honda_get_pt_bus(); - int bus_buttons = (honda_bosch_radarless) ? 2 : bus_pt; // the camera controls ACC on radarless Bosch cars - - // ACC_HUD: safety check (nidec w/o pedal) - if ((addr == 0x30C) && (bus == bus_pt)) { - int pcm_speed = (GET_BYTE(to_send, 0) << 8) | GET_BYTE(to_send, 1); - int pcm_gas = GET_BYTE(to_send, 2); - - bool violation = false; - violation |= longitudinal_speed_checks(pcm_speed, HONDA_NIDEC_LONG_LIMITS); - violation |= longitudinal_gas_checks(pcm_gas, HONDA_NIDEC_LONG_LIMITS); - if (violation) { - tx = false; - } - } - - // BRAKE: safety check (nidec) - if ((addr == 0x1FA) && (bus == bus_pt)) { - honda_brake = (GET_BYTE(to_send, 0) << 2) + ((GET_BYTE(to_send, 1) >> 6) & 0x3U); - if (longitudinal_brake_checks(honda_brake, HONDA_NIDEC_LONG_LIMITS)) { - tx = false; - } - if (honda_fwd_brake) { - tx = false; - } - } - - // BRAKE/GAS: safety check (bosch) - if ((addr == 0x1DF) && (bus == bus_pt)) { - int accel = (GET_BYTE(to_send, 3) << 3) | ((GET_BYTE(to_send, 4) >> 5) & 0x7U); - accel = to_signed(accel, 11); - - int gas = (GET_BYTE(to_send, 0) << 8) | GET_BYTE(to_send, 1); - gas = to_signed(gas, 16); - - bool violation = false; - violation |= longitudinal_accel_checks(accel, HONDA_BOSCH_LONG_LIMITS); - violation |= longitudinal_gas_checks(gas, HONDA_BOSCH_LONG_LIMITS); - if (violation) { - tx = false; - } - } - - // ACCEL: safety check (radarless) - if ((addr == 0x1C8) && (bus == bus_pt)) { - int accel = (GET_BYTE(to_send, 0) << 4) | (GET_BYTE(to_send, 1) >> 4); - accel = to_signed(accel, 12); - - bool violation = false; - violation |= longitudinal_accel_checks(accel, HONDA_BOSCH_LONG_LIMITS); - if (violation) { - tx = false; - } - } - - // STEER: safety check - if ((addr == 0xE4) || (addr == 0x194)) { - if (!controls_allowed) { - bool steer_applied = GET_BYTE(to_send, 0) | GET_BYTE(to_send, 1); - if (steer_applied) { - tx = false; - } - } - } - - // Bosch supplemental control check - if (addr == 0xE5) { - if ((GET_BYTES(to_send, 0, 4) != 0x10800004U) || ((GET_BYTES(to_send, 4, 4) & 0x00FFFFFFU) != 0x0U)) { - tx = false; - } - } - - // 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 - if ((addr == 0x296) && !controls_allowed && (bus == bus_buttons)) { - if (((GET_BYTE(to_send, 0) >> 5) & 0x7U) != 2U) { - tx = false; - } - } - - // Only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address - if (addr == 0x18DAB0F1) { - if ((GET_BYTES(to_send, 0, 4) != 0x00803E02U) || (GET_BYTES(to_send, 4, 4) != 0x0U)) { - tx = false; - } - } - - return tx; -} - -static safety_config honda_nidec_init(uint16_t param) { - static CanMsg HONDA_N_TX_MSGS[] = {{0xE4, 0, 5}, {0x194, 0, 4}, {0x1FA, 0, 8}, {0x30C, 0, 8}, {0x33D, 0, 5}}; - - const uint16_t HONDA_PARAM_NIDEC_ALT = 4; - - honda_hw = HONDA_NIDEC; - honda_brake = 0; - honda_brake_switch_prev = false; - honda_fwd_brake = false; - honda_alt_brake_msg = false; - honda_bosch_long = false; - honda_bosch_radarless = false; - - safety_config ret; - - bool enable_nidec_alt = GET_FLAG(param, HONDA_PARAM_NIDEC_ALT); - - if (enable_nidec_alt) { - // For Nidecs with main on signal on an alternate msg (missing 0x326) - static RxCheck honda_nidec_alt_rx_checks[] = { - HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(0) - }; - - SET_RX_CHECKS(honda_nidec_alt_rx_checks, ret); - } else { - SET_RX_CHECKS(honda_common_rx_checks, ret); - } - - SET_TX_MSGS(HONDA_N_TX_MSGS, ret); - - return ret; -} - -static safety_config honda_bosch_init(uint16_t param) { - static CanMsg HONDA_BOSCH_TX_MSGS[] = {{0xE4, 0, 5}, {0xE5, 0, 8}, {0x296, 1, 4}, {0x33D, 0, 5}, {0x33DA, 0, 5}, {0x33DB, 0, 8}}; // Bosch - static CanMsg HONDA_BOSCH_LONG_TX_MSGS[] = {{0xE4, 1, 5}, {0x1DF, 1, 8}, {0x1EF, 1, 8}, {0x1FA, 1, 8}, {0x30C, 1, 8}, {0x33D, 1, 5}, {0x33DA, 1, 5}, {0x33DB, 1, 8}, {0x39F, 1, 8}, {0x18DAB0F1, 1, 8}}; // Bosch w/ gas and brakes - static CanMsg HONDA_RADARLESS_TX_MSGS[] = {{0xE4, 0, 5}, {0x296, 2, 4}, {0x33D, 0, 8}}; // Bosch radarless - static CanMsg HONDA_RADARLESS_LONG_TX_MSGS[] = {{0xE4, 0, 5}, {0x33D, 0, 8}, {0x1C8, 0, 8}, {0x30C, 0, 8}}; // Bosch radarless w/ gas and brakes - - const uint16_t HONDA_PARAM_ALT_BRAKE = 1; - const uint16_t HONDA_PARAM_RADARLESS = 8; - - static RxCheck honda_common_alt_brake_rx_checks[] = { - HONDA_COMMON_RX_CHECKS(0) - HONDA_ALT_BRAKE_ADDR_CHECK(0) - }; - - static RxCheck honda_bosch_alt_brake_rx_checks[] = { - HONDA_COMMON_RX_CHECKS(1) - HONDA_ALT_BRAKE_ADDR_CHECK(1) - }; - - // Bosch has pt on bus 1, verified 0x1A6 does not exist - static RxCheck honda_bosch_rx_checks[] = { - HONDA_COMMON_RX_CHECKS(1) - }; - - honda_hw = HONDA_BOSCH; - honda_brake_switch_prev = false; - honda_bosch_radarless = GET_FLAG(param, HONDA_PARAM_RADARLESS); - // Checking for alternate brake override from safety parameter - honda_alt_brake_msg = GET_FLAG(param, HONDA_PARAM_ALT_BRAKE); - - // radar disabled so allow gas/brakes -#ifdef ALLOW_DEBUG - const uint16_t HONDA_PARAM_BOSCH_LONG = 2; - honda_bosch_long = GET_FLAG(param, HONDA_PARAM_BOSCH_LONG); -#endif - - safety_config ret; - if (honda_bosch_radarless && honda_alt_brake_msg) { - SET_RX_CHECKS(honda_common_alt_brake_rx_checks, ret); - } else if (honda_bosch_radarless) { - SET_RX_CHECKS(honda_common_rx_checks, ret); - } else if (honda_alt_brake_msg) { - SET_RX_CHECKS(honda_bosch_alt_brake_rx_checks, ret); - } else { - SET_RX_CHECKS(honda_bosch_rx_checks, ret); - } - - if (honda_bosch_radarless) { - if (honda_bosch_long) { - SET_TX_MSGS(HONDA_RADARLESS_LONG_TX_MSGS, ret); - } else { - SET_TX_MSGS(HONDA_RADARLESS_TX_MSGS, ret); - } - } else { - if (honda_bosch_long) { - SET_TX_MSGS(HONDA_BOSCH_LONG_TX_MSGS, ret); - } else { - SET_TX_MSGS(HONDA_BOSCH_TX_MSGS, ret); - } - } - return ret; -} - -static int honda_nidec_fwd_hook(int bus_num, int addr) { - // 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 - int bus_fwd = -1; - - if (bus_num == 0) { - bus_fwd = 2; - } - - if (bus_num == 2) { - // block stock lkas messages and stock acc messages (if OP is doing ACC) - 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 || (is_brake_msg && !honda_fwd_brake); - if (!block_fwd) { - bus_fwd = 0; - } - } - - return bus_fwd; -} - -static int honda_bosch_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - - if (bus_num == 0) { - bus_fwd = 2; - } - if (bus_num == 2) { - bool is_lkas_msg = (addr == 0xE4) || (addr == 0xE5) || (addr == 0x33D) || (addr == 0x33DA) || (addr == 0x33DB); - bool is_acc_msg = ((addr == 0x1C8) || (addr == 0x30C)) && honda_bosch_radarless && honda_bosch_long; - bool block_msg = is_lkas_msg || is_acc_msg; - if (!block_msg) { - bus_fwd = 0; - } - } - - return bus_fwd; -} - -const safety_hooks honda_nidec_hooks = { - .init = honda_nidec_init, - .rx = honda_rx_hook, - .tx = honda_tx_hook, - .fwd = honda_nidec_fwd_hook, - .get_counter = honda_get_counter, - .get_checksum = honda_get_checksum, - .compute_checksum = honda_compute_checksum, -}; - -const safety_hooks honda_bosch_hooks = { - .init = honda_bosch_init, - .rx = honda_rx_hook, - .tx = honda_tx_hook, - .fwd = honda_bosch_fwd_hook, - .get_counter = honda_get_counter, - .get_checksum = honda_get_checksum, - .compute_checksum = honda_compute_checksum, -}; diff --git a/board/safety/safety_hyundai.h b/board/safety/safety_hyundai.h deleted file mode 100644 index cf73afee62..0000000000 --- a/board/safety/safety_hyundai.h +++ /dev/null @@ -1,356 +0,0 @@ -#pragma once - -#include "safety_declarations.h" -#include "safety_hyundai_common.h" - -#define HYUNDAI_LIMITS(steer, rate_up, rate_down) { \ - .max_steer = (steer), \ - .max_rate_up = (rate_up), \ - .max_rate_down = (rate_down), \ - .max_rt_delta = 112, \ - .max_rt_interval = 250000, \ - .driver_torque_allowance = 50, \ - .driver_torque_factor = 2, \ - .type = TorqueDriverLimited, \ - /* the EPS faults when the steering angle is above a certain threshold for too long. to prevent this, */ \ - /* we allow setting CF_Lkas_ActToi bit to 0 while maintaining the requested torque value for two consecutive frames */ \ - .min_valid_request_frames = 89, \ - .max_invalid_request_frames = 2, \ - .min_valid_request_rt_interval = 810000, /* 810ms; a ~10% buffer on cutting every 90 frames */ \ - .has_steer_req_tolerance = true, \ -} - -extern const LongitudinalLimits HYUNDAI_LONG_LIMITS; -const LongitudinalLimits HYUNDAI_LONG_LIMITS = { - .max_accel = 200, // 1/100 m/s2 - .min_accel = -350, // 1/100 m/s2 -}; - -static const CanMsg HYUNDAI_TX_MSGS[] = { - {0x340, 0, 8}, // LKAS11 Bus 0 - {0x4F1, 0, 4}, // CLU11 Bus 0 - {0x485, 0, 4}, // LFAHDA_MFC Bus 0 -}; - -#define HYUNDAI_COMMON_RX_CHECKS(legacy) \ - {.msg = {{0x260, 0, 8, .check_checksum = true, .max_counter = 3U, .frequency = 100U}, \ - {0x371, 0, 8, .frequency = 100U}, { 0 }}}, \ - {.msg = {{0x386, 0, 8, .check_checksum = !(legacy), .max_counter = (legacy) ? 0U : 15U, .frequency = 100U}, { 0 }, { 0 }}}, \ - {.msg = {{0x394, 0, 8, .check_checksum = !(legacy), .max_counter = (legacy) ? 0U : 7U, .frequency = 100U}, { 0 }, { 0 }}}, \ - -#define HYUNDAI_SCC12_ADDR_CHECK(scc_bus) \ - {.msg = {{0x421, (scc_bus), 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, \ - -static bool hyundai_legacy = false; - -static uint8_t hyundai_get_counter(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - - uint8_t cnt = 0; - if (addr == 0x260) { - cnt = (GET_BYTE(to_push, 7) >> 4) & 0x3U; - } else if (addr == 0x386) { - cnt = ((GET_BYTE(to_push, 3) >> 6) << 2) | (GET_BYTE(to_push, 1) >> 6); - } else if (addr == 0x394) { - cnt = (GET_BYTE(to_push, 1) >> 5) & 0x7U; - } else if (addr == 0x421) { - cnt = GET_BYTE(to_push, 7) & 0xFU; - } else if (addr == 0x4F1) { - cnt = (GET_BYTE(to_push, 3) >> 4) & 0xFU; - } else { - } - return cnt; -} - -static uint32_t hyundai_get_checksum(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - - uint8_t chksum = 0; - if (addr == 0x260) { - chksum = GET_BYTE(to_push, 7) & 0xFU; - } else if (addr == 0x386) { - chksum = ((GET_BYTE(to_push, 7) >> 6) << 2) | (GET_BYTE(to_push, 5) >> 6); - } else if (addr == 0x394) { - chksum = GET_BYTE(to_push, 6) & 0xFU; - } else if (addr == 0x421) { - chksum = GET_BYTE(to_push, 7) >> 4; - } else { - } - return chksum; -} - -static uint32_t hyundai_compute_checksum(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - - uint8_t chksum = 0; - if (addr == 0x386) { - // count the bits - for (int i = 0; i < 8; i++) { - uint8_t b = GET_BYTE(to_push, i); - for (int j = 0; j < 8; j++) { - uint8_t bit = 0; - // exclude checksum and counter - if (((i != 1) || (j < 6)) && ((i != 3) || (j < 6)) && ((i != 5) || (j < 6)) && ((i != 7) || (j < 6))) { - bit = (b >> (uint8_t)j) & 1U; - } - chksum += bit; - } - } - chksum = (chksum ^ 9U) & 15U; - } else { - // sum of nibbles - for (int i = 0; i < 8; i++) { - if ((addr == 0x394) && (i == 7)) { - continue; // exclude - } - uint8_t b = GET_BYTE(to_push, i); - if (((addr == 0x260) && (i == 7)) || ((addr == 0x394) && (i == 6)) || ((addr == 0x421) && (i == 7))) { - b &= (addr == 0x421) ? 0x0FU : 0xF0U; // remove checksum - } - chksum += (b % 16U) + (b / 16U); - } - chksum = (16U - (chksum % 16U)) % 16U; - } - - return chksum; -} - -static void hyundai_rx_hook(const CANPacket_t *to_push) { - int bus = GET_BUS(to_push); - int addr = GET_ADDR(to_push); - - // SCC12 is on bus 2 for camera-based SCC cars, bus 0 on all others - if ((addr == 0x421) && (((bus == 0) && !hyundai_camera_scc) || ((bus == 2) && hyundai_camera_scc))) { - // 2 bits: 13-14 - int cruise_engaged = (GET_BYTES(to_push, 0, 4) >> 13) & 0x3U; - hyundai_common_cruise_state_check(cruise_engaged); - } - - if (bus == 0) { - if (addr == 0x251) { - int torque_driver_new = (GET_BYTES(to_push, 0, 2) & 0x7ffU) - 1024U; - // update array of samples - update_sample(&torque_driver, torque_driver_new); - } - - // ACC steering wheel buttons - if (addr == 0x4F1) { - int cruise_button = GET_BYTE(to_push, 0) & 0x7U; - bool main_button = GET_BIT(to_push, 3U); - hyundai_common_cruise_buttons_check(cruise_button, main_button); - } - - // gas press, different for EV, hybrid, and ICE models - if ((addr == 0x371) && hyundai_ev_gas_signal) { - gas_pressed = (((GET_BYTE(to_push, 4) & 0x7FU) << 1) | GET_BYTE(to_push, 3) >> 7) != 0U; - } else if ((addr == 0x371) && hyundai_hybrid_gas_signal) { - gas_pressed = GET_BYTE(to_push, 7) != 0U; - } else if ((addr == 0x260) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) { - gas_pressed = (GET_BYTE(to_push, 7) >> 6) != 0U; - } else { - } - - // sample wheel speed, averaging opposite corners - if (addr == 0x386) { - uint32_t front_left_speed = GET_BYTES(to_push, 0, 2) & 0x3FFFU; - uint32_t rear_right_speed = GET_BYTES(to_push, 6, 2) & 0x3FFFU; - vehicle_moving = (front_left_speed > HYUNDAI_STANDSTILL_THRSLD) || (rear_right_speed > HYUNDAI_STANDSTILL_THRSLD); - } - - if (addr == 0x394) { - brake_pressed = ((GET_BYTE(to_push, 5) >> 5U) & 0x3U) == 0x2U; - } - - bool stock_ecu_detected = (addr == 0x340); - - // If openpilot is controlling longitudinal we need to ensure the radar is turned off - // Enforce by checking we don't see SCC12 - if (hyundai_longitudinal && (addr == 0x421)) { - stock_ecu_detected = true; - } - generic_rx_checks(stock_ecu_detected); - } -} - -static bool hyundai_tx_hook(const CANPacket_t *to_send) { - const SteeringLimits HYUNDAI_STEERING_LIMITS = HYUNDAI_LIMITS(384, 3, 7); - const SteeringLimits HYUNDAI_STEERING_LIMITS_ALT = HYUNDAI_LIMITS(270, 2, 3); - - bool tx = true; - int addr = GET_ADDR(to_send); - - // FCA11: Block any potential actuation - if (addr == 0x38D) { - int CR_VSM_DecCmd = GET_BYTE(to_send, 1); - bool FCA_CmdAct = GET_BIT(to_send, 20U); - bool CF_VSM_DecCmdAct = GET_BIT(to_send, 31U); - - if ((CR_VSM_DecCmd != 0) || FCA_CmdAct || CF_VSM_DecCmdAct) { - tx = false; - } - } - - // ACCEL: safety check - if (addr == 0x421) { - int desired_accel_raw = (((GET_BYTE(to_send, 4) & 0x7U) << 8) | GET_BYTE(to_send, 3)) - 1023U; - int desired_accel_val = ((GET_BYTE(to_send, 5) << 3) | (GET_BYTE(to_send, 4) >> 5)) - 1023U; - - int aeb_decel_cmd = GET_BYTE(to_send, 2); - bool aeb_req = GET_BIT(to_send, 54U); - - bool violation = false; - - violation |= longitudinal_accel_checks(desired_accel_raw, HYUNDAI_LONG_LIMITS); - violation |= longitudinal_accel_checks(desired_accel_val, HYUNDAI_LONG_LIMITS); - violation |= (aeb_decel_cmd != 0); - violation |= aeb_req; - - if (violation) { - tx = false; - } - } - - // LKA STEER: safety check - if (addr == 0x340) { - int desired_torque = ((GET_BYTES(to_send, 0, 4) >> 16) & 0x7ffU) - 1024U; - bool steer_req = GET_BIT(to_send, 27U); - - const SteeringLimits limits = hyundai_alt_limits ? HYUNDAI_STEERING_LIMITS_ALT : HYUNDAI_STEERING_LIMITS; - if (steer_torque_cmd_checks(desired_torque, steer_req, limits)) { - tx = false; - } - } - - // UDS: Only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address - if (addr == 0x7D0) { - if ((GET_BYTES(to_send, 0, 4) != 0x00803E02U) || (GET_BYTES(to_send, 4, 4) != 0x0U)) { - tx = false; - } - } - - // BUTTONS: used for resume spamming and cruise cancellation - if ((addr == 0x4F1) && !hyundai_longitudinal) { - int button = GET_BYTE(to_send, 0) & 0x7U; - - bool allowed_resume = (button == 1) && controls_allowed; - bool allowed_cancel = (button == 4) && cruise_engaged_prev; - if (!(allowed_resume || allowed_cancel)) { - tx = false; - } - } - - return tx; -} - -static int hyundai_fwd_hook(int bus_num, int addr) { - - int bus_fwd = -1; - - // forward cam to ccan and viceversa, except lkas cmd - if (bus_num == 0) { - bus_fwd = 2; - } - - if (bus_num == 2) { - // Stock LKAS11 messages - bool is_lkas_11 = (addr == 0x340); - // LFA and HDA cluster icons - bool is_lfahda_mfc = (addr == 0x485); - - bool block_msg = is_lkas_11 || is_lfahda_mfc; - if (!block_msg) { - bus_fwd = 0; - } - } - - return bus_fwd; -} - -static safety_config hyundai_init(uint16_t param) { - static const CanMsg HYUNDAI_LONG_TX_MSGS[] = { - {0x340, 0, 8}, // LKAS11 Bus 0 - {0x4F1, 0, 4}, // CLU11 Bus 0 - {0x485, 0, 4}, // LFAHDA_MFC Bus 0 - {0x420, 0, 8}, // SCC11 Bus 0 - {0x421, 0, 8}, // SCC12 Bus 0 - {0x50A, 0, 8}, // SCC13 Bus 0 - {0x389, 0, 8}, // SCC14 Bus 0 - {0x4A2, 0, 2}, // FRT_RADAR11 Bus 0 - {0x38D, 0, 8}, // FCA11 Bus 0 - {0x483, 0, 8}, // FCA12 Bus 0 - {0x7D0, 0, 8}, // radar UDS TX addr Bus 0 (for radar disable) - }; - - static const CanMsg HYUNDAI_CAMERA_SCC_TX_MSGS[] = { - {0x340, 0, 8}, // LKAS11 Bus 0 - {0x4F1, 2, 4}, // CLU11 Bus 2 - {0x485, 0, 4}, // LFAHDA_MFC Bus 0 - }; - - hyundai_common_init(param); - hyundai_legacy = false; - - if (hyundai_camera_scc) { - hyundai_longitudinal = false; - } - - safety_config ret; - if (hyundai_longitudinal) { - static RxCheck hyundai_long_rx_checks[] = { - HYUNDAI_COMMON_RX_CHECKS(false) - // Use CLU11 (buttons) to manage controls allowed instead of SCC cruise state - {.msg = {{0x4F1, 0, 4, .check_checksum = false, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - }; - - ret = BUILD_SAFETY_CFG(hyundai_long_rx_checks, HYUNDAI_LONG_TX_MSGS); - } else if (hyundai_camera_scc) { - static RxCheck hyundai_cam_scc_rx_checks[] = { - HYUNDAI_COMMON_RX_CHECKS(false) - HYUNDAI_SCC12_ADDR_CHECK(2) - }; - - ret = BUILD_SAFETY_CFG(hyundai_cam_scc_rx_checks, HYUNDAI_CAMERA_SCC_TX_MSGS); - } else { - static RxCheck hyundai_rx_checks[] = { - HYUNDAI_COMMON_RX_CHECKS(false) - HYUNDAI_SCC12_ADDR_CHECK(0) - }; - - ret = BUILD_SAFETY_CFG(hyundai_rx_checks, HYUNDAI_TX_MSGS); - } - return ret; -} - -static safety_config hyundai_legacy_init(uint16_t param) { - // older hyundai models have less checks due to missing counters and checksums - static RxCheck hyundai_legacy_rx_checks[] = { - HYUNDAI_COMMON_RX_CHECKS(true) - HYUNDAI_SCC12_ADDR_CHECK(0) - }; - - hyundai_common_init(param); - hyundai_legacy = true; - hyundai_longitudinal = false; - hyundai_camera_scc = false; - return BUILD_SAFETY_CFG(hyundai_legacy_rx_checks, HYUNDAI_TX_MSGS); -} - -const safety_hooks hyundai_hooks = { - .init = hyundai_init, - .rx = hyundai_rx_hook, - .tx = hyundai_tx_hook, - .fwd = hyundai_fwd_hook, - .get_counter = hyundai_get_counter, - .get_checksum = hyundai_get_checksum, - .compute_checksum = hyundai_compute_checksum, -}; - -const safety_hooks hyundai_legacy_hooks = { - .init = hyundai_legacy_init, - .rx = hyundai_rx_hook, - .tx = hyundai_tx_hook, - .fwd = hyundai_fwd_hook, - .get_counter = hyundai_get_counter, - .get_checksum = hyundai_get_checksum, - .compute_checksum = hyundai_compute_checksum, -}; diff --git a/board/safety/safety_hyundai_canfd.h b/board/safety/safety_hyundai_canfd.h deleted file mode 100644 index b42889bb0e..0000000000 --- a/board/safety/safety_hyundai_canfd.h +++ /dev/null @@ -1,363 +0,0 @@ -#pragma once - -#include "safety_declarations.h" -#include "safety_hyundai_common.h" - -// *** Addresses checked in rx hook *** -// EV, ICE, HYBRID: ACCELERATOR (0x35), ACCELERATOR_BRAKE_ALT (0x100), ACCELERATOR_ALT (0x105) -#define HYUNDAI_CANFD_COMMON_RX_CHECKS(pt_bus) \ - {.msg = {{0x35, (pt_bus), 32, .check_checksum = true, .max_counter = 0xffU, .frequency = 100U}, \ - {0x100, (pt_bus), 32, .check_checksum = true, .max_counter = 0xffU, .frequency = 100U}, \ - {0x105, (pt_bus), 32, .check_checksum = true, .max_counter = 0xffU, .frequency = 100U}}}, \ - {.msg = {{0x175, (pt_bus), 24, .check_checksum = true, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \ - {.msg = {{0xa0, (pt_bus), 24, .check_checksum = true, .max_counter = 0xffU, .frequency = 100U}, { 0 }, { 0 }}}, \ - {.msg = {{0xea, (pt_bus), 24, .check_checksum = true, .max_counter = 0xffU, .frequency = 100U}, { 0 }, { 0 }}}, \ - -#define HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(pt_bus) \ - {.msg = {{0x1cf, (pt_bus), 8, .check_checksum = false, .max_counter = 0xfU, .frequency = 50U}, { 0 }, { 0 }}}, \ - -#define HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(pt_bus) \ - {.msg = {{0x1aa, (pt_bus), 16, .check_checksum = false, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \ - -// SCC_CONTROL (from ADAS unit or camera) -#define HYUNDAI_CANFD_SCC_ADDR_CHECK(scc_bus) \ - {.msg = {{0x1a0, (scc_bus), 32, .check_checksum = true, .max_counter = 0xffU, .frequency = 50U}, { 0 }, { 0 }}}, \ - -static bool hyundai_canfd_alt_buttons = false; -static bool hyundai_canfd_hda2_alt_steering = false; - -static int hyundai_canfd_hda2_get_lkas_addr(void) { - return hyundai_canfd_hda2_alt_steering ? 0x110 : 0x50; -} - -static uint8_t hyundai_canfd_get_counter(const CANPacket_t *to_push) { - uint8_t ret = 0; - if (GET_LEN(to_push) == 8U) { - ret = GET_BYTE(to_push, 1) >> 4; - } else { - ret = GET_BYTE(to_push, 2); - } - return ret; -} - -static uint32_t hyundai_canfd_get_checksum(const CANPacket_t *to_push) { - uint32_t chksum = GET_BYTE(to_push, 0) | (GET_BYTE(to_push, 1) << 8); - return chksum; -} - -static void hyundai_canfd_rx_hook(const CANPacket_t *to_push) { - int bus = GET_BUS(to_push); - int addr = GET_ADDR(to_push); - - const int pt_bus = hyundai_canfd_hda2 ? 1 : 0; - const int scc_bus = hyundai_camera_scc ? 2 : pt_bus; - - if (bus == pt_bus) { - // driver torque - if (addr == 0xea) { - int torque_driver_new = ((GET_BYTE(to_push, 11) & 0x1fU) << 8U) | GET_BYTE(to_push, 10); - torque_driver_new -= 4095; - update_sample(&torque_driver, torque_driver_new); - } - - // cruise buttons - const int button_addr = hyundai_canfd_alt_buttons ? 0x1aa : 0x1cf; - if (addr == button_addr) { - bool main_button = false; - int cruise_button = 0; - if (addr == 0x1cf) { - cruise_button = GET_BYTE(to_push, 2) & 0x7U; - main_button = GET_BIT(to_push, 19U); - } else { - cruise_button = (GET_BYTE(to_push, 4) >> 4) & 0x7U; - main_button = GET_BIT(to_push, 34U); - } - hyundai_common_cruise_buttons_check(cruise_button, main_button); - } - - // gas press, different for EV, hybrid, and ICE models - if ((addr == 0x35) && hyundai_ev_gas_signal) { - gas_pressed = GET_BYTE(to_push, 5) != 0U; - } else if ((addr == 0x105) && hyundai_hybrid_gas_signal) { - gas_pressed = GET_BIT(to_push, 103U) || (GET_BYTE(to_push, 13) != 0U) || GET_BIT(to_push, 112U); - } else if ((addr == 0x100) && !hyundai_ev_gas_signal && !hyundai_hybrid_gas_signal) { - gas_pressed = GET_BIT(to_push, 176U); - } else { - } - - // brake press - if (addr == 0x175) { - brake_pressed = GET_BIT(to_push, 81U); - } - - // vehicle moving - if (addr == 0xa0) { - uint32_t front_left_speed = GET_BYTES(to_push, 8, 2); - uint32_t rear_right_speed = GET_BYTES(to_push, 14, 2); - vehicle_moving = (front_left_speed > HYUNDAI_STANDSTILL_THRSLD) || (rear_right_speed > HYUNDAI_STANDSTILL_THRSLD); - } - } - - if (bus == scc_bus) { - // cruise state - if ((addr == 0x1a0) && !hyundai_longitudinal) { - // 1=enabled, 2=driver override - int cruise_status = ((GET_BYTE(to_push, 8) >> 4) & 0x7U); - bool cruise_engaged = (cruise_status == 1) || (cruise_status == 2); - hyundai_common_cruise_state_check(cruise_engaged); - } - } - - const int steer_addr = hyundai_canfd_hda2 ? hyundai_canfd_hda2_get_lkas_addr() : 0x12a; - bool stock_ecu_detected = (addr == steer_addr) && (bus == 0); - if (hyundai_longitudinal) { - // on HDA2, ensure ADRV ECU is still knocked out - // on others, ensure accel msg is blocked from camera - const int stock_scc_bus = hyundai_canfd_hda2 ? 1 : 0; - stock_ecu_detected = stock_ecu_detected || ((addr == 0x1a0) && (bus == stock_scc_bus)); - } - generic_rx_checks(stock_ecu_detected); - -} - -static bool hyundai_canfd_tx_hook(const CANPacket_t *to_send) { - const SteeringLimits HYUNDAI_CANFD_STEERING_LIMITS = { - .max_steer = 270, - .max_rt_delta = 112, - .max_rt_interval = 250000, - .max_rate_up = 2, - .max_rate_down = 3, - .driver_torque_allowance = 250, - .driver_torque_factor = 2, - .type = TorqueDriverLimited, - - // the EPS faults when the steering angle is above a certain threshold for too long. to prevent this, - // we allow setting torque actuation bit to 0 while maintaining the requested torque value for two consecutive frames - .min_valid_request_frames = 89, - .max_invalid_request_frames = 2, - .min_valid_request_rt_interval = 810000, // 810ms; a ~10% buffer on cutting every 90 frames - .has_steer_req_tolerance = true, - }; - - bool tx = true; - int addr = GET_ADDR(to_send); - - // steering - const int steer_addr = (hyundai_canfd_hda2 && !hyundai_longitudinal) ? hyundai_canfd_hda2_get_lkas_addr() : 0x12a; - if (addr == steer_addr) { - int desired_torque = (((GET_BYTE(to_send, 6) & 0xFU) << 7U) | (GET_BYTE(to_send, 5) >> 1U)) - 1024U; - bool steer_req = GET_BIT(to_send, 52U); - - if (steer_torque_cmd_checks(desired_torque, steer_req, HYUNDAI_CANFD_STEERING_LIMITS)) { - tx = false; - } - } - - // cruise buttons check - if (addr == 0x1cf) { - int button = GET_BYTE(to_send, 2) & 0x7U; - bool is_cancel = (button == HYUNDAI_BTN_CANCEL); - bool is_resume = (button == HYUNDAI_BTN_RESUME); - - bool allowed = (is_cancel && cruise_engaged_prev) || (is_resume && controls_allowed); - if (!allowed) { - tx = false; - } - } - - // UDS: only tester present ("\x02\x3E\x80\x00\x00\x00\x00\x00") allowed on diagnostics address - if ((addr == 0x730) && hyundai_canfd_hda2) { - if ((GET_BYTES(to_send, 0, 4) != 0x00803E02U) || (GET_BYTES(to_send, 4, 4) != 0x0U)) { - tx = false; - } - } - - // ACCEL: safety check - if (addr == 0x1a0) { - int desired_accel_raw = (((GET_BYTE(to_send, 17) & 0x7U) << 8) | GET_BYTE(to_send, 16)) - 1023U; - int desired_accel_val = ((GET_BYTE(to_send, 18) << 4) | (GET_BYTE(to_send, 17) >> 4)) - 1023U; - - bool violation = false; - - if (hyundai_longitudinal) { - violation |= longitudinal_accel_checks(desired_accel_raw, HYUNDAI_LONG_LIMITS); - violation |= longitudinal_accel_checks(desired_accel_val, HYUNDAI_LONG_LIMITS); - } else { - // only used to cancel on here - if ((desired_accel_raw != 0) || (desired_accel_val != 0)) { - violation = true; - } - } - - if (violation) { - tx = false; - } - } - - return tx; -} - -static int hyundai_canfd_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - - if (bus_num == 0) { - bus_fwd = 2; - } - if (bus_num == 2) { - // LKAS for HDA2, LFA for HDA1 - int hda2_lfa_block_addr = hyundai_canfd_hda2_alt_steering ? 0x362 : 0x2a4; - bool is_lkas_msg = ((addr == hyundai_canfd_hda2_get_lkas_addr()) || (addr == hda2_lfa_block_addr)) && hyundai_canfd_hda2; - bool is_lfa_msg = ((addr == 0x12a) && !hyundai_canfd_hda2); - - // HUD icons - bool is_lfahda_msg = ((addr == 0x1e0) && !hyundai_canfd_hda2); - - // CRUISE_INFO for non-HDA2, we send our own longitudinal commands - bool is_scc_msg = ((addr == 0x1a0) && hyundai_longitudinal && !hyundai_canfd_hda2); - - bool block_msg = is_lkas_msg || is_lfa_msg || is_lfahda_msg || is_scc_msg; - if (!block_msg) { - bus_fwd = 0; - } - } - - return bus_fwd; -} - -static safety_config hyundai_canfd_init(uint16_t param) { - const int HYUNDAI_PARAM_CANFD_HDA2_ALT_STEERING = 128; - const int HYUNDAI_PARAM_CANFD_ALT_BUTTONS = 32; - - static const CanMsg HYUNDAI_CANFD_HDA2_TX_MSGS[] = { - {0x50, 0, 16}, // LKAS - {0x1CF, 1, 8}, // CRUISE_BUTTON - {0x2A4, 0, 24}, // CAM_0x2A4 - }; - - static const CanMsg HYUNDAI_CANFD_HDA2_ALT_STEERING_TX_MSGS[] = { - {0x110, 0, 32}, // LKAS_ALT - {0x1CF, 1, 8}, // CRUISE_BUTTON - {0x362, 0, 32}, // CAM_0x362 - }; - - static const CanMsg HYUNDAI_CANFD_HDA2_LONG_TX_MSGS[] = { - {0x50, 0, 16}, // LKAS - {0x1CF, 1, 8}, // CRUISE_BUTTON - {0x2A4, 0, 24}, // CAM_0x2A4 - {0x51, 0, 32}, // ADRV_0x51 - {0x730, 1, 8}, // tester present for ADAS ECU disable - {0x12A, 1, 16}, // LFA - {0x160, 1, 16}, // ADRV_0x160 - {0x1E0, 1, 16}, // LFAHDA_CLUSTER - {0x1A0, 1, 32}, // CRUISE_INFO - {0x1EA, 1, 32}, // ADRV_0x1ea - {0x200, 1, 8}, // ADRV_0x200 - {0x345, 1, 8}, // ADRV_0x345 - {0x1DA, 1, 32}, // ADRV_0x1da - }; - - static const CanMsg HYUNDAI_CANFD_HDA1_TX_MSGS[] = { - {0x12A, 0, 16}, // LFA - {0x1A0, 0, 32}, // CRUISE_INFO - {0x1CF, 2, 8}, // CRUISE_BUTTON - {0x1E0, 0, 16}, // LFAHDA_CLUSTER - }; - - - hyundai_common_init(param); - - gen_crc_lookup_table_16(0x1021, hyundai_canfd_crc_lut); - hyundai_canfd_alt_buttons = GET_FLAG(param, HYUNDAI_PARAM_CANFD_ALT_BUTTONS); - hyundai_canfd_hda2_alt_steering = GET_FLAG(param, HYUNDAI_PARAM_CANFD_HDA2_ALT_STEERING); - - // no long for radar-SCC HDA1 yet - if (!hyundai_canfd_hda2 && !hyundai_camera_scc) { - hyundai_longitudinal = false; - } - - safety_config ret; - if (hyundai_longitudinal) { - if (hyundai_canfd_hda2) { - static RxCheck hyundai_canfd_hda2_long_rx_checks[] = { - HYUNDAI_CANFD_COMMON_RX_CHECKS(1) - HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(1) - }; - - ret = BUILD_SAFETY_CFG(hyundai_canfd_hda2_long_rx_checks, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS); - } else { - static RxCheck hyundai_canfd_long_alt_buttons_rx_checks[] = { - HYUNDAI_CANFD_COMMON_RX_CHECKS(0) - HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(0) - }; - - // Longitudinal checks for HDA1 - static RxCheck hyundai_canfd_long_rx_checks[] = { - HYUNDAI_CANFD_COMMON_RX_CHECKS(0) - HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0) - }; - - ret = hyundai_canfd_alt_buttons ? BUILD_SAFETY_CFG(hyundai_canfd_long_alt_buttons_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS) : \ - BUILD_SAFETY_CFG(hyundai_canfd_long_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS); - } - } else { - if (hyundai_canfd_hda2) { - // *** HDA2 checks *** - // E-CAN is on bus 1, ADAS unit sends SCC messages on HDA2. - // Does not use the alt buttons message - static RxCheck hyundai_canfd_hda2_rx_checks[] = { - HYUNDAI_CANFD_COMMON_RX_CHECKS(1) - HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(1) - HYUNDAI_CANFD_SCC_ADDR_CHECK(1) - }; - - ret = hyundai_canfd_hda2_alt_steering ? BUILD_SAFETY_CFG(hyundai_canfd_hda2_rx_checks, HYUNDAI_CANFD_HDA2_ALT_STEERING_TX_MSGS) : \ - BUILD_SAFETY_CFG(hyundai_canfd_hda2_rx_checks, HYUNDAI_CANFD_HDA2_TX_MSGS); - } else if (!hyundai_camera_scc) { - static RxCheck hyundai_canfd_radar_scc_alt_buttons_rx_checks[] = { - HYUNDAI_CANFD_COMMON_RX_CHECKS(0) - HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(0) - HYUNDAI_CANFD_SCC_ADDR_CHECK(0) - }; - - // Radar sends SCC messages on these cars instead of camera - static RxCheck hyundai_canfd_radar_scc_rx_checks[] = { - HYUNDAI_CANFD_COMMON_RX_CHECKS(0) - HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0) - HYUNDAI_CANFD_SCC_ADDR_CHECK(0) - }; - - ret = hyundai_canfd_alt_buttons ? BUILD_SAFETY_CFG(hyundai_canfd_radar_scc_alt_buttons_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS) : \ - BUILD_SAFETY_CFG(hyundai_canfd_radar_scc_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS); - } else { - // *** Non-HDA2 checks *** - static RxCheck hyundai_canfd_alt_buttons_rx_checks[] = { - HYUNDAI_CANFD_COMMON_RX_CHECKS(0) - HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(0) - HYUNDAI_CANFD_SCC_ADDR_CHECK(2) - }; - - // Camera sends SCC messages on HDA1. - // Both button messages exist on some platforms, so we ensure we track the correct one using flag - static RxCheck hyundai_canfd_rx_checks[] = { - HYUNDAI_CANFD_COMMON_RX_CHECKS(0) - HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0) - HYUNDAI_CANFD_SCC_ADDR_CHECK(2) - }; - - ret = hyundai_canfd_alt_buttons ? BUILD_SAFETY_CFG(hyundai_canfd_alt_buttons_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS) : \ - BUILD_SAFETY_CFG(hyundai_canfd_rx_checks, HYUNDAI_CANFD_HDA1_TX_MSGS); - } - } - - return ret; -} - -const safety_hooks hyundai_canfd_hooks = { - .init = hyundai_canfd_init, - .rx = hyundai_canfd_rx_hook, - .tx = hyundai_canfd_tx_hook, - .fwd = hyundai_canfd_fwd_hook, - .get_counter = hyundai_canfd_get_counter, - .get_checksum = hyundai_canfd_get_checksum, - .compute_checksum = hyundai_common_canfd_compute_checksum, -}; diff --git a/board/safety/safety_hyundai_common.h b/board/safety/safety_hyundai_common.h deleted file mode 100644 index d83b396401..0000000000 --- a/board/safety/safety_hyundai_common.h +++ /dev/null @@ -1,128 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -extern uint16_t hyundai_canfd_crc_lut[256]; -uint16_t hyundai_canfd_crc_lut[256]; - -static const uint8_t HYUNDAI_PREV_BUTTON_SAMPLES = 8; // roughly 160 ms - // -extern const uint32_t HYUNDAI_STANDSTILL_THRSLD; -const uint32_t HYUNDAI_STANDSTILL_THRSLD = 12; // 0.375 kph - -enum { - HYUNDAI_BTN_NONE = 0, - HYUNDAI_BTN_RESUME = 1, - HYUNDAI_BTN_SET = 2, - HYUNDAI_BTN_CANCEL = 4, -}; - -// common state -extern bool hyundai_ev_gas_signal; -bool hyundai_ev_gas_signal = false; - -extern bool hyundai_hybrid_gas_signal; -bool hyundai_hybrid_gas_signal = false; - -extern bool hyundai_longitudinal; -bool hyundai_longitudinal = false; - -extern bool hyundai_camera_scc; -bool hyundai_camera_scc = false; - -extern bool hyundai_canfd_hda2; -bool hyundai_canfd_hda2 = false; - -extern bool hyundai_alt_limits; -bool hyundai_alt_limits = false; - -static uint8_t hyundai_last_button_interaction; // button messages since the user pressed an enable button - -void hyundai_common_init(uint16_t param) { - const int HYUNDAI_PARAM_EV_GAS = 1; - const int HYUNDAI_PARAM_HYBRID_GAS = 2; - const int HYUNDAI_PARAM_CAMERA_SCC = 8; - const int HYUNDAI_PARAM_CANFD_HDA2 = 16; - const int HYUNDAI_PARAM_ALT_LIMITS = 64; // TODO: shift this down with the rest of the common flags - - hyundai_ev_gas_signal = GET_FLAG(param, HYUNDAI_PARAM_EV_GAS); - hyundai_hybrid_gas_signal = !hyundai_ev_gas_signal && GET_FLAG(param, HYUNDAI_PARAM_HYBRID_GAS); - hyundai_camera_scc = GET_FLAG(param, HYUNDAI_PARAM_CAMERA_SCC); - hyundai_canfd_hda2 = GET_FLAG(param, HYUNDAI_PARAM_CANFD_HDA2); - hyundai_alt_limits = GET_FLAG(param, HYUNDAI_PARAM_ALT_LIMITS); - - hyundai_last_button_interaction = HYUNDAI_PREV_BUTTON_SAMPLES; - -#ifdef ALLOW_DEBUG - const int HYUNDAI_PARAM_LONGITUDINAL = 4; - hyundai_longitudinal = GET_FLAG(param, HYUNDAI_PARAM_LONGITUDINAL); -#else - hyundai_longitudinal = false; -#endif -} - -void hyundai_common_cruise_state_check(const bool cruise_engaged) { - // some newer HKG models can re-enable after spamming cancel button, - // so keep track of user button presses to deny engagement if no interaction - - // enter controls on rising edge of ACC and recent user button press, exit controls when ACC off - if (!hyundai_longitudinal) { - if (cruise_engaged && !cruise_engaged_prev && (hyundai_last_button_interaction < HYUNDAI_PREV_BUTTON_SAMPLES)) { - controls_allowed = true; - } - - if (!cruise_engaged) { - controls_allowed = false; - } - cruise_engaged_prev = cruise_engaged; - } -} - -void hyundai_common_cruise_buttons_check(const int cruise_button, const bool main_button) { - if ((cruise_button == HYUNDAI_BTN_RESUME) || (cruise_button == HYUNDAI_BTN_SET) || (cruise_button == HYUNDAI_BTN_CANCEL) || main_button) { - hyundai_last_button_interaction = 0U; - } else { - hyundai_last_button_interaction = MIN(hyundai_last_button_interaction + 1U, HYUNDAI_PREV_BUTTON_SAMPLES); - } - - if (hyundai_longitudinal) { - // enter controls on falling edge of resume or set - bool set = (cruise_button != HYUNDAI_BTN_SET) && (cruise_button_prev == HYUNDAI_BTN_SET); - bool res = (cruise_button != HYUNDAI_BTN_RESUME) && (cruise_button_prev == HYUNDAI_BTN_RESUME); - if (set || res) { - controls_allowed = true; - } - - // exit controls on cancel press - if (cruise_button == HYUNDAI_BTN_CANCEL) { - controls_allowed = false; - } - - cruise_button_prev = cruise_button; - } -} - -uint32_t hyundai_common_canfd_compute_checksum(const CANPacket_t *to_push) { - int len = GET_LEN(to_push); - uint32_t address = GET_ADDR(to_push); - - uint16_t crc = 0; - - for (int i = 2; i < len; i++) { - crc = (crc << 8U) ^ hyundai_canfd_crc_lut[(crc >> 8U) ^ GET_BYTE(to_push, i)]; - } - - // Add address to crc - crc = (crc << 8U) ^ hyundai_canfd_crc_lut[(crc >> 8U) ^ ((address >> 0U) & 0xFFU)]; - crc = (crc << 8U) ^ hyundai_canfd_crc_lut[(crc >> 8U) ^ ((address >> 8U) & 0xFFU)]; - - if (len == 24) { - crc ^= 0x819dU; - } else if (len == 32) { - crc ^= 0x9f5bU; - } else { - - } - - return crc; -} diff --git a/board/safety/safety_mazda.h b/board/safety/safety_mazda.h deleted file mode 100644 index ed87451f77..0000000000 --- a/board/safety/safety_mazda.h +++ /dev/null @@ -1,131 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -// CAN msgs we care about -#define MAZDA_LKAS 0x243 -#define MAZDA_LKAS_HUD 0x440 -#define MAZDA_CRZ_CTRL 0x21c -#define MAZDA_CRZ_BTNS 0x09d -#define MAZDA_STEER_TORQUE 0x240 -#define MAZDA_ENGINE_DATA 0x202 -#define MAZDA_PEDALS 0x165 - -// CAN bus numbers -#define MAZDA_MAIN 0 -#define MAZDA_CAM 2 - -// track msgs coming from OP so that we know what CAM msgs to drop and what to forward -static void mazda_rx_hook(const CANPacket_t *to_push) { - if ((int)GET_BUS(to_push) == MAZDA_MAIN) { - int addr = GET_ADDR(to_push); - - if (addr == MAZDA_ENGINE_DATA) { - // sample speed: scale by 0.01 to get kph - int speed = (GET_BYTE(to_push, 2) << 8) | GET_BYTE(to_push, 3); - vehicle_moving = speed > 10; // moving when speed > 0.1 kph - } - - if (addr == MAZDA_STEER_TORQUE) { - int torque_driver_new = GET_BYTE(to_push, 0) - 127U; - // update array of samples - update_sample(&torque_driver, torque_driver_new); - } - - // enter controls on rising edge of ACC, exit controls on ACC off - if (addr == MAZDA_CRZ_CTRL) { - bool cruise_engaged = GET_BYTE(to_push, 0) & 0x8U; - pcm_cruise_check(cruise_engaged); - } - - if (addr == MAZDA_ENGINE_DATA) { - gas_pressed = (GET_BYTE(to_push, 4) || (GET_BYTE(to_push, 5) & 0xF0U)); - } - - if (addr == MAZDA_PEDALS) { - brake_pressed = (GET_BYTE(to_push, 0) & 0x10U); - } - - generic_rx_checks((addr == MAZDA_LKAS)); - } -} - -static bool mazda_tx_hook(const CANPacket_t *to_send) { - const SteeringLimits MAZDA_STEERING_LIMITS = { - .max_steer = 800, - .max_rate_up = 10, - .max_rate_down = 25, - .max_rt_delta = 300, - .max_rt_interval = 250000, - .driver_torque_factor = 1, - .driver_torque_allowance = 15, - .type = TorqueDriverLimited, - }; - - bool tx = true; - int bus = GET_BUS(to_send); - // Check if msg is sent on the main BUS - if (bus == MAZDA_MAIN) { - int addr = GET_ADDR(to_send); - - // steer cmd checks - if (addr == MAZDA_LKAS) { - int desired_torque = (((GET_BYTE(to_send, 0) & 0x0FU) << 8) | GET_BYTE(to_send, 1)) - 2048U; - - if (steer_torque_cmd_checks(desired_torque, -1, MAZDA_STEERING_LIMITS)) { - tx = false; - } - } - - // cruise buttons check - if (addr == MAZDA_CRZ_BTNS) { - // allow resume spamming while controls allowed, but - // only allow cancel while contrls not allowed - bool cancel_cmd = (GET_BYTE(to_send, 0) == 0x1U); - if (!controls_allowed && !cancel_cmd) { - tx = false; - } - } - } - - return tx; -} - -static int mazda_fwd_hook(int bus, int addr) { - int bus_fwd = -1; - - if (bus == MAZDA_MAIN) { - bus_fwd = MAZDA_CAM; - } else if (bus == MAZDA_CAM) { - bool block = (addr == MAZDA_LKAS) || (addr == MAZDA_LKAS_HUD); - if (!block) { - bus_fwd = MAZDA_MAIN; - } - } else { - // don't fwd - } - - return bus_fwd; -} - -static safety_config mazda_init(uint16_t param) { - static const CanMsg MAZDA_TX_MSGS[] = {{MAZDA_LKAS, 0, 8}, {MAZDA_CRZ_BTNS, 0, 8}, {MAZDA_LKAS_HUD, 0, 8}}; - - static RxCheck mazda_rx_checks[] = { - {.msg = {{MAZDA_CRZ_CTRL, 0, 8, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{MAZDA_CRZ_BTNS, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, - {.msg = {{MAZDA_STEER_TORQUE, 0, 8, .frequency = 83U}, { 0 }, { 0 }}}, - {.msg = {{MAZDA_ENGINE_DATA, 0, 8, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{MAZDA_PEDALS, 0, 8, .frequency = 50U}, { 0 }, { 0 }}}, - }; - - UNUSED(param); - return BUILD_SAFETY_CFG(mazda_rx_checks, MAZDA_TX_MSGS); -} - -const safety_hooks mazda_hooks = { - .init = mazda_init, - .rx = mazda_rx_hook, - .tx = mazda_tx_hook, - .fwd = mazda_fwd_hook, -}; diff --git a/board/safety/safety_nissan.h b/board/safety/safety_nissan.h deleted file mode 100644 index fd47e09448..0000000000 --- a/board/safety/safety_nissan.h +++ /dev/null @@ -1,163 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -static bool nissan_alt_eps = false; - -static void nissan_rx_hook(const CANPacket_t *to_push) { - int bus = GET_BUS(to_push); - int addr = GET_ADDR(to_push); - - if (bus == (nissan_alt_eps ? 1 : 0)) { - if (addr == 0x2) { - // Current steering angle - // Factor -0.1, little endian - int angle_meas_new = (GET_BYTES(to_push, 0, 4) & 0xFFFFU); - // Multiply by -10 to match scale of LKAS angle - angle_meas_new = to_signed(angle_meas_new, 16) * -10; - - // update array of samples - update_sample(&angle_meas, angle_meas_new); - } - - if (addr == 0x285) { - // Get current speed and standstill - uint16_t right_rear = (GET_BYTE(to_push, 0) << 8) | (GET_BYTE(to_push, 1)); - uint16_t left_rear = (GET_BYTE(to_push, 2) << 8) | (GET_BYTE(to_push, 3)); - vehicle_moving = (right_rear | left_rear) != 0U; - UPDATE_VEHICLE_SPEED((right_rear + left_rear) / 2.0 * 0.005 / 3.6); - } - - // X-Trail 0x15c, Leaf 0x239 - if ((addr == 0x15c) || (addr == 0x239)) { - if (addr == 0x15c){ - gas_pressed = ((GET_BYTE(to_push, 5) << 2) | ((GET_BYTE(to_push, 6) >> 6) & 0x3U)) > 3U; - } else { - gas_pressed = GET_BYTE(to_push, 0) > 3U; - } - } - - // X-trail 0x454, Leaf 0x239 - if ((addr == 0x454) || (addr == 0x239)) { - if (addr == 0x454){ - brake_pressed = (GET_BYTE(to_push, 2) & 0x80U) != 0U; - } else { - brake_pressed = ((GET_BYTE(to_push, 4) >> 5) & 1U) != 0U; - } - } - } - - // Handle cruise enabled - if ((addr == 0x30f) && (bus == (nissan_alt_eps ? 1 : 2))) { - bool cruise_engaged = (GET_BYTE(to_push, 0) >> 3) & 1U; - pcm_cruise_check(cruise_engaged); - } - - generic_rx_checks((addr == 0x169) && (bus == 0)); -} - - -static bool nissan_tx_hook(const CANPacket_t *to_send) { - const SteeringLimits NISSAN_STEERING_LIMITS = { - .angle_deg_to_can = 100, - .angle_rate_up_lookup = { - {0., 5., 15.}, - {5., .8, .15} - }, - .angle_rate_down_lookup = { - {0., 5., 15.}, - {5., 3.5, .4} - }, - }; - - bool tx = true; - int addr = GET_ADDR(to_send); - bool violation = false; - - // steer cmd checks - if (addr == 0x169) { - int desired_angle = ((GET_BYTE(to_send, 0) << 10) | (GET_BYTE(to_send, 1) << 2) | ((GET_BYTE(to_send, 2) >> 6) & 0x3U)); - bool lka_active = (GET_BYTE(to_send, 6) >> 4) & 1U; - - // Factor is -0.01, offset is 1310. Flip to correct sign, but keep units in CAN scale - desired_angle = -desired_angle + (1310.0f * NISSAN_STEERING_LIMITS.angle_deg_to_can); - - if (steer_angle_cmd_checks(desired_angle, lka_active, NISSAN_STEERING_LIMITS)) { - violation = true; - } - } - - // acc button check, only allow cancel button to be sent - if (addr == 0x20b) { - // Violation of any button other than cancel is pressed - violation |= ((GET_BYTE(to_send, 1) & 0x3dU) > 0U); - } - - if (violation) { - tx = false; - } - - return tx; -} - - -static int nissan_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - - if (bus_num == 0) { - bool block_msg = (addr == 0x280); // CANCEL_MSG - if (!block_msg) { - bus_fwd = 2; // ADAS - } - } - - if (bus_num == 2) { - // 0x169 is LKAS, 0x2b1 LKAS_HUD, 0x4cc LKAS_HUD_INFO_MSG - bool block_msg = ((addr == 0x169) || (addr == 0x2b1) || (addr == 0x4cc)); - if (!block_msg) { - bus_fwd = 0; // V-CAN - } - } - - return bus_fwd; -} - -static safety_config nissan_init(uint16_t param) { - static const CanMsg NISSAN_TX_MSGS[] = { - {0x169, 0, 8}, // LKAS - {0x2b1, 0, 8}, // PROPILOT_HUD - {0x4cc, 0, 8}, // PROPILOT_HUD_INFO_MSG - {0x20b, 2, 6}, // CRUISE_THROTTLE (X-Trail) - {0x20b, 1, 6}, // CRUISE_THROTTLE (Altima) - {0x280, 2, 8} // CANCEL_MSG (Leaf) - }; - - // Signals duplicated below due to the fact that these messages can come in on either CAN bus, depending on car model. - static RxCheck nissan_rx_checks[] = { - {.msg = {{0x2, 0, 5, .frequency = 100U}, - {0x2, 1, 5, .frequency = 100U}, { 0 }}}, // STEER_ANGLE_SENSOR - {.msg = {{0x285, 0, 8, .frequency = 50U}, - {0x285, 1, 8, .frequency = 50U}, { 0 }}}, // WHEEL_SPEEDS_REAR - {.msg = {{0x30f, 2, 3, .frequency = 10U}, - {0x30f, 1, 3, .frequency = 10U}, { 0 }}}, // CRUISE_STATE - {.msg = {{0x15c, 0, 8, .frequency = 50U}, - {0x15c, 1, 8, .frequency = 50U}, - {0x239, 0, 8, .frequency = 50U}}}, // GAS_PEDAL - {.msg = {{0x454, 0, 8, .frequency = 10U}, - {0x454, 1, 8, .frequency = 10U}, - {0x1cc, 0, 4, .frequency = 100U}}}, // DOORS_LIGHTS / BRAKE - }; - - // EPS Location. false = V-CAN, true = C-CAN - const int NISSAN_PARAM_ALT_EPS_BUS = 1; - - nissan_alt_eps = GET_FLAG(param, NISSAN_PARAM_ALT_EPS_BUS); - return BUILD_SAFETY_CFG(nissan_rx_checks, NISSAN_TX_MSGS); -} - -const safety_hooks nissan_hooks = { - .init = nissan_init, - .rx = nissan_rx_hook, - .tx = nissan_tx_hook, - .fwd = nissan_fwd_hook, -}; diff --git a/board/safety/safety_subaru.h b/board/safety/safety_subaru.h deleted file mode 100644 index 290150657e..0000000000 --- a/board/safety/safety_subaru.h +++ /dev/null @@ -1,293 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -#define SUBARU_STEERING_LIMITS_GENERATOR(steer_max, rate_up, rate_down) \ - { \ - .max_steer = (steer_max), \ - .max_rt_delta = 940, \ - .max_rt_interval = 250000, \ - .max_rate_up = (rate_up), \ - .max_rate_down = (rate_down), \ - .driver_torque_factor = 50, \ - .driver_torque_allowance = 60, \ - .type = TorqueDriverLimited, \ - /* the EPS will temporary fault if the steering rate is too high, so we cut the \ - the steering torque every 7 frames for 1 frame if the steering rate is high */ \ - .min_valid_request_frames = 7, \ - .max_invalid_request_frames = 1, \ - .min_valid_request_rt_interval = 144000, /* 10% tolerance */ \ - .has_steer_req_tolerance = true, \ - } - -#define MSG_SUBARU_Brake_Status 0x13c -#define MSG_SUBARU_CruiseControl 0x240 -#define MSG_SUBARU_Throttle 0x40 -#define MSG_SUBARU_Steering_Torque 0x119 -#define MSG_SUBARU_Wheel_Speeds 0x13a - -#define MSG_SUBARU_ES_LKAS 0x122 -#define MSG_SUBARU_ES_Brake 0x220 -#define MSG_SUBARU_ES_Distance 0x221 -#define MSG_SUBARU_ES_Status 0x222 -#define MSG_SUBARU_ES_DashStatus 0x321 -#define MSG_SUBARU_ES_LKAS_State 0x322 -#define MSG_SUBARU_ES_Infotainment 0x323 - -#define MSG_SUBARU_ES_UDS_Request 0x787 - -#define MSG_SUBARU_ES_HighBeamAssist 0x121 -#define MSG_SUBARU_ES_STATIC_1 0x22a -#define MSG_SUBARU_ES_STATIC_2 0x325 - -#define SUBARU_MAIN_BUS 0 -#define SUBARU_ALT_BUS 1 -#define SUBARU_CAM_BUS 2 - -#define SUBARU_COMMON_TX_MSGS(alt_bus, lkas_msg) \ - {lkas_msg, SUBARU_MAIN_BUS, 8}, \ - {MSG_SUBARU_ES_Distance, alt_bus, 8}, \ - {MSG_SUBARU_ES_DashStatus, SUBARU_MAIN_BUS, 8}, \ - {MSG_SUBARU_ES_LKAS_State, SUBARU_MAIN_BUS, 8}, \ - {MSG_SUBARU_ES_Infotainment, SUBARU_MAIN_BUS, 8}, \ - -#define SUBARU_COMMON_LONG_TX_MSGS(alt_bus) \ - {MSG_SUBARU_ES_Brake, alt_bus, 8}, \ - {MSG_SUBARU_ES_Status, alt_bus, 8}, \ - -#define SUBARU_GEN2_LONG_ADDITIONAL_TX_MSGS() \ - {MSG_SUBARU_ES_UDS_Request, SUBARU_CAM_BUS, 8}, \ - {MSG_SUBARU_ES_HighBeamAssist, SUBARU_MAIN_BUS, 8}, \ - {MSG_SUBARU_ES_STATIC_1, SUBARU_MAIN_BUS, 8}, \ - {MSG_SUBARU_ES_STATIC_2, SUBARU_MAIN_BUS, 8}, \ - -#define SUBARU_COMMON_RX_CHECKS(alt_bus) \ - {.msg = {{MSG_SUBARU_Throttle, SUBARU_MAIN_BUS, 8, .check_checksum = true, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}}, \ - {.msg = {{MSG_SUBARU_Steering_Torque, SUBARU_MAIN_BUS, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, \ - {.msg = {{MSG_SUBARU_Wheel_Speeds, alt_bus, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, \ - {.msg = {{MSG_SUBARU_Brake_Status, alt_bus, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, \ - {.msg = {{MSG_SUBARU_CruiseControl, alt_bus, 8, .check_checksum = true, .max_counter = 15U, .frequency = 20U}, { 0 }, { 0 }}}, \ - -static bool subaru_gen2 = false; -static bool subaru_longitudinal = false; - -static uint32_t subaru_get_checksum(const CANPacket_t *to_push) { - return (uint8_t)GET_BYTE(to_push, 0); -} - -static uint8_t subaru_get_counter(const CANPacket_t *to_push) { - return (uint8_t)(GET_BYTE(to_push, 1) & 0xFU); -} - -static uint32_t subaru_compute_checksum(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - int len = GET_LEN(to_push); - uint8_t checksum = (uint8_t)(addr) + (uint8_t)((unsigned int)(addr) >> 8U); - for (int i = 1; i < len; i++) { - checksum += (uint8_t)GET_BYTE(to_push, i); - } - return checksum; -} - -static void subaru_rx_hook(const CANPacket_t *to_push) { - const int bus = GET_BUS(to_push); - const int alt_main_bus = subaru_gen2 ? SUBARU_ALT_BUS : SUBARU_MAIN_BUS; - - int addr = GET_ADDR(to_push); - if ((addr == MSG_SUBARU_Steering_Torque) && (bus == SUBARU_MAIN_BUS)) { - int torque_driver_new; - torque_driver_new = ((GET_BYTES(to_push, 0, 4) >> 16) & 0x7FFU); - torque_driver_new = -1 * to_signed(torque_driver_new, 11); - update_sample(&torque_driver, torque_driver_new); - - int angle_meas_new = (GET_BYTES(to_push, 4, 2) & 0xFFFFU); - // convert Steering_Torque -> Steering_Angle to centidegrees, to match the ES_LKAS_ANGLE angle request units - angle_meas_new = ROUND(to_signed(angle_meas_new, 16) * -2.17); - update_sample(&angle_meas, angle_meas_new); - } - - // enter controls on rising edge of ACC, exit controls on ACC off - if ((addr == MSG_SUBARU_CruiseControl) && (bus == alt_main_bus)) { - bool cruise_engaged = GET_BIT(to_push, 41U); - pcm_cruise_check(cruise_engaged); - } - - // update vehicle moving with any non-zero wheel speed - if ((addr == MSG_SUBARU_Wheel_Speeds) && (bus == alt_main_bus)) { - uint32_t fr = (GET_BYTES(to_push, 1, 3) >> 4) & 0x1FFFU; - uint32_t rr = (GET_BYTES(to_push, 3, 3) >> 1) & 0x1FFFU; - uint32_t rl = (GET_BYTES(to_push, 4, 3) >> 6) & 0x1FFFU; - uint32_t fl = (GET_BYTES(to_push, 6, 2) >> 3) & 0x1FFFU; - - vehicle_moving = (fr > 0U) || (rr > 0U) || (rl > 0U) || (fl > 0U); - - UPDATE_VEHICLE_SPEED((fr + rr + rl + fl) / 4U * 0.057); - } - - if ((addr == MSG_SUBARU_Brake_Status) && (bus == alt_main_bus)) { - brake_pressed = GET_BIT(to_push, 62U); - } - - if ((addr == MSG_SUBARU_Throttle) && (bus == SUBARU_MAIN_BUS)) { - gas_pressed = GET_BYTE(to_push, 4) != 0U; - } - - generic_rx_checks((addr == MSG_SUBARU_ES_LKAS) && (bus == SUBARU_MAIN_BUS)); -} - -static bool subaru_tx_hook(const CANPacket_t *to_send) { - const SteeringLimits SUBARU_STEERING_LIMITS = SUBARU_STEERING_LIMITS_GENERATOR(2047, 50, 70); - const SteeringLimits SUBARU_GEN2_STEERING_LIMITS = SUBARU_STEERING_LIMITS_GENERATOR(1000, 40, 40); - - const LongitudinalLimits SUBARU_LONG_LIMITS = { - .min_gas = 808, // appears to be engine braking - .max_gas = 3400, // approx 2 m/s^2 when maxing cruise_rpm and cruise_throttle - .inactive_gas = 1818, // this is zero acceleration - .max_brake = 600, // approx -3.5 m/s^2 - - .min_transmission_rpm = 0, - .max_transmission_rpm = 3600, - }; - - bool tx = true; - int addr = GET_ADDR(to_send); - bool violation = false; - - // steer cmd checks - if (addr == MSG_SUBARU_ES_LKAS) { - int desired_torque = ((GET_BYTES(to_send, 0, 4) >> 16) & 0x1FFFU); - desired_torque = -1 * to_signed(desired_torque, 13); - - bool steer_req = GET_BIT(to_send, 29U); - - const SteeringLimits limits = subaru_gen2 ? SUBARU_GEN2_STEERING_LIMITS : SUBARU_STEERING_LIMITS; - violation |= steer_torque_cmd_checks(desired_torque, steer_req, limits); - } - - // check es_brake brake_pressure limits - if (addr == MSG_SUBARU_ES_Brake) { - int es_brake_pressure = GET_BYTES(to_send, 2, 2); - violation |= longitudinal_brake_checks(es_brake_pressure, SUBARU_LONG_LIMITS); - } - - // check es_distance cruise_throttle limits - if (addr == MSG_SUBARU_ES_Distance) { - int cruise_throttle = (GET_BYTES(to_send, 2, 2) & 0x1FFFU); - bool cruise_cancel = GET_BIT(to_send, 56U); - - if (subaru_longitudinal) { - violation |= longitudinal_gas_checks(cruise_throttle, SUBARU_LONG_LIMITS); - } else { - // If openpilot is not controlling long, only allow ES_Distance for cruise cancel requests, - // (when Cruise_Cancel is true, and Cruise_Throttle is inactive) - violation |= (cruise_throttle != SUBARU_LONG_LIMITS.inactive_gas); - violation |= (!cruise_cancel); - } - } - - // check es_status transmission_rpm limits - if (addr == MSG_SUBARU_ES_Status) { - int transmission_rpm = (GET_BYTES(to_send, 2, 2) & 0x1FFFU); - violation |= longitudinal_transmission_rpm_checks(transmission_rpm, SUBARU_LONG_LIMITS); - } - - if (addr == MSG_SUBARU_ES_UDS_Request) { - // tester present ('\x02\x3E\x80\x00\x00\x00\x00\x00') is allowed for gen2 longitudinal to keep eyesight disabled - bool is_tester_present = (GET_BYTES(to_send, 0, 4) == 0x00803E02U) && (GET_BYTES(to_send, 4, 4) == 0x0U); - - // reading ES button data by identifier (b'\x03\x22\x11\x30\x00\x00\x00\x00') is also allowed (DID 0x1130) - bool is_button_rdbi = (GET_BYTES(to_send, 0, 4) == 0x30112203U) && (GET_BYTES(to_send, 4, 4) == 0x0U); - - violation |= !(is_tester_present || is_button_rdbi); - } - - if (violation){ - tx = false; - } - return tx; -} - -static int subaru_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - - if (bus_num == SUBARU_MAIN_BUS) { - bus_fwd = SUBARU_CAM_BUS; // to the eyesight camera - } - - if (bus_num == SUBARU_CAM_BUS) { - // Global platform - bool block_lkas = ((addr == MSG_SUBARU_ES_LKAS) || - (addr == MSG_SUBARU_ES_DashStatus) || - (addr == MSG_SUBARU_ES_LKAS_State) || - (addr == MSG_SUBARU_ES_Infotainment)); - - bool block_long = ((addr == MSG_SUBARU_ES_Brake) || - (addr == MSG_SUBARU_ES_Distance) || - (addr == MSG_SUBARU_ES_Status)); - - bool block_msg = block_lkas || (subaru_longitudinal && block_long); - if (!block_msg) { - bus_fwd = SUBARU_MAIN_BUS; // Main CAN - } - } - - return bus_fwd; -} - -static safety_config subaru_init(uint16_t param) { - static const CanMsg SUBARU_TX_MSGS[] = { - SUBARU_COMMON_TX_MSGS(SUBARU_MAIN_BUS, MSG_SUBARU_ES_LKAS) - }; - - static const CanMsg SUBARU_LONG_TX_MSGS[] = { - SUBARU_COMMON_TX_MSGS(SUBARU_MAIN_BUS, MSG_SUBARU_ES_LKAS) - SUBARU_COMMON_LONG_TX_MSGS(SUBARU_MAIN_BUS) - }; - - static const CanMsg SUBARU_GEN2_TX_MSGS[] = { - SUBARU_COMMON_TX_MSGS(SUBARU_ALT_BUS, MSG_SUBARU_ES_LKAS) - }; - - static const CanMsg SUBARU_GEN2_LONG_TX_MSGS[] = { - SUBARU_COMMON_TX_MSGS(SUBARU_ALT_BUS, MSG_SUBARU_ES_LKAS) - SUBARU_COMMON_LONG_TX_MSGS(SUBARU_ALT_BUS) - SUBARU_GEN2_LONG_ADDITIONAL_TX_MSGS() - }; - - static RxCheck subaru_rx_checks[] = { - SUBARU_COMMON_RX_CHECKS(SUBARU_MAIN_BUS) - }; - - static RxCheck subaru_gen2_rx_checks[] = { - SUBARU_COMMON_RX_CHECKS(SUBARU_ALT_BUS) - }; - - const uint16_t SUBARU_PARAM_GEN2 = 1; - - subaru_gen2 = GET_FLAG(param, SUBARU_PARAM_GEN2); - -#ifdef ALLOW_DEBUG - const uint16_t SUBARU_PARAM_LONGITUDINAL = 2; - subaru_longitudinal = GET_FLAG(param, SUBARU_PARAM_LONGITUDINAL); -#endif - - safety_config ret; - if (subaru_gen2) { - ret = subaru_longitudinal ? BUILD_SAFETY_CFG(subaru_gen2_rx_checks, SUBARU_GEN2_LONG_TX_MSGS) : \ - BUILD_SAFETY_CFG(subaru_gen2_rx_checks, SUBARU_GEN2_TX_MSGS); - } else { - ret = subaru_longitudinal ? BUILD_SAFETY_CFG(subaru_rx_checks, SUBARU_LONG_TX_MSGS) : \ - BUILD_SAFETY_CFG(subaru_rx_checks, SUBARU_TX_MSGS); - } - return ret; -} - -const safety_hooks subaru_hooks = { - .init = subaru_init, - .rx = subaru_rx_hook, - .tx = subaru_tx_hook, - .fwd = subaru_fwd_hook, - .get_counter = subaru_get_counter, - .get_checksum = subaru_get_checksum, - .compute_checksum = subaru_compute_checksum, -}; diff --git a/board/safety/safety_subaru_preglobal.h b/board/safety/safety_subaru_preglobal.h deleted file mode 100644 index 760840f333..0000000000 --- a/board/safety/safety_subaru_preglobal.h +++ /dev/null @@ -1,129 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -// Preglobal platform -// 0x161 is ES_CruiseThrottle -// 0x164 is ES_LKAS - -#define MSG_SUBARU_PG_CruiseControl 0x144 -#define MSG_SUBARU_PG_Throttle 0x140 -#define MSG_SUBARU_PG_Wheel_Speeds 0xD4 -#define MSG_SUBARU_PG_Brake_Pedal 0xD1 -#define MSG_SUBARU_PG_ES_LKAS 0x164 -#define MSG_SUBARU_PG_ES_Distance 0x161 -#define MSG_SUBARU_PG_Steering_Torque 0x371 - -#define SUBARU_PG_MAIN_BUS 0 -#define SUBARU_PG_CAM_BUS 2 - -static bool subaru_pg_reversed_driver_torque = false; - -static void subaru_preglobal_rx_hook(const CANPacket_t *to_push) { - const int bus = GET_BUS(to_push); - - if (bus == SUBARU_PG_MAIN_BUS) { - int addr = GET_ADDR(to_push); - if (addr == MSG_SUBARU_PG_Steering_Torque) { - int torque_driver_new; - torque_driver_new = (GET_BYTE(to_push, 3) >> 5) + (GET_BYTE(to_push, 4) << 3); - torque_driver_new = to_signed(torque_driver_new, 11); - torque_driver_new = subaru_pg_reversed_driver_torque ? -torque_driver_new : torque_driver_new; - update_sample(&torque_driver, torque_driver_new); - } - - // enter controls on rising edge of ACC, exit controls on ACC off - if (addr == MSG_SUBARU_PG_CruiseControl) { - bool cruise_engaged = GET_BIT(to_push, 49U); - pcm_cruise_check(cruise_engaged); - } - - // update vehicle moving with any non-zero wheel speed - if (addr == MSG_SUBARU_PG_Wheel_Speeds) { - vehicle_moving = ((GET_BYTES(to_push, 0, 4) >> 12) != 0U) || (GET_BYTES(to_push, 4, 4) != 0U); - } - - if (addr == MSG_SUBARU_PG_Brake_Pedal) { - brake_pressed = ((GET_BYTES(to_push, 0, 4) >> 16) & 0xFFU) > 0U; - } - - if (addr == MSG_SUBARU_PG_Throttle) { - gas_pressed = GET_BYTE(to_push, 0) != 0U; - } - - generic_rx_checks((addr == MSG_SUBARU_PG_ES_LKAS)); - } -} - -static bool subaru_preglobal_tx_hook(const CANPacket_t *to_send) { - const SteeringLimits SUBARU_PG_STEERING_LIMITS = { - .max_steer = 2047, - .max_rt_delta = 940, - .max_rt_interval = 250000, - .max_rate_up = 50, - .max_rate_down = 70, - .driver_torque_factor = 10, - .driver_torque_allowance = 75, - .type = TorqueDriverLimited, - }; - - bool tx = true; - int addr = GET_ADDR(to_send); - - // steer cmd checks - if (addr == MSG_SUBARU_PG_ES_LKAS) { - int desired_torque = ((GET_BYTES(to_send, 0, 4) >> 8) & 0x1FFFU); - desired_torque = -1 * to_signed(desired_torque, 13); - - bool steer_req = GET_BIT(to_send, 24U); - - if (steer_torque_cmd_checks(desired_torque, steer_req, SUBARU_PG_STEERING_LIMITS)) { - tx = false; - } - - } - return tx; -} - -static int subaru_preglobal_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - - if (bus_num == SUBARU_PG_MAIN_BUS) { - bus_fwd = SUBARU_PG_CAM_BUS; // Camera CAN - } - - if (bus_num == SUBARU_PG_CAM_BUS) { - bool block_msg = ((addr == MSG_SUBARU_PG_ES_Distance) || (addr == MSG_SUBARU_PG_ES_LKAS)); - if (!block_msg) { - bus_fwd = SUBARU_PG_MAIN_BUS; // Main CAN - } - } - - return bus_fwd; -} - -static safety_config subaru_preglobal_init(uint16_t param) { - static const CanMsg SUBARU_PG_TX_MSGS[] = { - {MSG_SUBARU_PG_ES_Distance, SUBARU_PG_MAIN_BUS, 8}, - {MSG_SUBARU_PG_ES_LKAS, SUBARU_PG_MAIN_BUS, 8} - }; - - // TODO: do checksum and counter checks after adding the signals to the outback dbc file - static RxCheck subaru_preglobal_rx_checks[] = { - {.msg = {{MSG_SUBARU_PG_Throttle, SUBARU_PG_MAIN_BUS, 8, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{MSG_SUBARU_PG_Steering_Torque, SUBARU_PG_MAIN_BUS, 8, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{MSG_SUBARU_PG_CruiseControl, SUBARU_PG_MAIN_BUS, 8, .frequency = 20U}, { 0 }, { 0 }}}, - }; - - const int SUBARU_PG_PARAM_REVERSED_DRIVER_TORQUE = 1; - - subaru_pg_reversed_driver_torque = GET_FLAG(param, SUBARU_PG_PARAM_REVERSED_DRIVER_TORQUE); - return BUILD_SAFETY_CFG(subaru_preglobal_rx_checks, SUBARU_PG_TX_MSGS); -} - -const safety_hooks subaru_preglobal_hooks = { - .init = subaru_preglobal_init, - .rx = subaru_preglobal_rx_hook, - .tx = subaru_preglobal_tx_hook, - .fwd = subaru_preglobal_fwd_hook, -}; diff --git a/board/safety/safety_tesla.h b/board/safety/safety_tesla.h deleted file mode 100644 index 7ea50dcfe5..0000000000 --- a/board/safety/safety_tesla.h +++ /dev/null @@ -1,244 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -static bool tesla_longitudinal = false; -static bool tesla_powertrain = false; // Are we the second panda intercepting the powertrain bus? -static bool tesla_raven = false; - -static bool tesla_stock_aeb = false; - -static void tesla_rx_hook(const CANPacket_t *to_push) { - int bus = GET_BUS(to_push); - int addr = GET_ADDR(to_push); - - if (!tesla_powertrain) { - if((!tesla_raven && (addr == 0x370) && (bus == 0)) || (tesla_raven && (addr == 0x131) && (bus == 2))) { - // Steering angle: (0.1 * val) - 819.2 in deg. - // Store it 1/10 deg to match steering request - int angle_meas_new = (((GET_BYTE(to_push, 4) & 0x3FU) << 8) | GET_BYTE(to_push, 5)) - 8192U; - update_sample(&angle_meas, angle_meas_new); - } - } - - if(bus == 0) { - if(addr == (tesla_powertrain ? 0x116 : 0x118)) { - // Vehicle speed: ((0.05 * val) - 25) * MPH_TO_MPS - float speed = (((((GET_BYTE(to_push, 3) & 0x0FU) << 8) | (GET_BYTE(to_push, 2))) * 0.05) - 25) * 0.447; - vehicle_moving = ABS(speed) > 0.1; - UPDATE_VEHICLE_SPEED(speed); - } - - if(addr == (tesla_powertrain ? 0x106 : 0x108)) { - // Gas pressed - gas_pressed = (GET_BYTE(to_push, 6) != 0U); - } - - if(addr == (tesla_powertrain ? 0x1f8 : 0x20a)) { - // Brake pressed - brake_pressed = (((GET_BYTE(to_push, 0) & 0x0CU) >> 2) != 1U); - } - - if(addr == (tesla_powertrain ? 0x256 : 0x368)) { - // Cruise state - int cruise_state = (GET_BYTE(to_push, 1) >> 4); - bool cruise_engaged = (cruise_state == 2) || // ENABLED - (cruise_state == 3) || // STANDSTILL - (cruise_state == 4) || // OVERRIDE - (cruise_state == 6) || // PRE_FAULT - (cruise_state == 7); // PRE_CANCEL - pcm_cruise_check(cruise_engaged); - } - } - - if (bus == 2) { - int das_control_addr = (tesla_powertrain ? 0x2bf : 0x2b9); - if (tesla_longitudinal && (addr == das_control_addr)) { - // "AEB_ACTIVE" - tesla_stock_aeb = ((GET_BYTE(to_push, 2) & 0x03U) == 1U); - } - } - - if (tesla_powertrain) { - // 0x2bf: DAS_control should not be received on bus 0 - generic_rx_checks((addr == 0x2bf) && (bus == 0)); - } else { - // 0x488: DAS_steeringControl should not be received on bus 0 - generic_rx_checks((addr == 0x488) && (bus == 0)); - } - -} - - -static bool tesla_tx_hook(const CANPacket_t *to_send) { - const SteeringLimits TESLA_STEERING_LIMITS = { - .angle_deg_to_can = 10, - .angle_rate_up_lookup = { - {0., 5., 15.}, - {10., 1.6, .3} - }, - .angle_rate_down_lookup = { - {0., 5., 15.}, - {10., 7.0, .8} - }, - }; - - const LongitudinalLimits TESLA_LONG_LIMITS = { - .max_accel = 425, // 2. m/s^2 - .min_accel = 287, // -3.52 m/s^2 // TODO: limit to -3.48 - .inactive_accel = 375, // 0. m/s^2 - }; - - bool tx = true; - int addr = GET_ADDR(to_send); - bool violation = false; - - if(!tesla_powertrain && (addr == 0x488)) { - // Steering control: (0.1 * val) - 1638.35 in deg. - // We use 1/10 deg as a unit here - int raw_angle_can = (((GET_BYTE(to_send, 0) & 0x7FU) << 8) | GET_BYTE(to_send, 1)); - int desired_angle = raw_angle_can - 16384; - int steer_control_type = GET_BYTE(to_send, 2) >> 6; - bool steer_control_enabled = (steer_control_type != 0) && // NONE - (steer_control_type != 3); // DISABLED - - if (steer_angle_cmd_checks(desired_angle, steer_control_enabled, TESLA_STEERING_LIMITS)) { - violation = true; - } - } - - if (!tesla_powertrain && (addr == 0x45)) { - // No button other than cancel can be sent by us - int control_lever_status = (GET_BYTE(to_send, 0) & 0x3FU); - if (control_lever_status != 1) { - violation = true; - } - } - - if(addr == (tesla_powertrain ? 0x2bf : 0x2b9)) { - // DAS_control: longitudinal control message - if (tesla_longitudinal) { - // No AEB events may be sent by openpilot - int aeb_event = GET_BYTE(to_send, 2) & 0x03U; - if (aeb_event != 0) { - violation = true; - } - - // Don't send messages when the stock AEB system is active - if (tesla_stock_aeb) { - violation = true; - } - - // Don't allow any acceleration limits above the safety limits - int raw_accel_max = ((GET_BYTE(to_send, 6) & 0x1FU) << 4) | (GET_BYTE(to_send, 5) >> 4); - int raw_accel_min = ((GET_BYTE(to_send, 5) & 0x0FU) << 5) | (GET_BYTE(to_send, 4) >> 3); - violation |= longitudinal_accel_checks(raw_accel_max, TESLA_LONG_LIMITS); - violation |= longitudinal_accel_checks(raw_accel_min, TESLA_LONG_LIMITS); - } else { - violation = true; - } - } - - if (violation) { - tx = false; - } - - return tx; -} - -static int tesla_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - - if(bus_num == 0) { - // Chassis/PT to autopilot - bus_fwd = 2; - } - - if(bus_num == 2) { - // Autopilot to chassis/PT - int das_control_addr = (tesla_powertrain ? 0x2bf : 0x2b9); - - bool block_msg = false; - if (!tesla_powertrain && (addr == 0x488)) { - block_msg = true; - } - - if (tesla_longitudinal && (addr == das_control_addr) && !tesla_stock_aeb) { - block_msg = true; - } - - if(!block_msg) { - bus_fwd = 0; - } - } - - return bus_fwd; -} - -static safety_config tesla_init(uint16_t param) { - const int TESLA_FLAG_POWERTRAIN = 1; - const int TESLA_FLAG_LONGITUDINAL_CONTROL = 2; - const int TESLA_FLAG_RAVEN = 4; - - static const CanMsg TESLA_TX_MSGS[] = { - {0x488, 0, 4}, // DAS_steeringControl - {0x45, 0, 8}, // STW_ACTN_RQ - {0x45, 2, 8}, // STW_ACTN_RQ - {0x2b9, 0, 8}, // DAS_control - }; - - static const CanMsg TESLA_PT_TX_MSGS[] = { - {0x2bf, 0, 8}, // DAS_control - }; - - tesla_powertrain = GET_FLAG(param, TESLA_FLAG_POWERTRAIN); - tesla_longitudinal = GET_FLAG(param, TESLA_FLAG_LONGITUDINAL_CONTROL); - tesla_raven = GET_FLAG(param, TESLA_FLAG_RAVEN); - - tesla_stock_aeb = false; - - safety_config ret; - if (tesla_powertrain) { - static RxCheck tesla_pt_rx_checks[] = { - {.msg = {{0x106, 0, 8, .frequency = 100U}, { 0 }, { 0 }}}, // DI_torque1 - {.msg = {{0x116, 0, 6, .frequency = 100U}, { 0 }, { 0 }}}, // DI_torque2 - {.msg = {{0x1f8, 0, 8, .frequency = 50U}, { 0 }, { 0 }}}, // BrakeMessage - {.msg = {{0x2bf, 2, 8, .frequency = 25U}, { 0 }, { 0 }}}, // DAS_control - {.msg = {{0x256, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, // DI_state - }; - - ret = BUILD_SAFETY_CFG(tesla_pt_rx_checks, TESLA_PT_TX_MSGS); - } else if (tesla_raven) { - static RxCheck tesla_raven_rx_checks[] = { - {.msg = {{0x2b9, 2, 8, .frequency = 25U}, { 0 }, { 0 }}}, // DAS_control - {.msg = {{0x131, 2, 8, .frequency = 100U}, { 0 }, { 0 }}}, // EPAS3P_sysStatus - {.msg = {{0x108, 0, 8, .frequency = 100U}, { 0 }, { 0 }}}, // DI_torque1 - {.msg = {{0x118, 0, 6, .frequency = 100U}, { 0 }, { 0 }}}, // DI_torque2 - {.msg = {{0x20a, 0, 8, .frequency = 50U}, { 0 }, { 0 }}}, // BrakeMessage - {.msg = {{0x368, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, // DI_state - {.msg = {{0x318, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, // GTW_carState - }; - - ret = BUILD_SAFETY_CFG(tesla_raven_rx_checks, TESLA_TX_MSGS); - } else { - static RxCheck tesla_rx_checks[] = { - {.msg = {{0x2b9, 2, 8, .frequency = 25U}, { 0 }, { 0 }}}, // DAS_control - {.msg = {{0x370, 0, 8, .frequency = 25U}, { 0 }, { 0 }}}, // EPAS_sysStatus - {.msg = {{0x108, 0, 8, .frequency = 100U}, { 0 }, { 0 }}}, // DI_torque1 - {.msg = {{0x118, 0, 6, .frequency = 100U}, { 0 }, { 0 }}}, // DI_torque2 - {.msg = {{0x20a, 0, 8, .frequency = 50U}, { 0 }, { 0 }}}, // BrakeMessage - {.msg = {{0x368, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, // DI_state - {.msg = {{0x318, 0, 8, .frequency = 10U}, { 0 }, { 0 }}}, // GTW_carState - }; - - ret = BUILD_SAFETY_CFG(tesla_rx_checks, TESLA_TX_MSGS); - } - return ret; -} - -const safety_hooks tesla_hooks = { - .init = tesla_init, - .rx = tesla_rx_hook, - .tx = tesla_tx_hook, - .fwd = tesla_fwd_hook, -}; diff --git a/board/safety/safety_toyota.h b/board/safety/safety_toyota.h deleted file mode 100644 index 7008bf8419..0000000000 --- a/board/safety/safety_toyota.h +++ /dev/null @@ -1,413 +0,0 @@ -#pragma once - -#include "safety_declarations.h" - -// Stock longitudinal -#define TOYOTA_BASE_TX_MSGS \ - {0x191, 0, 8}, {0x412, 0, 8}, {0x343, 0, 8}, {0x1D2, 0, 8}, /* LKAS + LTA + ACC & PCM cancel cmds */ \ - -#define TOYOTA_COMMON_TX_MSGS \ - TOYOTA_BASE_TX_MSGS \ - {0x2E4, 0, 5}, \ - -#define TOYOTA_COMMON_SECOC_TX_MSGS \ - TOYOTA_BASE_TX_MSGS \ - {0x2E4, 0, 8}, {0x131, 0, 8}, \ - -#define TOYOTA_COMMON_LONG_TX_MSGS \ - TOYOTA_COMMON_TX_MSGS \ - {0x283, 0, 7}, {0x2E6, 0, 8}, {0x2E7, 0, 8}, {0x33E, 0, 7}, {0x344, 0, 8}, {0x365, 0, 7}, {0x366, 0, 7}, {0x4CB, 0, 8}, /* DSU bus 0 */ \ - {0x128, 1, 6}, {0x141, 1, 4}, {0x160, 1, 8}, {0x161, 1, 7}, {0x470, 1, 4}, /* DSU bus 1 */ \ - {0x411, 0, 8}, /* PCS_HUD */ \ - {0x750, 0, 8}, /* radar diagnostic address */ \ - -#define TOYOTA_COMMON_RX_CHECKS(lta) \ - {.msg = {{ 0xaa, 0, 8, .check_checksum = false, .frequency = 83U}, { 0 }, { 0 }}}, \ - {.msg = {{0x260, 0, 8, .check_checksum = true, .quality_flag = (lta), .frequency = 50U}, { 0 }, { 0 }}}, \ - {.msg = {{0x1D2, 0, 8, .check_checksum = true, .frequency = 33U}, \ - {0x176, 0, 8, .check_checksum = true, .frequency = 32U}, { 0 }}}, \ - {.msg = {{0x101, 0, 8, .check_checksum = false, .frequency = 50U}, \ - {0x224, 0, 8, .check_checksum = false, .frequency = 40U}, \ - {0x226, 0, 8, .check_checksum = false, .frequency = 40U}}}, \ - -static bool toyota_secoc = false; -static bool toyota_alt_brake = false; -static bool toyota_stock_longitudinal = false; -static bool toyota_lta = false; -static int toyota_dbc_eps_torque_factor = 100; // conversion factor for STEER_TORQUE_EPS in %: see dbc file - -static uint32_t toyota_compute_checksum(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - 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; -} - -static uint32_t toyota_get_checksum(const CANPacket_t *to_push) { - int checksum_byte = GET_LEN(to_push) - 1U; - return (uint8_t)(GET_BYTE(to_push, checksum_byte)); -} - -static bool toyota_get_quality_flag_valid(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - - bool valid = false; - if (addr == 0x260) { - valid = !GET_BIT(to_push, 3U); // STEER_ANGLE_INITIALIZING - } - return valid; -} - -static void toyota_rx_hook(const CANPacket_t *to_push) { - const int TOYOTA_LTA_MAX_ANGLE = 1657; // EPS only accepts up to 94.9461 - - if (GET_BUS(to_push) == 0U) { - 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(&torque_meas, torque_meas_new); - - // increase torque_meas by 1 to be conservative on rounding - torque_meas.min--; - torque_meas.max++; - - // driver torque for angle limiting - int torque_driver_new = (GET_BYTE(to_push, 1) << 8) | GET_BYTE(to_push, 2); - torque_driver_new = to_signed(torque_driver_new, 16); - update_sample(&torque_driver, torque_driver_new); - - // LTA request angle should match current angle while inactive, clipped to max accepted angle. - // note that angle can be relative to init angle on some TSS2 platforms, LTA has the same offset - bool steer_angle_initializing = GET_BIT(to_push, 3U); - if (!steer_angle_initializing) { - int angle_meas_new = (GET_BYTE(to_push, 3) << 8U) | GET_BYTE(to_push, 4); - angle_meas_new = CLAMP(to_signed(angle_meas_new, 16), -TOYOTA_LTA_MAX_ANGLE, TOYOTA_LTA_MAX_ANGLE); - update_sample(&angle_meas, angle_meas_new); - } - } - - // enter controls on rising edge of ACC, exit controls on ACC off - // exit controls on rising edge of gas press, if not alternative experience - // exit controls on rising edge of brake press - if (toyota_secoc) { - if (addr == 0x176) { - bool cruise_engaged = GET_BIT(to_push, 5U); // PCM_CRUISE.CRUISE_ACTIVE - pcm_cruise_check(cruise_engaged); - } - if (addr == 0x116) { - gas_pressed = GET_BYTE(to_push, 1) != 0U; // GAS_PEDAL.GAS_PEDAL_USER - } - if (addr == 0x101) { - brake_pressed = GET_BIT(to_push, 3U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_rav4_prime_generated.dbc) - } - } else { - if (addr == 0x1D2) { - bool cruise_engaged = GET_BIT(to_push, 5U); // PCM_CRUISE.CRUISE_ACTIVE - pcm_cruise_check(cruise_engaged); - gas_pressed = !GET_BIT(to_push, 4U); // PCM_CRUISE.GAS_RELEASED - } - if (!toyota_alt_brake && (addr == 0x226)) { - brake_pressed = GET_BIT(to_push, 37U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_nodsu_pt_generated.dbc) - } - if (toyota_alt_brake && (addr == 0x224)) { - brake_pressed = GET_BIT(to_push, 5U); // BRAKE_MODULE.BRAKE_PRESSED (toyota_new_mc_pt_generated.dbc) - } - } - - // sample speed - if (addr == 0xaa) { - int speed = 0; - // sum 4 wheel speeds. conversion: raw * 0.01 - 67.67 - for (uint8_t i = 0U; i < 8U; i += 2U) { - int wheel_speed = (GET_BYTE(to_push, i) << 8U) | GET_BYTE(to_push, (i + 1U)); - speed += wheel_speed - 6767; - } - // check that all wheel speeds are at zero value - vehicle_moving = speed != 0; - - UPDATE_VEHICLE_SPEED(speed / 4.0 * 0.01 / 3.6); - } - - bool stock_ecu_detected = addr == 0x2E4; // STEERING_LKA - if (!toyota_stock_longitudinal && (addr == 0x343)) { - stock_ecu_detected = true; // ACC_CONTROL - } - generic_rx_checks(stock_ecu_detected); - } -} - -static bool toyota_tx_hook(const CANPacket_t *to_send) { - const SteeringLimits TOYOTA_STEERING_LIMITS = { - .max_steer = 1500, - .max_rate_up = 15, // ramp up slow - .max_rate_down = 25, // ramp down fast - .max_torque_error = 350, // max torque cmd in excess of motor torque - .max_rt_delta = 450, // the real time limit is 1800/sec, a 20% buffer - .max_rt_interval = 250000, - .type = TorqueMotorLimited, - - // the EPS faults when the steering angle rate is above a certain threshold for too long. to prevent this, - // we allow setting STEER_REQUEST bit to 0 while maintaining the requested torque value for a single frame - .min_valid_request_frames = 18, - .max_invalid_request_frames = 1, - .min_valid_request_rt_interval = 170000, // 170ms; a ~10% buffer on cutting every 19 frames - .has_steer_req_tolerance = true, - - // LTA angle limits - // factor for STEER_TORQUE_SENSOR->STEER_ANGLE and STEERING_LTA->STEER_ANGLE_CMD (1 / 0.0573) - .angle_deg_to_can = 17.452007, - .angle_rate_up_lookup = { - {5., 25., 25.}, - {0.3, 0.15, 0.15} - }, - .angle_rate_down_lookup = { - {5., 25., 25.}, - {0.36, 0.26, 0.26} - }, - }; - - const int TOYOTA_LTA_MAX_MEAS_TORQUE = 1500; - const int TOYOTA_LTA_MAX_DRIVER_TORQUE = 150; - - // longitudinal limits - const LongitudinalLimits TOYOTA_LONG_LIMITS = { - .max_accel = 2000, // 2.0 m/s2 - .min_accel = -3500, // -3.5 m/s2 - }; - - bool tx = true; - int addr = GET_ADDR(to_send); - int bus = GET_BUS(to_send); - - // Check if msg is sent on BUS 0 - if (bus == 0) { - // ACCEL: safety check on byte 1-2 - if (addr == 0x343) { - int desired_accel = (GET_BYTE(to_send, 0) << 8) | GET_BYTE(to_send, 1); - desired_accel = to_signed(desired_accel, 16); - - bool violation = false; - violation |= longitudinal_accel_checks(desired_accel, TOYOTA_LONG_LIMITS); - - // only ACC messages that cancel are allowed when openpilot is not controlling longitudinal - if (toyota_stock_longitudinal) { - bool cancel_req = GET_BIT(to_send, 24U); - if (!cancel_req) { - violation = true; - } - if (desired_accel != TOYOTA_LONG_LIMITS.inactive_accel) { - violation = true; - } - } - - if (violation) { - tx = false; - } - } - - // AEB: block all actuation. only used when DSU is unplugged - if (addr == 0x283) { - // only allow the checksum, which is the last byte - bool block = (GET_BYTES(to_send, 0, 4) != 0U) || (GET_BYTE(to_send, 4) != 0U) || (GET_BYTE(to_send, 5) != 0U); - if (block) { - tx = false; - } - } - - // STEERING_LTA angle steering check - if (addr == 0x191) { - // check the STEER_REQUEST, STEER_REQUEST_2, TORQUE_WIND_DOWN, STEER_ANGLE_CMD signals - bool lta_request = GET_BIT(to_send, 0U); - bool lta_request2 = GET_BIT(to_send, 25U); - int torque_wind_down = GET_BYTE(to_send, 5); - int lta_angle = (GET_BYTE(to_send, 1) << 8) | GET_BYTE(to_send, 2); - lta_angle = to_signed(lta_angle, 16); - - bool steer_control_enabled = lta_request || lta_request2; - if (!toyota_lta) { - // using torque (LKA), block LTA msgs with actuation requests - if (steer_control_enabled || (lta_angle != 0) || (torque_wind_down != 0)) { - tx = false; - } - } else { - // check angle rate limits and inactive angle - if (steer_angle_cmd_checks(lta_angle, steer_control_enabled, TOYOTA_STEERING_LIMITS)) { - tx = false; - } - - if (lta_request != lta_request2) { - tx = false; - } - - // TORQUE_WIND_DOWN is gated on steer request - if (!steer_control_enabled && (torque_wind_down != 0)) { - tx = false; - } - - // TORQUE_WIND_DOWN can only be no or full torque - if ((torque_wind_down != 0) && (torque_wind_down != 100)) { - tx = false; - } - - // check if we should wind down torque - int driver_torque = MIN(ABS(torque_driver.min), ABS(torque_driver.max)); - if ((driver_torque > TOYOTA_LTA_MAX_DRIVER_TORQUE) && (torque_wind_down != 0)) { - tx = false; - } - - int eps_torque = MIN(ABS(torque_meas.min), ABS(torque_meas.max)); - if ((eps_torque > TOYOTA_LTA_MAX_MEAS_TORQUE) && (torque_wind_down != 0)) { - tx = false; - } - } - } - - // STEERING_LTA_2 angle steering check (SecOC) - if (toyota_secoc && (addr == 0x131)) { - // SecOC cars block any form of LTA actuation for now - bool lta_request = GET_BIT(to_send, 3U); // STEERING_LTA_2.STEER_REQUEST - bool lta_request2 = GET_BIT(to_send, 0U); // STEERING_LTA_2.STEER_REQUEST_2 - int lta_angle_msb = GET_BYTE(to_send, 2); // STEERING_LTA_2.STEER_ANGLE_CMD (MSB) - int lta_angle_lsb = GET_BYTE(to_send, 3); // STEERING_LTA_2.STEER_ANGLE_CMD (LSB) - - bool actuation = lta_request || lta_request2 || (lta_angle_msb != 0) || (lta_angle_lsb != 0); - if (actuation) { - tx = false; - } - } - - // STEER: safety check on bytes 2-3 - if (addr == 0x2E4) { - int desired_torque = (GET_BYTE(to_send, 1) << 8) | GET_BYTE(to_send, 2); - desired_torque = to_signed(desired_torque, 16); - bool steer_req = GET_BIT(to_send, 0U); - // When using LTA (angle control), assert no actuation on LKA message - if (!toyota_lta) { - if (steer_torque_cmd_checks(desired_torque, steer_req, TOYOTA_STEERING_LIMITS)) { - tx = false; - } - } else { - if ((desired_torque != 0) || steer_req) { - tx = false; - } - } - } - } - - // UDS: Only tester present ("\x0F\x02\x3E\x00\x00\x00\x00\x00") allowed on diagnostics address - if (addr == 0x750) { - // this address is sub-addressed. only allow tester present to radar (0xF) - bool invalid_uds_msg = (GET_BYTES(to_send, 0, 4) != 0x003E020FU) || (GET_BYTES(to_send, 4, 4) != 0x0U); - if (invalid_uds_msg) { - tx = 0; - } - } - - return tx; -} - -static safety_config toyota_init(uint16_t param) { - static const CanMsg TOYOTA_TX_MSGS[] = { - TOYOTA_COMMON_TX_MSGS - }; - - static const CanMsg TOYOTA_SECOC_TX_MSGS[] = { - TOYOTA_COMMON_SECOC_TX_MSGS - }; - - static const CanMsg TOYOTA_LONG_TX_MSGS[] = { - TOYOTA_COMMON_LONG_TX_MSGS - }; - - // safety param flags - // first byte is for EPS factor, second is for flags - const uint32_t TOYOTA_PARAM_OFFSET = 8U; - const uint32_t TOYOTA_EPS_FACTOR = (1UL << TOYOTA_PARAM_OFFSET) - 1U; - const uint32_t TOYOTA_PARAM_ALT_BRAKE = 1UL << TOYOTA_PARAM_OFFSET; - const uint32_t TOYOTA_PARAM_STOCK_LONGITUDINAL = 2UL << TOYOTA_PARAM_OFFSET; - const uint32_t TOYOTA_PARAM_LTA = 4UL << TOYOTA_PARAM_OFFSET; - -#ifdef ALLOW_DEBUG - const uint32_t TOYOTA_PARAM_SECOC = 8UL << TOYOTA_PARAM_OFFSET; - toyota_secoc = GET_FLAG(param, TOYOTA_PARAM_SECOC); -#endif - - toyota_alt_brake = GET_FLAG(param, TOYOTA_PARAM_ALT_BRAKE); - toyota_stock_longitudinal = GET_FLAG(param, TOYOTA_PARAM_STOCK_LONGITUDINAL); - toyota_lta = GET_FLAG(param, TOYOTA_PARAM_LTA); - toyota_dbc_eps_torque_factor = param & TOYOTA_EPS_FACTOR; - - safety_config ret; - if (toyota_stock_longitudinal) { - if (toyota_secoc) { - SET_TX_MSGS(TOYOTA_SECOC_TX_MSGS, ret); - } else { - SET_TX_MSGS(TOYOTA_TX_MSGS, ret); - } - } else { - SET_TX_MSGS(TOYOTA_LONG_TX_MSGS, ret); - } - - if (toyota_lta) { - // Check the quality flag for angle measurement when using LTA, since it's not set on TSS-P cars - static RxCheck toyota_lta_rx_checks[] = { - TOYOTA_COMMON_RX_CHECKS(true) - }; - - SET_RX_CHECKS(toyota_lta_rx_checks, ret); - } else { - static RxCheck toyota_lka_rx_checks[] = { - TOYOTA_COMMON_RX_CHECKS(false) - }; - - SET_RX_CHECKS(toyota_lka_rx_checks, ret); - } - - return ret; -} - -static int toyota_fwd_hook(int bus_num, int addr) { - - int bus_fwd = -1; - - if (bus_num == 0) { - bus_fwd = 2; - } - - if (bus_num == 2) { - // block stock lkas messages and stock acc messages (if OP is doing ACC) - // in TSS2, 0x191 is LTA which we need to block to avoid controls collision - bool is_lkas_msg = ((addr == 0x2E4) || (addr == 0x412) || (addr == 0x191)); - // on SecOC cars 0x131 is also LTA - is_lkas_msg |= toyota_secoc && (addr == 0x131); - // in TSS2 the camera does ACC as well, so filter 0x343 - bool is_acc_msg = (addr == 0x343); - bool block_msg = is_lkas_msg || (is_acc_msg && !toyota_stock_longitudinal); - if (!block_msg) { - bus_fwd = 0; - } - } - - return bus_fwd; -} - -const safety_hooks toyota_hooks = { - .init = toyota_init, - .rx = toyota_rx_hook, - .tx = toyota_tx_hook, - .fwd = toyota_fwd_hook, - .get_checksum = toyota_get_checksum, - .compute_checksum = toyota_compute_checksum, - .get_quality_flag_valid = toyota_get_quality_flag_valid, -}; diff --git a/board/safety/safety_volkswagen_common.h b/board/safety/safety_volkswagen_common.h deleted file mode 100644 index f94879212b..0000000000 --- a/board/safety/safety_volkswagen_common.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -extern const uint16_t FLAG_VOLKSWAGEN_LONG_CONTROL; -const uint16_t FLAG_VOLKSWAGEN_LONG_CONTROL = 1; - -extern bool volkswagen_longitudinal; -bool volkswagen_longitudinal = false; - -extern bool volkswagen_set_button_prev; -bool volkswagen_set_button_prev = false; - -extern bool volkswagen_resume_button_prev; -bool volkswagen_resume_button_prev = false; diff --git a/board/safety/safety_volkswagen_mqb.h b/board/safety/safety_volkswagen_mqb.h deleted file mode 100644 index 40f7cbccc9..0000000000 --- a/board/safety/safety_volkswagen_mqb.h +++ /dev/null @@ -1,302 +0,0 @@ -#pragma once - -#include "safety_declarations.h" -#include "safety_volkswagen_common.h" - -#define MSG_ESP_19 0x0B2 // RX from ABS, for wheel speeds -#define MSG_LH_EPS_03 0x09F // RX from EPS, for driver steering torque -#define MSG_ESP_05 0x106 // RX from ABS, for brake switch state -#define MSG_TSK_06 0x120 // RX from ECU, for ACC status from drivetrain coordinator -#define MSG_MOTOR_20 0x121 // RX from ECU, for driver throttle input -#define MSG_ACC_06 0x122 // TX by OP, ACC control instructions to the drivetrain coordinator -#define MSG_HCA_01 0x126 // TX by OP, Heading Control Assist steering torque -#define MSG_GRA_ACC_01 0x12B // TX by OP, ACC control buttons for cancel/resume -#define MSG_ACC_07 0x12E // TX by OP, ACC control instructions to the drivetrain coordinator -#define MSG_ACC_02 0x30C // TX by OP, ACC HUD data to the instrument cluster -#define MSG_MOTOR_14 0x3BE // RX from ECU, for brake switch status -#define MSG_LDW_02 0x397 // TX by OP, Lane line recognition and text alerts - -static uint8_t volkswagen_crc8_lut_8h2f[256]; // Static lookup table for CRC8 poly 0x2F, aka 8H2F/AUTOSAR -static bool volkswagen_mqb_brake_pedal_switch = false; -static bool volkswagen_mqb_brake_pressure_detected = false; - -static uint32_t volkswagen_mqb_get_checksum(const CANPacket_t *to_push) { - return (uint8_t)GET_BYTE(to_push, 0); -} - -static uint8_t volkswagen_mqb_get_counter(const CANPacket_t *to_push) { - // MQB message counters are consistently found at LSB 8. - return (uint8_t)GET_BYTE(to_push, 1) & 0xFU; -} - -static uint32_t volkswagen_mqb_compute_crc(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - int len = GET_LEN(to_push); - - // This is CRC-8H2F/AUTOSAR with a twist. See the OpenDBC implementation - // of this algorithm for a version with explanatory comments. - - uint8_t crc = 0xFFU; - for (int i = 1; i < len; i++) { - crc ^= (uint8_t)GET_BYTE(to_push, i); - crc = volkswagen_crc8_lut_8h2f[crc]; - } - - uint8_t counter = volkswagen_mqb_get_counter(to_push); - if (addr == MSG_LH_EPS_03) { - crc ^= (uint8_t[]){0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5}[counter]; - } else if (addr == MSG_ESP_05) { - crc ^= (uint8_t[]){0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07}[counter]; - } else if (addr == MSG_TSK_06) { - crc ^= (uint8_t[]){0xC4,0xE2,0x4F,0xE4,0xF8,0x2F,0x56,0x81,0x9F,0xE5,0x83,0x44,0x05,0x3F,0x97,0xDF}[counter]; - } else if (addr == MSG_MOTOR_20) { - crc ^= (uint8_t[]){0xE9,0x65,0xAE,0x6B,0x7B,0x35,0xE5,0x5F,0x4E,0xC7,0x86,0xA2,0xBB,0xDD,0xEB,0xB4}[counter]; - } else if (addr == MSG_GRA_ACC_01) { - crc ^= (uint8_t[]){0x6A,0x38,0xB4,0x27,0x22,0xEF,0xE1,0xBB,0xF8,0x80,0x84,0x49,0xC7,0x9E,0x1E,0x2B}[counter]; - } else { - // Undefined CAN message, CRC check expected to fail - } - crc = volkswagen_crc8_lut_8h2f[crc]; - - return (uint8_t)(crc ^ 0xFFU); -} - -static safety_config volkswagen_mqb_init(uint16_t param) { - // Transmit of GRA_ACC_01 is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration - static const CanMsg VOLKSWAGEN_MQB_STOCK_TX_MSGS[] = {{MSG_HCA_01, 0, 8}, {MSG_GRA_ACC_01, 0, 8}, {MSG_GRA_ACC_01, 2, 8}, - {MSG_LDW_02, 0, 8}, {MSG_LH_EPS_03, 2, 8}}; - - static const CanMsg VOLKSWAGEN_MQB_LONG_TX_MSGS[] = {{MSG_HCA_01, 0, 8}, {MSG_LDW_02, 0, 8}, {MSG_LH_EPS_03, 2, 8}, - {MSG_ACC_02, 0, 8}, {MSG_ACC_06, 0, 8}, {MSG_ACC_07, 0, 8}}; - - static RxCheck volkswagen_mqb_rx_checks[] = { - {.msg = {{MSG_ESP_19, 0, 8, .check_checksum = false, .max_counter = 0U, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{MSG_LH_EPS_03, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{MSG_ESP_05, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{MSG_TSK_06, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{MSG_MOTOR_20, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{MSG_MOTOR_14, 0, 8, .check_checksum = false, .max_counter = 0U, .frequency = 10U}, { 0 }, { 0 }}}, - {.msg = {{MSG_GRA_ACC_01, 0, 8, .check_checksum = true, .max_counter = 15U, .frequency = 33U}, { 0 }, { 0 }}}, - }; - - UNUSED(param); - - volkswagen_set_button_prev = false; - volkswagen_resume_button_prev = false; - volkswagen_mqb_brake_pedal_switch = false; - volkswagen_mqb_brake_pressure_detected = false; - -#ifdef ALLOW_DEBUG - volkswagen_longitudinal = GET_FLAG(param, FLAG_VOLKSWAGEN_LONG_CONTROL); -#endif - gen_crc_lookup_table_8(0x2F, volkswagen_crc8_lut_8h2f); - return volkswagen_longitudinal ? BUILD_SAFETY_CFG(volkswagen_mqb_rx_checks, VOLKSWAGEN_MQB_LONG_TX_MSGS) : \ - BUILD_SAFETY_CFG(volkswagen_mqb_rx_checks, VOLKSWAGEN_MQB_STOCK_TX_MSGS); -} - -static void volkswagen_mqb_rx_hook(const CANPacket_t *to_push) { - if (GET_BUS(to_push) == 0U) { - int addr = GET_ADDR(to_push); - - // Update in-motion state by sampling wheel speeds - if (addr == MSG_ESP_19) { - // sum 4 wheel speeds - int speed = 0; - for (uint8_t i = 0U; i < 8U; i += 2U) { - int wheel_speed = GET_BYTE(to_push, i) | (GET_BYTE(to_push, i + 1U) << 8); - speed += wheel_speed; - } - // Check all wheel speeds for any movement - vehicle_moving = speed > 0; - } - - // Update driver input torque samples - // Signal: LH_EPS_03.EPS_Lenkmoment (absolute torque) - // Signal: LH_EPS_03.EPS_VZ_Lenkmoment (direction) - if (addr == MSG_LH_EPS_03) { - int torque_driver_new = GET_BYTE(to_push, 5) | ((GET_BYTE(to_push, 6) & 0x1FU) << 8); - int sign = (GET_BYTE(to_push, 6) & 0x80U) >> 7; - if (sign == 1) { - torque_driver_new *= -1; - } - update_sample(&torque_driver, torque_driver_new); - } - - if (addr == MSG_TSK_06) { - // When using stock ACC, enter controls on rising edge of stock ACC engage, exit on disengage - // Always exit controls on main switch off - // Signal: TSK_06.TSK_Status - int acc_status = (GET_BYTE(to_push, 3) & 0x7U); - bool cruise_engaged = (acc_status == 3) || (acc_status == 4) || (acc_status == 5); - acc_main_on = cruise_engaged || (acc_status == 2); - - if (!volkswagen_longitudinal) { - pcm_cruise_check(cruise_engaged); - } - - if (!acc_main_on) { - controls_allowed = false; - } - } - - if (addr == MSG_GRA_ACC_01) { - // If using openpilot longitudinal, enter controls on falling edge of Set or Resume with main switch on - // Signal: GRA_ACC_01.GRA_Tip_Setzen - // Signal: GRA_ACC_01.GRA_Tip_Wiederaufnahme - if (volkswagen_longitudinal) { - bool set_button = GET_BIT(to_push, 16U); - bool resume_button = GET_BIT(to_push, 19U); - if ((volkswagen_set_button_prev && !set_button) || (volkswagen_resume_button_prev && !resume_button)) { - controls_allowed = acc_main_on; - } - volkswagen_set_button_prev = set_button; - volkswagen_resume_button_prev = resume_button; - } - // Always exit controls on rising edge of Cancel - // Signal: GRA_ACC_01.GRA_Abbrechen - if (GET_BIT(to_push, 13U)) { - controls_allowed = false; - } - } - - // Signal: Motor_20.MO_Fahrpedalrohwert_01 - if (addr == MSG_MOTOR_20) { - gas_pressed = ((GET_BYTES(to_push, 0, 4) >> 12) & 0xFFU) != 0U; - } - - // Signal: Motor_14.MO_Fahrer_bremst (ECU detected brake pedal switch F63) - if (addr == MSG_MOTOR_14) { - volkswagen_mqb_brake_pedal_switch = (GET_BYTE(to_push, 3) & 0x10U) >> 4; - } - - // Signal: ESP_05.ESP_Fahrer_bremst (ESP detected driver brake pressure above platform specified threshold) - if (addr == MSG_ESP_05) { - volkswagen_mqb_brake_pressure_detected = (GET_BYTE(to_push, 3) & 0x4U) >> 2; - } - - brake_pressed = volkswagen_mqb_brake_pedal_switch || volkswagen_mqb_brake_pressure_detected; - - generic_rx_checks((addr == MSG_HCA_01)); - } -} - -static bool volkswagen_mqb_tx_hook(const CANPacket_t *to_send) { - // lateral limits - const SteeringLimits VOLKSWAGEN_MQB_STEERING_LIMITS = { - .max_steer = 300, // 3.0 Nm (EPS side max of 3.0Nm with fault if violated) - .max_rt_delta = 75, // 4 max rate up * 50Hz send rate * 250000 RT interval / 1000000 = 50 ; 50 * 1.5 for safety pad = 75 - .max_rt_interval = 250000, // 250ms between real time checks - .max_rate_up = 4, // 2.0 Nm/s RoC limit (EPS rack has own soft-limit of 5.0 Nm/s) - .max_rate_down = 10, // 5.0 Nm/s RoC limit (EPS rack has own soft-limit of 5.0 Nm/s) - .driver_torque_allowance = 80, - .driver_torque_factor = 3, - .type = TorqueDriverLimited, - }; - - // longitudinal limits - // acceleration in m/s2 * 1000 to avoid floating point math - const LongitudinalLimits VOLKSWAGEN_MQB_LONG_LIMITS = { - .max_accel = 2000, - .min_accel = -3500, - .inactive_accel = 3010, // VW sends one increment above the max range when inactive - }; - - int addr = GET_ADDR(to_send); - bool tx = true; - - // Safety check for HCA_01 Heading Control Assist torque - // Signal: HCA_01.HCA_01_LM_Offset (absolute torque) - // Signal: HCA_01.HCA_01_LM_OffSign (direction) - if (addr == MSG_HCA_01) { - int desired_torque = GET_BYTE(to_send, 2) | ((GET_BYTE(to_send, 3) & 0x1U) << 8); - bool sign = GET_BIT(to_send, 31U); - if (sign) { - desired_torque *= -1; - } - - bool steer_req = GET_BIT(to_send, 30U); - - if (steer_torque_cmd_checks(desired_torque, steer_req, VOLKSWAGEN_MQB_STEERING_LIMITS)) { - tx = false; - } - } - - // Safety check for both ACC_06 and ACC_07 acceleration requests - // To avoid floating point math, scale upward and compare to pre-scaled safety m/s2 boundaries - if ((addr == MSG_ACC_06) || (addr == MSG_ACC_07)) { - bool violation = false; - int desired_accel = 0; - - if (addr == MSG_ACC_06) { - // Signal: ACC_06.ACC_Sollbeschleunigung_02 (acceleration in m/s2, scale 0.005, offset -7.22) - desired_accel = ((((GET_BYTE(to_send, 4) & 0x7U) << 8) | GET_BYTE(to_send, 3)) * 5U) - 7220U; - } else { - // Signal: ACC_07.ACC_Folgebeschl (acceleration in m/s2, scale 0.03, offset -4.6) - int secondary_accel = (GET_BYTE(to_send, 4) * 30U) - 4600U; - violation |= (secondary_accel != 3020); // enforce always inactive (one increment above max range) at this time - // Signal: ACC_07.ACC_Sollbeschleunigung_02 (acceleration in m/s2, scale 0.005, offset -7.22) - desired_accel = (((GET_BYTE(to_send, 7) << 3) | ((GET_BYTE(to_send, 6) & 0xE0U) >> 5)) * 5U) - 7220U; - } - - violation |= longitudinal_accel_checks(desired_accel, VOLKSWAGEN_MQB_LONG_LIMITS); - - if (violation) { - tx = false; - } - } - - // FORCE CANCEL: ensuring that only the cancel button press is sent when controls are off. - // This avoids unintended engagements while still allowing resume spam - if ((addr == MSG_GRA_ACC_01) && !controls_allowed) { - // disallow resume and set: bits 16 and 19 - if ((GET_BYTE(to_send, 2) & 0x9U) != 0U) { - tx = false; - } - } - - return tx; -} - -static int volkswagen_mqb_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - - switch (bus_num) { - case 0: - if (addr == MSG_LH_EPS_03) { - // openpilot needs to replace apparent driver steering input torque to pacify VW Emergency Assist - bus_fwd = -1; - } else { - // Forward all remaining traffic from Extended CAN onward - bus_fwd = 2; - } - break; - case 2: - if ((addr == MSG_HCA_01) || (addr == MSG_LDW_02)) { - // openpilot takes over LKAS steering control and related HUD messages from the camera - bus_fwd = -1; - } else if (volkswagen_longitudinal && ((addr == MSG_ACC_02) || (addr == MSG_ACC_06) || (addr == MSG_ACC_07))) { - // openpilot takes over acceleration/braking control and related HUD messages from the stock ACC radar - bus_fwd = -1; - } else { - // Forward all remaining traffic from Extended CAN devices to J533 gateway - bus_fwd = 0; - } - break; - default: - // No other buses should be in use; fallback to do-not-forward - bus_fwd = -1; - break; - } - - return bus_fwd; -} - -const safety_hooks volkswagen_mqb_hooks = { - .init = volkswagen_mqb_init, - .rx = volkswagen_mqb_rx_hook, - .tx = volkswagen_mqb_tx_hook, - .fwd = volkswagen_mqb_fwd_hook, - .get_counter = volkswagen_mqb_get_counter, - .get_checksum = volkswagen_mqb_get_checksum, - .compute_checksum = volkswagen_mqb_compute_crc, -}; diff --git a/board/safety/safety_volkswagen_pq.h b/board/safety/safety_volkswagen_pq.h deleted file mode 100644 index 75979a5149..0000000000 --- a/board/safety/safety_volkswagen_pq.h +++ /dev/null @@ -1,259 +0,0 @@ -#pragma once - -#include "safety_declarations.h" -#include "safety_volkswagen_common.h" - -#define MSG_LENKHILFE_3 0x0D0 // RX from EPS, for steering angle and driver steering torque -#define MSG_HCA_1 0x0D2 // TX by OP, Heading Control Assist steering torque -#define MSG_BREMSE_1 0x1A0 // RX from ABS, for ego speed -#define MSG_MOTOR_2 0x288 // RX from ECU, for CC state and brake switch state -#define MSG_ACC_SYSTEM 0x368 // TX by OP, longitudinal acceleration controls -#define MSG_MOTOR_3 0x380 // RX from ECU, for driver throttle input -#define MSG_GRA_NEU 0x38A // TX by OP, ACC control buttons for cancel/resume -#define MSG_MOTOR_5 0x480 // RX from ECU, for ACC main switch state -#define MSG_ACC_GRA_ANZEIGE 0x56A // TX by OP, ACC HUD -#define MSG_LDW_1 0x5BE // TX by OP, Lane line recognition and text alerts - -static uint32_t volkswagen_pq_get_checksum(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - - return (uint32_t)GET_BYTE(to_push, (addr == MSG_MOTOR_5) ? 7 : 0); -} - -static uint8_t volkswagen_pq_get_counter(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - uint8_t counter = 0U; - - if (addr == MSG_LENKHILFE_3) { - counter = (uint8_t)(GET_BYTE(to_push, 1) & 0xF0U) >> 4; - } else if (addr == MSG_GRA_NEU) { - counter = (uint8_t)(GET_BYTE(to_push, 2) & 0xF0U) >> 4; - } else { - } - - return counter; -} - -static uint32_t volkswagen_pq_compute_checksum(const CANPacket_t *to_push) { - int addr = GET_ADDR(to_push); - int len = GET_LEN(to_push); - uint8_t checksum = 0U; - int checksum_byte = (addr == MSG_MOTOR_5) ? 7 : 0; - - // Simple XOR over the payload, except for the byte where the checksum lives. - for (int i = 0; i < len; i++) { - if (i != checksum_byte) { - checksum ^= (uint8_t)GET_BYTE(to_push, i); - } - } - - return checksum; -} - -static safety_config volkswagen_pq_init(uint16_t param) { - // Transmit of GRA_Neu is allowed on bus 0 and 2 to keep compatibility with gateway and camera integration - static const CanMsg VOLKSWAGEN_PQ_STOCK_TX_MSGS[] = {{MSG_HCA_1, 0, 5}, {MSG_LDW_1, 0, 8}, - {MSG_GRA_NEU, 0, 4}, {MSG_GRA_NEU, 2, 4}}; - - static const CanMsg VOLKSWAGEN_PQ_LONG_TX_MSGS[] = {{MSG_HCA_1, 0, 5}, {MSG_LDW_1, 0, 8}, - {MSG_ACC_SYSTEM, 0, 8}, {MSG_ACC_GRA_ANZEIGE, 0, 8}}; - - static RxCheck volkswagen_pq_rx_checks[] = { - {.msg = {{MSG_LENKHILFE_3, 0, 6, .check_checksum = true, .max_counter = 15U, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{MSG_BREMSE_1, 0, 8, .check_checksum = false, .max_counter = 0U, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{MSG_MOTOR_2, 0, 8, .check_checksum = false, .max_counter = 0U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{MSG_MOTOR_3, 0, 8, .check_checksum = false, .max_counter = 0U, .frequency = 100U}, { 0 }, { 0 }}}, - {.msg = {{MSG_MOTOR_5, 0, 8, .check_checksum = true, .max_counter = 0U, .frequency = 50U}, { 0 }, { 0 }}}, - {.msg = {{MSG_GRA_NEU, 0, 4, .check_checksum = true, .max_counter = 15U, .frequency = 30U}, { 0 }, { 0 }}}, - }; - - UNUSED(param); - - volkswagen_set_button_prev = false; - volkswagen_resume_button_prev = false; - -#ifdef ALLOW_DEBUG - volkswagen_longitudinal = GET_FLAG(param, FLAG_VOLKSWAGEN_LONG_CONTROL); -#endif - return volkswagen_longitudinal ? BUILD_SAFETY_CFG(volkswagen_pq_rx_checks, VOLKSWAGEN_PQ_LONG_TX_MSGS) : \ - BUILD_SAFETY_CFG(volkswagen_pq_rx_checks, VOLKSWAGEN_PQ_STOCK_TX_MSGS); -} - -static void volkswagen_pq_rx_hook(const CANPacket_t *to_push) { - if (GET_BUS(to_push) == 0U) { - int addr = GET_ADDR(to_push); - - // Update in-motion state from speed value. - // Signal: Bremse_1.Geschwindigkeit_neu__Bremse_1_ - if (addr == MSG_BREMSE_1) { - int speed = ((GET_BYTE(to_push, 2) & 0xFEU) >> 1) | (GET_BYTE(to_push, 3) << 7); - vehicle_moving = speed > 0; - } - - // Update driver input torque samples - // Signal: Lenkhilfe_3.LH3_LM (absolute torque) - // Signal: Lenkhilfe_3.LH3_LMSign (direction) - if (addr == MSG_LENKHILFE_3) { - int torque_driver_new = GET_BYTE(to_push, 2) | ((GET_BYTE(to_push, 3) & 0x3U) << 8); - int sign = (GET_BYTE(to_push, 3) & 0x4U) >> 2; - if (sign == 1) { - torque_driver_new *= -1; - } - update_sample(&torque_driver, torque_driver_new); - } - - if (volkswagen_longitudinal) { - if (addr == MSG_MOTOR_5) { - // ACC main switch on is a prerequisite to enter controls, exit controls immediately on main switch off - // Signal: Motor_5.GRA_Hauptschalter - acc_main_on = GET_BIT(to_push, 50U); - if (!acc_main_on) { - controls_allowed = false; - } - } - - if (addr == MSG_GRA_NEU) { - // If ACC main switch is on, enter controls on falling edge of Set or Resume - // Signal: GRA_Neu.GRA_Neu_Setzen - // Signal: GRA_Neu.GRA_Neu_Recall - bool set_button = GET_BIT(to_push, 16U); - bool resume_button = GET_BIT(to_push, 17U); - if ((volkswagen_set_button_prev && !set_button) || (volkswagen_resume_button_prev && !resume_button)) { - controls_allowed = acc_main_on; - } - volkswagen_set_button_prev = set_button; - volkswagen_resume_button_prev = resume_button; - // Exit controls on rising edge of Cancel, override Set/Resume if present simultaneously - // Signal: GRA_ACC_01.GRA_Abbrechen - if (GET_BIT(to_push, 9U)) { - controls_allowed = false; - } - } - } else { - if (addr == MSG_MOTOR_2) { - // Enter controls on rising edge of stock ACC, exit controls if stock ACC disengages - // Signal: Motor_2.GRA_Status - int acc_status = (GET_BYTE(to_push, 2) & 0xC0U) >> 6; - bool cruise_engaged = (acc_status == 1) || (acc_status == 2); - pcm_cruise_check(cruise_engaged); - } - } - - // Signal: Motor_3.Fahrpedal_Rohsignal - if (addr == MSG_MOTOR_3) { - gas_pressed = (GET_BYTE(to_push, 2)); - } - - // Signal: Motor_2.Bremslichtschalter - if (addr == MSG_MOTOR_2) { - brake_pressed = (GET_BYTE(to_push, 2) & 0x1U); - } - - generic_rx_checks((addr == MSG_HCA_1)); - } -} - -static bool volkswagen_pq_tx_hook(const CANPacket_t *to_send) { - // lateral limits - const SteeringLimits VOLKSWAGEN_PQ_STEERING_LIMITS = { - .max_steer = 300, // 3.0 Nm (EPS side max of 3.0Nm with fault if violated) - .max_rt_delta = 113, // 6 max rate up * 50Hz send rate * 250000 RT interval / 1000000 = 75 ; 125 * 1.5 for safety pad = 113 - .max_rt_interval = 250000, // 250ms between real time checks - .max_rate_up = 6, // 3.0 Nm/s RoC limit (EPS rack has own soft-limit of 5.0 Nm/s) - .max_rate_down = 10, // 5.0 Nm/s RoC limit (EPS rack has own soft-limit of 5.0 Nm/s) - .driver_torque_factor = 3, - .driver_torque_allowance = 80, - .type = TorqueDriverLimited, - }; - - // longitudinal limits - // acceleration in m/s2 * 1000 to avoid floating point math - const LongitudinalLimits VOLKSWAGEN_PQ_LONG_LIMITS = { - .max_accel = 2000, - .min_accel = -3500, - .inactive_accel = 3010, // VW sends one increment above the max range when inactive - }; - - int addr = GET_ADDR(to_send); - bool tx = true; - - // Safety check for HCA_1 Heading Control Assist torque - // Signal: HCA_1.LM_Offset (absolute torque) - // Signal: HCA_1.LM_Offsign (direction) - if (addr == MSG_HCA_1) { - int desired_torque = GET_BYTE(to_send, 2) | ((GET_BYTE(to_send, 3) & 0x7FU) << 8); - desired_torque = desired_torque / 32; // DBC scale from PQ network to centi-Nm - int sign = (GET_BYTE(to_send, 3) & 0x80U) >> 7; - if (sign == 1) { - desired_torque *= -1; - } - - uint32_t hca_status = ((GET_BYTE(to_send, 1) >> 4) & 0xFU); - bool steer_req = ((hca_status == 5U) || (hca_status == 7U)); - - if (steer_torque_cmd_checks(desired_torque, steer_req, VOLKSWAGEN_PQ_STEERING_LIMITS)) { - tx = false; - } - } - - // Safety check for acceleration commands - // To avoid floating point math, scale upward and compare to pre-scaled safety m/s2 boundaries - if (addr == MSG_ACC_SYSTEM) { - // Signal: ACC_System.ACS_Sollbeschl (acceleration in m/s2, scale 0.005, offset -7.22) - int desired_accel = ((((GET_BYTE(to_send, 4) & 0x7U) << 8) | GET_BYTE(to_send, 3)) * 5U) - 7220U; - - if (longitudinal_accel_checks(desired_accel, VOLKSWAGEN_PQ_LONG_LIMITS)) { - tx = false; - } - } - - // FORCE CANCEL: ensuring that only the cancel button press is sent when controls are off. - // This avoids unintended engagements while still allowing resume spam - if ((addr == MSG_GRA_NEU) && !controls_allowed) { - // Signal: GRA_Neu.GRA_Neu_Setzen - // Signal: GRA_Neu.GRA_Neu_Recall - if (GET_BIT(to_send, 16U) || GET_BIT(to_send, 17U)) { - tx = false; - } - } - - return tx; -} - -static int volkswagen_pq_fwd_hook(int bus_num, int addr) { - int bus_fwd = -1; - - switch (bus_num) { - case 0: - // Forward all traffic from the Extended CAN onward - bus_fwd = 2; - break; - case 2: - if ((addr == MSG_HCA_1) || (addr == MSG_LDW_1)) { - // openpilot takes over LKAS steering control and related HUD messages from the camera - bus_fwd = -1; - } else if (volkswagen_longitudinal && ((addr == MSG_ACC_SYSTEM) || (addr == MSG_ACC_GRA_ANZEIGE))) { - // openpilot takes over acceleration/braking control and related HUD messages from the stock ACC radar - } else { - // Forward all remaining traffic from Extended CAN devices to J533 gateway - bus_fwd = 0; - } - break; - default: - // No other buses should be in use; fallback to do-not-forward - bus_fwd = -1; - break; - } - - return bus_fwd; -} - -const safety_hooks volkswagen_pq_hooks = { - .init = volkswagen_pq_init, - .rx = volkswagen_pq_rx_hook, - .tx = volkswagen_pq_tx_hook, - .fwd = volkswagen_pq_fwd_hook, - .get_counter = volkswagen_pq_get_counter, - .get_checksum = volkswagen_pq_get_checksum, - .compute_checksum = volkswagen_pq_compute_checksum, -}; diff --git a/examples/query_fw_versions.py b/examples/query_fw_versions.py index 8064c86907..862429ae20 100755 --- a/examples/query_fw_versions.py +++ b/examples/query_fw_versions.py @@ -2,7 +2,7 @@ import argparse from tqdm import tqdm from panda import Panda -from panda.python.uds import UdsClient, MessageTimeoutError, NegativeResponseError, InvalidSubAddressError, \ +from opendbc.can.uds import UdsClient, MessageTimeoutError, NegativeResponseError, InvalidSubAddressError, \ SESSION_TYPE, DATA_IDENTIFIER_TYPE if __name__ == "__main__": diff --git a/python/__init__.py b/python/__init__.py index 4e729d30a5..fb052ede2b 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -184,48 +184,6 @@ class Panda: HARNESS_STATUS_NORMAL = 1 HARNESS_STATUS_FLIPPED = 2 - # first byte is for EPS scaling factor - FLAG_TOYOTA_ALT_BRAKE = (1 << 8) - FLAG_TOYOTA_STOCK_LONGITUDINAL = (2 << 8) - FLAG_TOYOTA_LTA = (4 << 8) - FLAG_TOYOTA_SECOC = (8 << 8) - - FLAG_HONDA_ALT_BRAKE = 1 - FLAG_HONDA_BOSCH_LONG = 2 - FLAG_HONDA_NIDEC_ALT = 4 - FLAG_HONDA_RADARLESS = 8 - - FLAG_HYUNDAI_EV_GAS = 1 - FLAG_HYUNDAI_HYBRID_GAS = 2 - FLAG_HYUNDAI_LONG = 4 - FLAG_HYUNDAI_CAMERA_SCC = 8 - FLAG_HYUNDAI_CANFD_HDA2 = 16 - FLAG_HYUNDAI_CANFD_ALT_BUTTONS = 32 - FLAG_HYUNDAI_ALT_LIMITS = 64 - FLAG_HYUNDAI_CANFD_HDA2_ALT_STEERING = 128 - - FLAG_TESLA_POWERTRAIN = 1 - FLAG_TESLA_LONG_CONTROL = 2 - FLAG_TESLA_RAVEN = 4 - - FLAG_VOLKSWAGEN_LONG_CONTROL = 1 - - FLAG_CHRYSLER_RAM_DT = 1 - FLAG_CHRYSLER_RAM_HD = 2 - - FLAG_SUBARU_GEN2 = 1 - FLAG_SUBARU_LONG = 2 - - FLAG_SUBARU_PREGLOBAL_REVERSED_DRIVER_TORQUE = 1 - - FLAG_NISSAN_ALT_EPS_BUS = 1 - - FLAG_GM_HW_CAM = 1 - FLAG_GM_HW_CAM_LONG = 2 - - FLAG_FORD_LONG_CONTROL = 1 - FLAG_FORD_CANFD = 2 - def __init__(self, serial: str | None = None, claim: bool = True, disable_checks: bool = True, can_speed_kbps: int = 500, cli: bool = True): self._disable_checks = disable_checks diff --git a/python/uds.py b/python/uds.py deleted file mode 100644 index 612eb206b0..0000000000 --- a/python/uds.py +++ /dev/null @@ -1,943 +0,0 @@ -import time -import struct -from collections import deque -from typing import NamedTuple, Deque, cast -from collections.abc import Callable, Generator -from enum import IntEnum -from functools import partial - -class SERVICE_TYPE(IntEnum): - DIAGNOSTIC_SESSION_CONTROL = 0x10 - ECU_RESET = 0x11 - SECURITY_ACCESS = 0x27 - COMMUNICATION_CONTROL = 0x28 - TESTER_PRESENT = 0x3E - ACCESS_TIMING_PARAMETER = 0x83 - SECURED_DATA_TRANSMISSION = 0x84 - CONTROL_DTC_SETTING = 0x85 - RESPONSE_ON_EVENT = 0x86 - LINK_CONTROL = 0x87 - READ_DATA_BY_IDENTIFIER = 0x22 - READ_MEMORY_BY_ADDRESS = 0x23 - READ_SCALING_DATA_BY_IDENTIFIER = 0x24 - READ_DATA_BY_PERIODIC_IDENTIFIER = 0x2A - DYNAMICALLY_DEFINE_DATA_IDENTIFIER = 0x2C - WRITE_DATA_BY_IDENTIFIER = 0x2E - WRITE_MEMORY_BY_ADDRESS = 0x3D - CLEAR_DIAGNOSTIC_INFORMATION = 0x14 - READ_DTC_INFORMATION = 0x19 - INPUT_OUTPUT_CONTROL_BY_IDENTIFIER = 0x2F - ROUTINE_CONTROL = 0x31 - REQUEST_DOWNLOAD = 0x34 - REQUEST_UPLOAD = 0x35 - TRANSFER_DATA = 0x36 - REQUEST_TRANSFER_EXIT = 0x37 - -class SESSION_TYPE(IntEnum): - DEFAULT = 1 - PROGRAMMING = 2 - EXTENDED_DIAGNOSTIC = 3 - SAFETY_SYSTEM_DIAGNOSTIC = 4 - -class RESET_TYPE(IntEnum): - HARD = 1 - KEY_OFF_ON = 2 - SOFT = 3 - ENABLE_RAPID_POWER_SHUTDOWN = 4 - DISABLE_RAPID_POWER_SHUTDOWN = 5 - -class ACCESS_TYPE(IntEnum): - REQUEST_SEED = 1 - SEND_KEY = 2 - -class CONTROL_TYPE(IntEnum): - ENABLE_RX_ENABLE_TX = 0 - ENABLE_RX_DISABLE_TX = 1 - DISABLE_RX_ENABLE_TX = 2 - DISABLE_RX_DISABLE_TX = 3 - -class MESSAGE_TYPE(IntEnum): - NORMAL = 1 - NETWORK_MANAGEMENT = 2 - NORMAL_AND_NETWORK_MANAGEMENT = 3 - -class TIMING_PARAMETER_TYPE(IntEnum): - READ_EXTENDED_SET = 1 - SET_TO_DEFAULT_VALUES = 2 - READ_CURRENTLY_ACTIVE = 3 - SET_TO_GIVEN_VALUES = 4 - -class DTC_SETTING_TYPE(IntEnum): - ON = 1 - OFF = 2 - -class RESPONSE_EVENT_TYPE(IntEnum): - STOP_RESPONSE_ON_EVENT = 0 - ON_DTC_STATUS_CHANGE = 1 - ON_TIMER_INTERRUPT = 2 - ON_CHANGE_OF_DATA_IDENTIFIER = 3 - REPORT_ACTIVATED_EVENTS = 4 - START_RESPONSE_ON_EVENT = 5 - CLEAR_RESPONSE_ON_EVENT = 6 - ON_COMPARISON_OF_VALUES = 7 - -class LINK_CONTROL_TYPE(IntEnum): - VERIFY_BAUDRATE_TRANSITION_WITH_FIXED_BAUDRATE = 1 - VERIFY_BAUDRATE_TRANSITION_WITH_SPECIFIC_BAUDRATE = 2 - TRANSITION_BAUDRATE = 3 - -class BAUD_RATE_TYPE(IntEnum): - PC9600 = 1 - PC19200 = 2 - PC38400 = 3 - PC57600 = 4 - PC115200 = 5 - CAN125000 = 16 - CAN250000 = 17 - CAN500000 = 18 - CAN1000000 = 19 - -class DATA_IDENTIFIER_TYPE(IntEnum): - BOOT_SOFTWARE_IDENTIFICATION = 0xF180 - APPLICATION_SOFTWARE_IDENTIFICATION = 0xF181 - APPLICATION_DATA_IDENTIFICATION = 0xF182 - BOOT_SOFTWARE_FINGERPRINT = 0xF183 - APPLICATION_SOFTWARE_FINGERPRINT = 0xF184 - APPLICATION_DATA_FINGERPRINT = 0xF185 - ACTIVE_DIAGNOSTIC_SESSION = 0xF186 - VEHICLE_MANUFACTURER_SPARE_PART_NUMBER = 0xF187 - VEHICLE_MANUFACTURER_ECU_SOFTWARE_NUMBER = 0xF188 - VEHICLE_MANUFACTURER_ECU_SOFTWARE_VERSION_NUMBER = 0xF189 - SYSTEM_SUPPLIER_IDENTIFIER = 0xF18A - ECU_MANUFACTURING_DATE = 0xF18B - ECU_SERIAL_NUMBER = 0xF18C - SUPPORTED_FUNCTIONAL_UNITS = 0xF18D - VEHICLE_MANUFACTURER_KIT_ASSEMBLY_PART_NUMBER = 0xF18E - VIN = 0xF190 - VEHICLE_MANUFACTURER_ECU_HARDWARE_NUMBER = 0xF191 - SYSTEM_SUPPLIER_ECU_HARDWARE_NUMBER = 0xF192 - SYSTEM_SUPPLIER_ECU_HARDWARE_VERSION_NUMBER = 0xF193 - SYSTEM_SUPPLIER_ECU_SOFTWARE_NUMBER = 0xF194 - SYSTEM_SUPPLIER_ECU_SOFTWARE_VERSION_NUMBER = 0xF195 - EXHAUST_REGULATION_OR_TYPE_APPROVAL_NUMBER = 0xF196 - SYSTEM_NAME_OR_ENGINE_TYPE = 0xF197 - REPAIR_SHOP_CODE_OR_TESTER_SERIAL_NUMBER = 0xF198 - PROGRAMMING_DATE = 0xF199 - CALIBRATION_REPAIR_SHOP_CODE_OR_CALIBRATION_EQUIPMENT_SERIAL_NUMBER = 0xF19A - CALIBRATION_DATE = 0xF19B - CALIBRATION_EQUIPMENT_SOFTWARE_NUMBER = 0xF19C - ECU_INSTALLATION_DATE = 0xF19D - ODX_FILE = 0xF19E - ENTITY = 0xF19F - -class TRANSMISSION_MODE_TYPE(IntEnum): - SEND_AT_SLOW_RATE = 1 - SEND_AT_MEDIUM_RATE = 2 - SEND_AT_FAST_RATE = 3 - STOP_SENDING = 4 - -class DYNAMIC_DEFINITION_TYPE(IntEnum): - DEFINE_BY_IDENTIFIER = 1 - DEFINE_BY_MEMORY_ADDRESS = 2 - CLEAR_DYNAMICALLY_DEFINED_DATA_IDENTIFIER = 3 - -class ISOTP_FRAME_TYPE(IntEnum): - SINGLE = 0 - FIRST = 1 - CONSECUTIVE = 2 - FLOW = 3 - -class DynamicSourceDefinition(NamedTuple): - data_identifier: int - position: int - memory_size: int - memory_address: int - -class DTC_GROUP_TYPE(IntEnum): - EMISSIONS = 0x000000 - ALL = 0xFFFFFF - -class DTC_REPORT_TYPE(IntEnum): - NUMBER_OF_DTC_BY_STATUS_MASK = 0x01 - DTC_BY_STATUS_MASK = 0x02 - DTC_SNAPSHOT_IDENTIFICATION = 0x03 - DTC_SNAPSHOT_RECORD_BY_DTC_NUMBER = 0x04 - DTC_SNAPSHOT_RECORD_BY_RECORD_NUMBER = 0x05 - DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER = 0x06 - NUMBER_OF_DTC_BY_SEVERITY_MASK_RECORD = 0x07 - DTC_BY_SEVERITY_MASK_RECORD = 0x08 - SEVERITY_INFORMATION_OF_DTC = 0x09 - SUPPORTED_DTC = 0x0A - FIRST_TEST_FAILED_DTC = 0x0B - FIRST_CONFIRMED_DTC = 0x0C - MOST_RECENT_TEST_FAILED_DTC = 0x0D - MOST_RECENT_CONFIRMED_DTC = 0x0E - MIRROR_MEMORY_DTC_BY_STATUS_MASK = 0x0F - MIRROR_MEMORY_DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER = 0x10 - NUMBER_OF_MIRROR_MEMORY_DTC_BY_STATUS_MASK = 0x11 - NUMBER_OF_EMISSIONS_RELATED_OBD_DTC_BY_STATUS_MASK = 0x12 - EMISSIONS_RELATED_OBD_DTC_BY_STATUS_MASK = 0x13 - DTC_FAULT_DETECTION_COUNTER = 0x14 - DTC_WITH_PERMANENT_STATUS = 0x15 - -class DTC_STATUS_MASK_TYPE(IntEnum): - TEST_FAILED = 0x01 - TEST_FAILED_THIS_OPERATION_CYCLE = 0x02 - PENDING_DTC = 0x04 - CONFIRMED_DTC = 0x08 - TEST_NOT_COMPLETED_SINCE_LAST_CLEAR = 0x10 - TEST_FAILED_SINCE_LAST_CLEAR = 0x20 - TEST_NOT_COMPLETED_THIS_OPERATION_CYCLE = 0x40 - WARNING_INDICATOR_REQUESTED = 0x80 - ALL = 0xFF - -class DTC_SEVERITY_MASK_TYPE(IntEnum): - MAINTENANCE_ONLY = 0x20 - CHECK_AT_NEXT_HALT = 0x40 - CHECK_IMMEDIATELY = 0x80 - ALL = 0xE0 - -class CONTROL_PARAMETER_TYPE(IntEnum): - RETURN_CONTROL_TO_ECU = 0 - RESET_TO_DEFAULT = 1 - FREEZE_CURRENT_STATE = 2 - SHORT_TERM_ADJUSTMENT = 3 - -class ROUTINE_CONTROL_TYPE(IntEnum): - START = 1 - STOP = 2 - REQUEST_RESULTS = 3 - -class ROUTINE_IDENTIFIER_TYPE(IntEnum): - ERASE_MEMORY = 0xFF00 - CHECK_PROGRAMMING_DEPENDENCIES = 0xFF01 - ERASE_MIRROR_MEMORY_DTCS = 0xFF02 - -class MessageTimeoutError(Exception): - pass - -class NegativeResponseError(Exception): - def __init__(self, message, service_id, error_code): - super().__init__() - self.message = message - self.service_id = service_id - self.error_code = error_code - - def __str__(self): - return self.message - -class InvalidServiceIdError(Exception): - pass - -class InvalidSubFunctionError(Exception): - pass - -class InvalidSubAddressError(Exception): - pass - -_negative_response_codes = { - 0x00: 'positive response', - 0x10: 'general reject', - 0x11: 'service not supported', - 0x12: 'sub-function not supported', - 0x13: 'incorrect message length or invalid format', - 0x14: 'response too long', - 0x21: 'busy repeat request', - 0x22: 'conditions not correct', - 0x24: 'request sequence error', - 0x25: 'no response from subnet component', - 0x26: 'failure prevents execution of requested action', - 0x31: 'request out of range', - 0x33: 'security access denied', - 0x35: 'invalid key', - 0x36: 'exceed number of attempts', - 0x37: 'required time delay not expired', - 0x70: 'upload download not accepted', - 0x71: 'transfer data suspended', - 0x72: 'general programming failure', - 0x73: 'wrong block sequence counter', - 0x78: 'request correctly received - response pending', - 0x7e: 'sub-function not supported in active session', - 0x7f: 'service not supported in active session', - 0x81: 'rpm too high', - 0x82: 'rpm too low', - 0x83: 'engine is running', - 0x84: 'engine is not running', - 0x85: 'engine run time too low', - 0x86: 'temperature too high', - 0x87: 'temperature too low', - 0x88: 'vehicle speed too high', - 0x89: 'vehicle speed too low', - 0x8a: 'throttle/pedal too high', - 0x8b: 'throttle/pedal too low', - 0x8c: 'transmission not in neutral', - 0x8d: 'transmission not in gear', - 0x8f: 'brake switch(es) not closed', - 0x90: 'shifter lever not in park', - 0x91: 'torque converter clutch locked', - 0x92: 'voltage too high', - 0x93: 'voltage too low', -} - -def get_dtc_num_as_str(dtc_num_bytes): - # ISO 15031-6 - designator = { - 0b00: "P", - 0b01: "C", - 0b10: "B", - 0b11: "U", - } - d = designator[dtc_num_bytes[0] >> 6] - n = bytes([dtc_num_bytes[0] & 0x3F]) + dtc_num_bytes[1:] - return d + n.hex() - -def get_dtc_status_names(status): - result = list() - for m in DTC_STATUS_MASK_TYPE: - if m == DTC_STATUS_MASK_TYPE.ALL: - continue - if status & m.value: - result.append(m.name) - return result - -class CanClient(): - def __init__(self, can_send: Callable[[int, bytes, int], None], can_recv: Callable[[], list[tuple[int, bytes, int]]], - tx_addr: int, rx_addr: int, bus: int, sub_addr: int | None = None, debug: bool = False): - self.tx = can_send - self.rx = can_recv - self.tx_addr = tx_addr - self.rx_addr = rx_addr - self.rx_buff: Deque[bytes] = deque() - self.sub_addr = sub_addr - self.bus = bus - self.debug = debug - - def _recv_filter(self, bus: int, addr: int) -> bool: - # handle functional addresses (switch to first addr to respond) - if self.tx_addr == 0x7DF: - is_response = addr >= 0x7E8 and addr <= 0x7EF - if is_response: - if self.debug: - print(f"switch to physical addr {hex(addr)}") - self.tx_addr = addr - 8 - self.rx_addr = addr - return is_response - if self.tx_addr == 0x18DB33F1: - is_response = addr >= 0x18DAF100 and addr <= 0x18DAF1FF - if is_response: - if self.debug: - print(f"switch to physical addr {hex(addr)}") - self.tx_addr = 0x18DA00F1 + (addr << 8 & 0xFF00) - self.rx_addr = addr - return bus == self.bus and addr == self.rx_addr - - def _recv_buffer(self, drain: bool = False) -> None: - while True: - msgs = self.rx() - if drain: - if self.debug: - print(f"CAN-RX: drain - {len(msgs)}") - self.rx_buff.clear() - else: - for rx_addr, 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 - - 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: - if rx_data[0] != self.sub_addr: - raise InvalidSubAddressError(f"isotp - rx: invalid sub-address: {rx_data[0]}, expected: {self.sub_addr}") - rx_data = rx_data[1:] - - self.rx_buff.append(rx_data) - # break when non-full buffer is processed - if len(msgs) < 254: - return - - def recv(self, drain: bool = False) -> Generator[bytes, None, None]: - # buffer rx messages in case two response messages are received at once - # (e.g. response pending and success/failure response) - self._recv_buffer(drain) - try: - while True: - yield self.rx_buff.popleft() - except IndexError: - pass # empty - - def send(self, msgs: list[bytes], delay: float = 0) -> None: - for i, msg in enumerate(msgs): - if delay and i != 0: - 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) - # prevent rx buffer from overflowing on large tx - if i % 10 == 9: - self._recv_buffer() - -class IsoTpMessage(): - def __init__(self, can_client: CanClient, timeout: float = 1, single_frame_mode: bool = False, separation_time: float = 0, - debug: bool = False, max_len: int = 8): - self._can_client = can_client - self.timeout = timeout - self.single_frame_mode = single_frame_mode - self.debug = debug - self.max_len = max_len - - # <= 127, separation time in milliseconds - # 0xF1 to 0xF9 UF, 100 to 900 microseconds - if 1e-4 <= separation_time <= 9e-4: - offset = int(round(separation_time, 4) * 1e4) - 1 - separation_time = 0xF1 + offset - elif 0 <= separation_time <= 0.127: - separation_time = round(separation_time * 1000) - else: - raise Exception("Separation time not in range") - - self.flow_control_msg = bytes([ - 0x30, # flow control - 0x01 if self.single_frame_mode else 0x00, # block size - separation_time, - ]).ljust(self.max_len, b"\x00") - - def send(self, dat: bytes, setup_only: bool = False) -> None: - # throw away any stale data - self._can_client.recv(drain=True) - - self.tx_dat = dat - self.tx_len = len(dat) - self.tx_idx = 0 - self.tx_done = False - - self.rx_dat = b"" - self.rx_len = 0 - self.rx_idx = 0 - self.rx_done = False - - if self.debug and not setup_only: - print(f"ISO-TP: REQUEST - {hex(self._can_client.tx_addr)} 0x{bytes.hex(self.tx_dat)}") - self._tx_first_frame(setup_only=setup_only) - - def _tx_first_frame(self, setup_only: bool = False) -> None: - if self.tx_len < self.max_len: - # single frame (send all bytes) - if self.debug and not setup_only: - print(f"ISO-TP: TX - single frame - {hex(self._can_client.tx_addr)}") - 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 and not setup_only: - print(f"ISO-TP: TX - first frame - {hex(self._can_client.tx_addr)}") - msg = (struct.pack("!H", 0x1000 | self.tx_len) + self.tx_dat[:self.max_len - 2]).ljust(self.max_len - 2, b"\x00") - if not setup_only: - self._can_client.send([msg]) - - def recv(self, timeout=None) -> tuple[bytes | None, bool]: - if timeout is None: - timeout = self.timeout - - start_time = time.monotonic() - rx_in_progress = False - try: - while True: - for msg in self._can_client.recv(): - frame_type = self._isotp_rx_next(msg) - start_time = time.monotonic() - # Anything that signifies we're building a response - rx_in_progress = frame_type in (ISOTP_FRAME_TYPE.FIRST, ISOTP_FRAME_TYPE.CONSECUTIVE) - if self.tx_done and self.rx_done: - return self.rx_dat, False - # no timeout indicates non-blocking - if timeout == 0: - return None, rx_in_progress - if time.monotonic() - start_time > timeout: - raise MessageTimeoutError("timeout waiting for response") - finally: - if self.debug and self.rx_dat: - print(f"ISO-TP: RESPONSE - {hex(self._can_client.rx_addr)} 0x{bytes.hex(self.rx_dat)}") - - def _isotp_rx_next(self, rx_data: bytes) -> ISOTP_FRAME_TYPE: - # TODO: Handle CAN frame data optimization, which is allowed with some frame types - # # ISO 15765-2 specifies an eight byte CAN frame for ISO-TP communication - # assert len(rx_data) == self.max_len, f"isotp - rx: invalid CAN frame length: {len(rx_data)}" - - if rx_data[0] >> 4 == ISOTP_FRAME_TYPE.SINGLE: - assert self.rx_dat == b"" or self.rx_done, "isotp - rx: single frame with active frame" - self.rx_len = rx_data[0] & 0x0F - assert self.rx_len < self.max_len, f"isotp - rx: invalid single frame length: {self.rx_len}" - self.rx_dat = rx_data[1:1 + self.rx_len] - self.rx_idx = 0 - self.rx_done = True - if self.debug: - print(f"ISO-TP: RX - single frame - {hex(self._can_client.rx_addr)} idx={self.rx_idx} done={self.rx_done}") - return ISOTP_FRAME_TYPE.SINGLE - - elif rx_data[0] >> 4 == ISOTP_FRAME_TYPE.FIRST: - # Once a first frame is received, further frames must be consecutive - assert self.rx_dat == b"" or self.rx_done, "isotp - rx: first frame with active frame" - self.rx_len = ((rx_data[0] & 0x0F) << 8) + rx_data[1] - assert self.rx_len >= self.max_len, f"isotp - rx: invalid first frame length: {self.rx_len}" - assert len(rx_data) == self.max_len, f"isotp - rx: invalid CAN frame length: {len(rx_data)}" - self.rx_dat = rx_data[2:] - self.rx_idx = 0 - self.rx_done = False - if self.debug: - print(f"ISO-TP: RX - first frame - {hex(self._can_client.rx_addr)} idx={self.rx_idx} done={self.rx_done}") - if self.debug: - print(f"ISO-TP: TX - flow control continue - {hex(self._can_client.tx_addr)}") - # send flow control message - self._can_client.send([self.flow_control_msg]) - return ISOTP_FRAME_TYPE.FIRST - - elif rx_data[0] >> 4 == ISOTP_FRAME_TYPE.CONSECUTIVE: - assert not self.rx_done, "isotp - rx: consecutive frame with no active frame" - 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 + rx_size] - if self.rx_len == len(self.rx_dat): - self.rx_done = True - elif self.single_frame_mode: - # notify ECU to send next frame - self._can_client.send([self.flow_control_msg]) - if self.debug: - print(f"ISO-TP: RX - consecutive frame - {hex(self._can_client.rx_addr)} idx={self.rx_idx} done={self.rx_done}") - return ISOTP_FRAME_TYPE.CONSECUTIVE - - elif rx_data[0] >> 4 == ISOTP_FRAME_TYPE.FLOW: - assert not self.tx_done, "isotp - rx: flow control with no active frame" - assert rx_data[0] != 0x32, "isotp - rx: flow-control overflow/abort" - assert rx_data[0] == 0x30 or rx_data[0] == 0x31, "isotp - rx: flow-control transfer state indicator invalid" - if rx_data[0] == 0x30: - if self.debug: - print(f"ISO-TP: RX - flow control continue - {hex(self._can_client.tx_addr)}") - delay_ts = rx_data[2] & 0x7F - # 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 - num_bytes = self.max_len - 1 - start = self.max_len - 2 + self.tx_idx * num_bytes - count = rx_data[1] - end = start + count * num_bytes if count > 0 else self.tx_len - tx_msgs = [] - 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 + 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) - if end >= self.tx_len: - self.tx_done = True - if self.debug: - print(f"ISO-TP: TX - consecutive frame - {hex(self._can_client.tx_addr)} idx={self.tx_idx} done={self.tx_done}") - elif rx_data[0] == 0x31: - # wait (do nothing until next flow control message) - if self.debug: - print(f"ISO-TP: TX - flow control wait - {hex(self._can_client.tx_addr)}") - return ISOTP_FRAME_TYPE.FLOW - - # 4-15 - reserved - else: - raise Exception(f"isotp - rx: invalid frame type: {rx_data[0] >> 4}") - - -FUNCTIONAL_ADDRS = [0x7DF, 0x18DB33F1] - - -def get_rx_addr_for_tx_addr(tx_addr, rx_offset=0x8): - if tx_addr in FUNCTIONAL_ADDRS: - return None - - if tx_addr < 0xFFF8: - # pseudo-standard 11 bit response addr (add 8) works for most manufacturers - # allow override; some manufacturers use other offsets for non-OBD2 access - return tx_addr + rx_offset - - 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(f"invalid tx_addr: {tx_addr}") - - -class UdsClient(): - def __init__(self, panda, tx_addr: int, rx_addr: int | None = None, bus: int = 0, sub_addr: int | None = None, timeout: float = 1, - debug: bool = False, tx_timeout: float = 1, response_pending_timeout: float = 10): - self.bus = bus - self.tx_addr = tx_addr - self.rx_addr = rx_addr if rx_addr is not None else get_rx_addr_for_tx_addr(tx_addr) - self.sub_addr = sub_addr - self.timeout = timeout - self.debug = debug - can_send_with_timeout = partial(panda.can_send, timeout=int(tx_timeout*1000)) - self._can_client = CanClient(can_send_with_timeout, panda.can_recv, self.tx_addr, self.rx_addr, self.bus, self.sub_addr, debug=self.debug) - self.response_pending_timeout = response_pending_timeout - - # generic uds request - def _uds_request(self, service_type: SERVICE_TYPE, subfunction: int | None = None, data: bytes | None = None) -> bytes: - req = bytes([service_type]) - if subfunction is not None: - req += bytes([subfunction]) - if data is not None: - req += data - - # send request, wait for response - max_len = 8 if self.sub_addr is None else 7 - isotp_msg = IsoTpMessage(self._can_client, timeout=self.timeout, debug=self.debug, max_len=max_len) - isotp_msg.send(req) - response_pending = False - while True: - timeout = self.response_pending_timeout if response_pending else self.timeout - resp, _ = isotp_msg.recv(timeout) - - if resp is None: - continue - - response_pending = False - resp_sid = resp[0] if len(resp) > 0 else None - - # negative response - if resp_sid == 0x7F: - service_id = resp[1] if len(resp) > 1 else -1 - try: - service_desc = SERVICE_TYPE(service_id).name - except BaseException: - service_desc = 'NON_STANDARD_SERVICE' - error_code = resp[2] if len(resp) > 2 else -1 - try: - error_desc = _negative_response_codes[error_code] - except BaseException: - error_desc = resp[3:].hex() - # wait for another message if response pending - if error_code == 0x78: - response_pending = True - if self.debug: - print("UDS-RX: response pending") - continue - raise NegativeResponseError(f'{service_desc} - {error_desc}', service_id, error_code) - - # positive response - if service_type + 0x40 != resp_sid: - resp_sid_hex = hex(resp_sid) if resp_sid is not None else None - raise InvalidServiceIdError(f'invalid response service id: {resp_sid_hex}') - - if subfunction is not None: - resp_sfn = resp[1] if len(resp) > 1 else None - if subfunction != resp_sfn: - resp_sfn_hex = hex(resp_sfn) if resp_sfn is not None else None - raise InvalidSubFunctionError(f'invalid response subfunction: {resp_sfn_hex}') - - # return data (exclude service id and sub-function id) - return resp[(1 if subfunction is None else 2):] - - # services - def diagnostic_session_control(self, session_type: SESSION_TYPE): - self._uds_request(SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL, subfunction=session_type) - - def ecu_reset(self, reset_type: RESET_TYPE): - resp = self._uds_request(SERVICE_TYPE.ECU_RESET, subfunction=reset_type) - power_down_time = None - if reset_type == RESET_TYPE.ENABLE_RAPID_POWER_SHUTDOWN: - power_down_time = resp[0] - return power_down_time - - def security_access(self, access_type: ACCESS_TYPE, security_key: bytes = b'', data_record: bytes = b''): - request_seed = access_type % 2 != 0 - if request_seed and len(security_key) != 0: - raise ValueError('security_key not allowed') - if not request_seed and len(security_key) == 0: - raise ValueError('security_key is missing') - if not request_seed and len(data_record) != 0: - raise ValueError('data_record not allowed') - data = security_key + data_record - resp = self._uds_request(SERVICE_TYPE.SECURITY_ACCESS, subfunction=access_type, data=data) - if request_seed: - security_seed = resp - return security_seed - - def communication_control(self, control_type: CONTROL_TYPE, message_type: MESSAGE_TYPE): - data = bytes([message_type]) - self._uds_request(SERVICE_TYPE.COMMUNICATION_CONTROL, subfunction=control_type, data=data) - - def tester_present(self, ): - self._uds_request(SERVICE_TYPE.TESTER_PRESENT, subfunction=0x00) - - def access_timing_parameter(self, timing_parameter_type: TIMING_PARAMETER_TYPE, parameter_values: bytes | None = None): - write_custom_values = timing_parameter_type == TIMING_PARAMETER_TYPE.SET_TO_GIVEN_VALUES - read_values = (timing_parameter_type == TIMING_PARAMETER_TYPE.READ_CURRENTLY_ACTIVE or - timing_parameter_type == TIMING_PARAMETER_TYPE.READ_EXTENDED_SET) - if not write_custom_values and parameter_values is not None: - raise ValueError('parameter_values not allowed') - if write_custom_values and parameter_values is None: - raise ValueError('parameter_values is missing') - resp = self._uds_request(SERVICE_TYPE.ACCESS_TIMING_PARAMETER, subfunction=timing_parameter_type, data=parameter_values) - if read_values: - # TODO: parse response into values? - parameter_values = resp - return parameter_values - - def secured_data_transmission(self, data: bytes): - # TODO: split data into multiple input parameters? - resp = self._uds_request(SERVICE_TYPE.SECURED_DATA_TRANSMISSION, subfunction=None, data=data) - # TODO: parse response into multiple output values? - return resp - - def control_dtc_setting(self, dtc_setting_type: DTC_SETTING_TYPE): - self._uds_request(SERVICE_TYPE.CONTROL_DTC_SETTING, subfunction=dtc_setting_type) - - def response_on_event(self, response_event_type: RESPONSE_EVENT_TYPE, store_event: bool, window_time: int, - event_type_record: int, service_response_record: int): - if store_event: - response_event_type |= 0x20 # type: ignore - # TODO: split record parameters into arrays - data = bytes([window_time, event_type_record, service_response_record]) - resp = self._uds_request(SERVICE_TYPE.RESPONSE_ON_EVENT, subfunction=response_event_type, data=data) - - if response_event_type == RESPONSE_EVENT_TYPE.REPORT_ACTIVATED_EVENTS: - return { - "num_of_activated_events": resp[0], - "data": resp[1:], # TODO: parse the reset of response - } - - return { - "num_of_identified_events": resp[0], - "event_window_time": resp[1], - "data": resp[2:], # TODO: parse the reset of response - } - - def link_control(self, link_control_type: LINK_CONTROL_TYPE, baud_rate_type: BAUD_RATE_TYPE | None = None): - data: bytes | None - - if link_control_type == LINK_CONTROL_TYPE.VERIFY_BAUDRATE_TRANSITION_WITH_FIXED_BAUDRATE: - # baud_rate_type = BAUD_RATE_TYPE - data = bytes([cast(int, baud_rate_type)]) - elif link_control_type == LINK_CONTROL_TYPE.VERIFY_BAUDRATE_TRANSITION_WITH_SPECIFIC_BAUDRATE: - # baud_rate_type = custom value (3 bytes big-endian) - data = struct.pack('!I', baud_rate_type)[1:] - else: - data = None - self._uds_request(SERVICE_TYPE.LINK_CONTROL, subfunction=link_control_type, data=data) - - def read_data_by_identifier(self, data_identifier_type: DATA_IDENTIFIER_TYPE): - # TODO: support list of identifiers - data = struct.pack('!H', data_identifier_type) - resp = self._uds_request(SERVICE_TYPE.READ_DATA_BY_IDENTIFIER, subfunction=None, data=data) - resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None - if resp_id != data_identifier_type: - raise ValueError(f'invalid response data identifier: {hex(resp_id)} expected: {hex(data_identifier_type)}') - return resp[2:] - - def read_memory_by_address(self, memory_address: int, memory_size: int, memory_address_bytes: int = 4, memory_size_bytes: int = 1): - if memory_address_bytes < 1 or memory_address_bytes > 4: - raise ValueError(f'invalid memory_address_bytes: {memory_address_bytes}') - if memory_size_bytes < 1 or memory_size_bytes > 4: - raise ValueError(f'invalid memory_size_bytes: {memory_size_bytes}') - data = bytes([memory_size_bytes << 4 | memory_address_bytes]) - - if memory_address >= 1 << (memory_address_bytes * 8): - raise ValueError(f'invalid memory_address: {memory_address}') - data += struct.pack('!I', memory_address)[4 - memory_address_bytes:] - if memory_size >= 1 << (memory_size_bytes * 8): - raise ValueError(f'invalid memory_size: {memory_size}') - data += struct.pack('!I', memory_size)[4 - memory_size_bytes:] - - resp = self._uds_request(SERVICE_TYPE.READ_MEMORY_BY_ADDRESS, subfunction=None, data=data) - return resp - - def read_scaling_data_by_identifier(self, data_identifier_type: DATA_IDENTIFIER_TYPE): - data = struct.pack('!H', data_identifier_type) - resp = self._uds_request(SERVICE_TYPE.READ_SCALING_DATA_BY_IDENTIFIER, subfunction=None, data=data) - resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None - if resp_id != data_identifier_type: - raise ValueError(f'invalid response data identifier: {hex(resp_id)}') - return resp[2:] # TODO: parse the response - - def read_data_by_periodic_identifier(self, transmission_mode_type: TRANSMISSION_MODE_TYPE, periodic_data_identifier: int): - # TODO: support list of identifiers - data = bytes([transmission_mode_type, periodic_data_identifier]) - self._uds_request(SERVICE_TYPE.READ_DATA_BY_PERIODIC_IDENTIFIER, subfunction=None, data=data) - - def dynamically_define_data_identifier(self, dynamic_definition_type: DYNAMIC_DEFINITION_TYPE, dynamic_data_identifier: int, - source_definitions: list[DynamicSourceDefinition], memory_address_bytes: int = 4, memory_size_bytes: int = 1): - if memory_address_bytes < 1 or memory_address_bytes > 4: - raise ValueError(f'invalid memory_address_bytes: {memory_address_bytes}') - if memory_size_bytes < 1 or memory_size_bytes > 4: - raise ValueError(f'invalid memory_size_bytes: {memory_size_bytes}') - - data = struct.pack('!H', dynamic_data_identifier) - if dynamic_definition_type == DYNAMIC_DEFINITION_TYPE.DEFINE_BY_IDENTIFIER: - for s in source_definitions: - data += struct.pack('!H', s.data_identifier) + bytes([s.position, s.memory_size]) - elif dynamic_definition_type == DYNAMIC_DEFINITION_TYPE.DEFINE_BY_MEMORY_ADDRESS: - data += bytes([memory_size_bytes << 4 | memory_address_bytes]) - for s in source_definitions: - if s.memory_address >= 1 << (memory_address_bytes * 8): - raise ValueError(f'invalid memory_address: {s.memory_address}') - data += struct.pack('!I', s.memory_address)[4 - memory_address_bytes:] - if s.memory_size >= 1 << (memory_size_bytes * 8): - raise ValueError(f'invalid memory_size: {s.memory_size}') - data += struct.pack('!I', s.memory_size)[4 - memory_size_bytes:] - elif dynamic_definition_type == DYNAMIC_DEFINITION_TYPE.CLEAR_DYNAMICALLY_DEFINED_DATA_IDENTIFIER: - pass - else: - raise ValueError(f'invalid dynamic identifier type: {hex(dynamic_definition_type)}') - self._uds_request(SERVICE_TYPE.DYNAMICALLY_DEFINE_DATA_IDENTIFIER, subfunction=dynamic_definition_type, data=data) - - def write_data_by_identifier(self, data_identifier_type: DATA_IDENTIFIER_TYPE, data_record: bytes): - data = struct.pack('!H', data_identifier_type) + data_record - resp = self._uds_request(SERVICE_TYPE.WRITE_DATA_BY_IDENTIFIER, subfunction=None, data=data) - resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None - if resp_id != data_identifier_type: - raise ValueError(f'invalid response data identifier: {hex(resp_id)}') - - def write_memory_by_address(self, memory_address: int, memory_size: int, data_record: bytes, memory_address_bytes: int = 4, memory_size_bytes: int = 1): - if memory_address_bytes < 1 or memory_address_bytes > 4: - raise ValueError(f'invalid memory_address_bytes: {memory_address_bytes}') - if memory_size_bytes < 1 or memory_size_bytes > 4: - raise ValueError(f'invalid memory_size_bytes: {memory_size_bytes}') - data = bytes([memory_size_bytes << 4 | memory_address_bytes]) - - if memory_address >= 1 << (memory_address_bytes * 8): - raise ValueError(f'invalid memory_address: {memory_address}') - data += struct.pack('!I', memory_address)[4 - memory_address_bytes:] - if memory_size >= 1 << (memory_size_bytes * 8): - raise ValueError(f'invalid memory_size: {memory_size}') - data += struct.pack('!I', memory_size)[4 - memory_size_bytes:] - - data += data_record - self._uds_request(SERVICE_TYPE.WRITE_MEMORY_BY_ADDRESS, subfunction=None, data=data) - - def clear_diagnostic_information(self, dtc_group_type: DTC_GROUP_TYPE): - data = struct.pack('!I', dtc_group_type)[1:] # 3 bytes - self._uds_request(SERVICE_TYPE.CLEAR_DIAGNOSTIC_INFORMATION, subfunction=None, data=data) - - def read_dtc_information(self, dtc_report_type: DTC_REPORT_TYPE, dtc_status_mask_type: DTC_STATUS_MASK_TYPE = DTC_STATUS_MASK_TYPE.ALL, - dtc_severity_mask_type: DTC_SEVERITY_MASK_TYPE = DTC_SEVERITY_MASK_TYPE.ALL, dtc_mask_record: int = 0xFFFFFF, - dtc_snapshot_record_num: int = 0xFF, dtc_extended_record_num: int = 0xFF): - data = b'' - # dtc_status_mask_type - if dtc_report_type == DTC_REPORT_TYPE.NUMBER_OF_DTC_BY_STATUS_MASK or \ - dtc_report_type == DTC_REPORT_TYPE.DTC_BY_STATUS_MASK or \ - dtc_report_type == DTC_REPORT_TYPE.MIRROR_MEMORY_DTC_BY_STATUS_MASK or \ - dtc_report_type == DTC_REPORT_TYPE.NUMBER_OF_MIRROR_MEMORY_DTC_BY_STATUS_MASK or \ - dtc_report_type == DTC_REPORT_TYPE.NUMBER_OF_EMISSIONS_RELATED_OBD_DTC_BY_STATUS_MASK or \ - dtc_report_type == DTC_REPORT_TYPE.EMISSIONS_RELATED_OBD_DTC_BY_STATUS_MASK: - data += bytes([dtc_status_mask_type]) - # dtc_mask_record - if dtc_report_type == DTC_REPORT_TYPE.DTC_SNAPSHOT_IDENTIFICATION or \ - dtc_report_type == DTC_REPORT_TYPE.DTC_SNAPSHOT_RECORD_BY_DTC_NUMBER or \ - dtc_report_type == DTC_REPORT_TYPE.DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER or \ - dtc_report_type == DTC_REPORT_TYPE.MIRROR_MEMORY_DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER or \ - dtc_report_type == DTC_REPORT_TYPE.SEVERITY_INFORMATION_OF_DTC: - data += struct.pack('!I', dtc_mask_record)[1:] # 3 bytes - # dtc_snapshot_record_num - if dtc_report_type == DTC_REPORT_TYPE.DTC_SNAPSHOT_IDENTIFICATION or \ - dtc_report_type == DTC_REPORT_TYPE.DTC_SNAPSHOT_RECORD_BY_DTC_NUMBER or \ - dtc_report_type == DTC_REPORT_TYPE.DTC_SNAPSHOT_RECORD_BY_RECORD_NUMBER: - data += bytes([dtc_snapshot_record_num]) - # dtc_extended_record_num - if dtc_report_type == DTC_REPORT_TYPE.DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER or \ - dtc_report_type == DTC_REPORT_TYPE.MIRROR_MEMORY_DTC_EXTENDED_DATA_RECORD_BY_DTC_NUMBER: - data += bytes([dtc_extended_record_num]) - # dtc_severity_mask_type - 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 - return resp - - def input_output_control_by_identifier(self, data_identifier_type: DATA_IDENTIFIER_TYPE, control_parameter_type: CONTROL_PARAMETER_TYPE, - control_option_record: bytes = b'', control_enable_mask_record: bytes = b''): - data = struct.pack('!H', data_identifier_type) + bytes([control_parameter_type]) + control_option_record + control_enable_mask_record - resp = self._uds_request(SERVICE_TYPE.INPUT_OUTPUT_CONTROL_BY_IDENTIFIER, subfunction=None, data=data) - resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None - if resp_id != data_identifier_type: - raise ValueError(f'invalid response data identifier: {hex(resp_id)}') - return resp[2:] - - def routine_control(self, routine_control_type: ROUTINE_CONTROL_TYPE, routine_identifier_type: ROUTINE_IDENTIFIER_TYPE, routine_option_record: bytes = b''): - data = struct.pack('!H', routine_identifier_type) + routine_option_record - resp = self._uds_request(SERVICE_TYPE.ROUTINE_CONTROL, subfunction=routine_control_type, data=data) - resp_id = struct.unpack('!H', resp[0:2])[0] if len(resp) >= 2 else None - if resp_id != routine_identifier_type: - raise ValueError(f'invalid response routine identifier: {hex(resp_id)}') - return resp[2:] - - def request_download(self, memory_address: int, memory_size: int, memory_address_bytes: int = 4, memory_size_bytes: int = 4, data_format: int = 0x00): - data = bytes([data_format]) - - if memory_address_bytes < 1 or memory_address_bytes > 4: - raise ValueError(f'invalid memory_address_bytes: {memory_address_bytes}') - if memory_size_bytes < 1 or memory_size_bytes > 4: - raise ValueError(f'invalid memory_size_bytes: {memory_size_bytes}') - data += bytes([memory_size_bytes << 4 | memory_address_bytes]) - - if memory_address >= 1 << (memory_address_bytes * 8): - raise ValueError(f'invalid memory_address: {memory_address}') - data += struct.pack('!I', memory_address)[4 - memory_address_bytes:] - if memory_size >= 1 << (memory_size_bytes * 8): - raise ValueError(f'invalid memory_size: {memory_size}') - data += struct.pack('!I', memory_size)[4 - memory_size_bytes:] - - resp = self._uds_request(SERVICE_TYPE.REQUEST_DOWNLOAD, subfunction=None, data=data) - max_num_bytes_len = resp[0] >> 4 if len(resp) > 0 else 0 - if max_num_bytes_len >= 1 and max_num_bytes_len <= 4: - max_num_bytes = struct.unpack('!I', (b"\x00" * (4 - max_num_bytes_len)) + resp[1:max_num_bytes_len + 1])[0] - else: - raise ValueError(f'invalid max_num_bytes_len: {max_num_bytes_len}') - - return max_num_bytes # max number of bytes per transfer data request - - def request_upload(self, memory_address: int, memory_size: int, memory_address_bytes: int = 4, memory_size_bytes: int = 4, data_format: int = 0x00): - data = bytes([data_format]) - - if memory_address_bytes < 1 or memory_address_bytes > 4: - raise ValueError(f'invalid memory_address_bytes: {memory_address_bytes}') - if memory_size_bytes < 1 or memory_size_bytes > 4: - raise ValueError(f'invalid memory_size_bytes: {memory_size_bytes}') - data += bytes([memory_size_bytes << 4 | memory_address_bytes]) - - if memory_address >= 1 << (memory_address_bytes * 8): - raise ValueError(f'invalid memory_address: {memory_address}') - data += struct.pack('!I', memory_address)[4 - memory_address_bytes:] - if memory_size >= 1 << (memory_size_bytes * 8): - raise ValueError(f'invalid memory_size: {memory_size}') - data += struct.pack('!I', memory_size)[4 - memory_size_bytes:] - - resp = self._uds_request(SERVICE_TYPE.REQUEST_UPLOAD, subfunction=None, data=data) - max_num_bytes_len = resp[0] >> 4 if len(resp) > 0 else 0 - if max_num_bytes_len >= 1 and max_num_bytes_len <= 4: - max_num_bytes = struct.unpack('!I', (b"\x00" * (4 - max_num_bytes_len)) + resp[1:max_num_bytes_len + 1])[0] - else: - raise ValueError(f'invalid max_num_bytes_len: {max_num_bytes_len}') - - return max_num_bytes # max number of bytes per transfer data request - - def transfer_data(self, block_sequence_count: int, data: bytes = b''): - data = bytes([block_sequence_count]) + data - resp = self._uds_request(SERVICE_TYPE.TRANSFER_DATA, subfunction=None, data=data) - resp_id = resp[0] if len(resp) > 0 else None - if resp_id != block_sequence_count: - raise ValueError(f'invalid block_sequence_count: {resp_id}') - return resp[1:] - - def request_transfer_exit(self): - self._uds_request(SERVICE_TYPE.REQUEST_TRANSFER_EXIT, subfunction=None) diff --git a/tests/hitl/2_health.py b/tests/hitl/2_health.py index 12c75f561d..03a065bba5 100644 --- a/tests/hitl/2_health.py +++ b/tests/hitl/2_health.py @@ -1,6 +1,7 @@ import time import pytest +from opendbc.car.hyundai.values import HyundaiPandaFlags from panda import Panda @@ -36,10 +37,10 @@ def test_hw_type(p): def test_heartbeat(p, panda_jungle): panda_jungle.set_ignition(True) # TODO: add more cases here once the tests aren't super slow - p.set_safety_mode(mode=Panda.SAFETY_HYUNDAI, param=Panda.FLAG_HYUNDAI_LONG) + p.set_safety_mode(mode=Panda.SAFETY_HYUNDAI, param=HyundaiPandaFlags.FLAG_HYUNDAI_LONG) p.send_heartbeat() assert p.health()['safety_mode'] == Panda.SAFETY_HYUNDAI - assert p.health()['safety_param'] == Panda.FLAG_HYUNDAI_LONG + assert p.health()['safety_param'] == HyundaiPandaFlags.FLAG_HYUNDAI_LONG # shouldn't do anything once we're in a car safety mode p.set_heartbeat_disabled() diff --git a/tests/safety/test_chrysler.py b/tests/safety/test_chrysler.py index 5bbb6dd103..24ee934de3 100755 --- a/tests/safety/test_chrysler.py +++ b/tests/safety/test_chrysler.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 import unittest + +from opendbc.car.chrysler.values import ChryslerPandaFlags from panda import Panda from panda.tests.libpanda import libpanda_py import panda.tests.safety.common as common @@ -89,7 +91,7 @@ class TestChryslerRamDTSafety(TestChryslerSafety): def setUp(self): self.packer = CANPackerPanda("chrysler_ram_dt_generated") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_CHRYSLER, Panda.FLAG_CHRYSLER_RAM_DT) + self.safety.set_safety_hooks(Panda.SAFETY_CHRYSLER, ChryslerPandaFlags.FLAG_CHRYSLER_RAM_DT) self.safety.init_tests() def _speed_msg(self, speed): @@ -113,7 +115,7 @@ class TestChryslerRamHDSafety(TestChryslerSafety): def setUp(self): self.packer = CANPackerPanda("chrysler_ram_hd_generated") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_CHRYSLER, Panda.FLAG_CHRYSLER_RAM_HD) + self.safety.set_safety_hooks(Panda.SAFETY_CHRYSLER, ChryslerPandaFlags.FLAG_CHRYSLER_RAM_HD) self.safety.init_tests() def _speed_msg(self, speed): diff --git a/tests/safety/test_ford.py b/tests/safety/test_ford.py index a97e26430b..0bccfc864d 100755 --- a/tests/safety/test_ford.py +++ b/tests/safety/test_ford.py @@ -4,6 +4,7 @@ import unittest import panda.tests.safety.common as common +from opendbc.car.ford.values import FordPandaFlags from panda import Panda from panda.tests.libpanda import libpanda_py @@ -381,7 +382,7 @@ class TestFordCANFDStockSafety(TestFordSafetyBase): def setUp(self): self.packer = CANPackerPanda("ford_lincoln_base_pt") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_FORD, Panda.FLAG_FORD_CANFD) + self.safety.set_safety_hooks(Panda.SAFETY_FORD, FordPandaFlags.FLAG_FORD_CANFD) self.safety.init_tests() @@ -457,7 +458,7 @@ class TestFordLongitudinalSafety(TestFordLongitudinalSafetyBase): def setUp(self): self.packer = CANPackerPanda("ford_lincoln_base_pt") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_FORD, Panda.FLAG_FORD_LONG_CONTROL) + self.safety.set_safety_hooks(Panda.SAFETY_FORD, FordPandaFlags.FLAG_FORD_LONG_CONTROL) self.safety.init_tests() @@ -472,7 +473,7 @@ class TestFordCANFDLongitudinalSafety(TestFordLongitudinalSafetyBase): def setUp(self): self.packer = CANPackerPanda("ford_lincoln_base_pt") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_FORD, Panda.FLAG_FORD_LONG_CONTROL | Panda.FLAG_FORD_CANFD) + self.safety.set_safety_hooks(Panda.SAFETY_FORD, FordPandaFlags.FLAG_FORD_LONG_CONTROL | FordPandaFlags.FLAG_FORD_CANFD) self.safety.init_tests() diff --git a/tests/safety/test_gm.py b/tests/safety/test_gm.py index c6c5ac6b3a..aa83fdafe7 100755 --- a/tests/safety/test_gm.py +++ b/tests/safety/test_gm.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 import unittest + +from opendbc.car.gm.values import GMPandaFlags from panda import Panda from panda.tests.libpanda import libpanda_py import panda.tests.safety.common as common @@ -187,7 +189,7 @@ def setUp(self): self.packer = CANPackerPanda("gm_global_a_powertrain_generated") self.packer_chassis = CANPackerPanda("gm_global_a_chassis") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_GM, Panda.FLAG_GM_HW_CAM) + self.safety.set_safety_hooks(Panda.SAFETY_GM, GMPandaFlags.FLAG_GM_HW_CAM) self.safety.init_tests() def test_buttons(self): @@ -219,7 +221,7 @@ def setUp(self): self.packer = CANPackerPanda("gm_global_a_powertrain_generated") self.packer_chassis = CANPackerPanda("gm_global_a_chassis") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_GM, Panda.FLAG_GM_HW_CAM | Panda.FLAG_GM_HW_CAM_LONG) + self.safety.set_safety_hooks(Panda.SAFETY_GM, GMPandaFlags.FLAG_GM_HW_CAM | GMPandaFlags.FLAG_GM_HW_CAM_LONG) self.safety.init_tests() diff --git a/tests/safety/test_honda.py b/tests/safety/test_honda.py index 082199c02b..08b6eb4111 100755 --- a/tests/safety/test_honda.py +++ b/tests/safety/test_honda.py @@ -2,6 +2,7 @@ import unittest import numpy as np +from opendbc.car.honda.values import HondaPandaFlags from panda import Panda from panda.tests.libpanda import libpanda_py import panda.tests.safety.common as common @@ -357,7 +358,7 @@ class TestHondaNidecPcmAltSafety(TestHondaNidecPcmSafety): def setUp(self): self.packer = CANPackerPanda("acura_ilx_2016_can_generated") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_HONDA_NIDEC, Panda.FLAG_HONDA_NIDEC_ALT) + self.safety.set_safety_hooks(Panda.SAFETY_HONDA_NIDEC, HondaPandaFlags.FLAG_HONDA_NIDEC_ALT) self.safety.init_tests() def _acc_state_msg(self, main_on): @@ -422,7 +423,7 @@ class TestHondaBoschAltBrakeSafetyBase(TestHondaBoschSafetyBase): """ def setUp(self): super().setUp() - self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH, Panda.FLAG_HONDA_ALT_BRAKE) + self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH, HondaPandaFlags.FLAG_HONDA_ALT_BRAKE) self.safety.init_tests() def _user_brake_msg(self, brake): @@ -471,7 +472,7 @@ class TestHondaBoschLongSafety(HondaButtonEnableBase, TestHondaBoschSafetyBase): def setUp(self): super().setUp() - self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH, Panda.FLAG_HONDA_BOSCH_LONG) + self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH, HondaPandaFlags.FLAG_HONDA_BOSCH_LONG) self.safety.init_tests() def _send_gas_brake_msg(self, gas, accel): @@ -531,7 +532,7 @@ class TestHondaBoschRadarlessSafety(HondaPcmEnableBase, TestHondaBoschRadarlessS def setUp(self): super().setUp() - self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH, Panda.FLAG_HONDA_RADARLESS) + self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH, HondaPandaFlags.FLAG_HONDA_RADARLESS) self.safety.init_tests() @@ -542,7 +543,7 @@ class TestHondaBoschRadarlessAltBrakeSafety(HondaPcmEnableBase, TestHondaBoschRa def setUp(self): super().setUp() - self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH, Panda.FLAG_HONDA_RADARLESS | Panda.FLAG_HONDA_ALT_BRAKE) + self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH, HondaPandaFlags.FLAG_HONDA_RADARLESS | HondaPandaFlags.FLAG_HONDA_ALT_BRAKE) self.safety.init_tests() @@ -556,7 +557,7 @@ class TestHondaBoschRadarlessLongSafety(common.LongitudinalAccelSafetyTest, Hond def setUp(self): super().setUp() - self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH, Panda.FLAG_HONDA_RADARLESS | Panda.FLAG_HONDA_BOSCH_LONG) + self.safety.set_safety_hooks(Panda.SAFETY_HONDA_BOSCH, HondaPandaFlags.FLAG_HONDA_RADARLESS | HondaPandaFlags.FLAG_HONDA_BOSCH_LONG) self.safety.init_tests() def _accel_msg(self, accel): diff --git a/tests/safety/test_hyundai.py b/tests/safety/test_hyundai.py index 1bff99fa75..51386563d3 100755 --- a/tests/safety/test_hyundai.py +++ b/tests/safety/test_hyundai.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 import random import unittest + +from opendbc.car.hyundai.values import HyundaiPandaFlags from panda import Panda from panda.tests.libpanda import libpanda_py import panda.tests.safety.common as common @@ -121,7 +123,7 @@ class TestHyundaiSafetyAltLimits(TestHyundaiSafety): def setUp(self): self.packer = CANPackerPanda("hyundai_kia_generic") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI, Panda.FLAG_HYUNDAI_ALT_LIMITS) + self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI, HyundaiPandaFlags.FLAG_HYUNDAI_ALT_LIMITS) self.safety.init_tests() @@ -132,7 +134,7 @@ class TestHyundaiSafetyCameraSCC(TestHyundaiSafety): def setUp(self): self.packer = CANPackerPanda("hyundai_kia_generic") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI, Panda.FLAG_HYUNDAI_CAMERA_SCC) + self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI, HyundaiPandaFlags.FLAG_HYUNDAI_CAMERA_SCC) self.safety.init_tests() @@ -178,7 +180,7 @@ class TestHyundaiLongitudinalSafety(HyundaiLongitudinalBase, TestHyundaiSafety): def setUp(self): self.packer = CANPackerPanda("hyundai_kia_generic") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI, Panda.FLAG_HYUNDAI_LONG) + self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI, HyundaiPandaFlags.FLAG_HYUNDAI_LONG) self.safety.init_tests() def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): diff --git a/tests/safety/test_hyundai_canfd.py b/tests/safety/test_hyundai_canfd.py index 7f280b6319..ef6b4ee9a0 100755 --- a/tests/safety/test_hyundai_canfd.py +++ b/tests/safety/test_hyundai_canfd.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 from parameterized import parameterized_class import unittest + +from opendbc.car.hyundai.values import HyundaiPandaFlags from panda import Panda from panda.tests.libpanda import libpanda_py import panda.tests.safety.common as common @@ -107,13 +109,13 @@ def setUp(self): @parameterized_class([ # Radar SCC, test with long flag to ensure flag is not respected until it is supported - {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 0, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_LONG}, - {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_EV_GAS | Panda.FLAG_HYUNDAI_LONG}, - {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_HYBRID_GAS | Panda.FLAG_HYUNDAI_LONG}, + {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_LONG}, + {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_EV_GAS | HyundaiPandaFlags.FLAG_HYUNDAI_LONG}, + {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_HYBRID_GAS | HyundaiPandaFlags.FLAG_HYUNDAI_LONG}, # Camera SCC - {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 2, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_CAMERA_SCC}, - {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_EV_GAS | Panda.FLAG_HYUNDAI_CAMERA_SCC}, - {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_HYBRID_GAS | Panda.FLAG_HYUNDAI_CAMERA_SCC}, + {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_CAMERA_SCC}, + {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_EV_GAS | HyundaiPandaFlags.FLAG_HYUNDAI_CAMERA_SCC}, + {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_HYBRID_GAS | HyundaiPandaFlags.FLAG_HYUNDAI_CAMERA_SCC}, ]) class TestHyundaiCanfdHDA1(TestHyundaiCanfdHDA1Base): pass @@ -121,13 +123,13 @@ class TestHyundaiCanfdHDA1(TestHyundaiCanfdHDA1Base): @parameterized_class([ # Radar SCC, test with long flag to ensure flag is not respected until it is supported - {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 0, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_LONG}, - {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_EV_GAS | Panda.FLAG_HYUNDAI_LONG}, - {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_HYBRID_GAS | Panda.FLAG_HYUNDAI_LONG}, + {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_LONG}, + {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_EV_GAS | HyundaiPandaFlags.FLAG_HYUNDAI_LONG}, + {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 0, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_HYBRID_GAS | HyundaiPandaFlags.FLAG_HYUNDAI_LONG}, # Camera SCC - {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 2, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_CAMERA_SCC}, - {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_EV_GAS | Panda.FLAG_HYUNDAI_CAMERA_SCC}, - {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": Panda.FLAG_HYUNDAI_HYBRID_GAS | Panda.FLAG_HYUNDAI_CAMERA_SCC}, + {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_CAMERA_SCC}, + {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_EV_GAS | HyundaiPandaFlags.FLAG_HYUNDAI_CAMERA_SCC}, + {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SCC_BUS": 2, "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_HYBRID_GAS | HyundaiPandaFlags.FLAG_HYUNDAI_CAMERA_SCC}, ]) class TestHyundaiCanfdHDA1AltButtons(TestHyundaiCanfdHDA1Base): @@ -136,7 +138,7 @@ class TestHyundaiCanfdHDA1AltButtons(TestHyundaiCanfdHDA1Base): def setUp(self): self.packer = CANPackerPanda("hyundai_canfd") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, Panda.FLAG_HYUNDAI_CANFD_ALT_BUTTONS | self.SAFETY_PARAM) + self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, HyundaiPandaFlags.FLAG_HYUNDAI_CANFD_ALT_BUTTONS | self.SAFETY_PARAM) self.safety.init_tests() def _button_msg(self, buttons, main_button=0, bus=1): @@ -171,7 +173,7 @@ class TestHyundaiCanfdHDA2EV(TestHyundaiCanfdBase): def setUp(self): self.packer = CANPackerPanda("hyundai_canfd") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, Panda.FLAG_HYUNDAI_CANFD_HDA2 | Panda.FLAG_HYUNDAI_EV_GAS) + self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, HyundaiPandaFlags.FLAG_HYUNDAI_CANFD_HDA2 | HyundaiPandaFlags.FLAG_HYUNDAI_EV_GAS) self.safety.init_tests() @@ -191,8 +193,8 @@ class TestHyundaiCanfdHDA2EVAltSteering(TestHyundaiCanfdBase): def setUp(self): self.packer = CANPackerPanda("hyundai_canfd") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, Panda.FLAG_HYUNDAI_CANFD_HDA2 | Panda.FLAG_HYUNDAI_EV_GAS | - Panda.FLAG_HYUNDAI_CANFD_HDA2_ALT_STEERING) + self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, HyundaiPandaFlags.FLAG_HYUNDAI_CANFD_HDA2 | HyundaiPandaFlags.FLAG_HYUNDAI_EV_GAS | + HyundaiPandaFlags.FLAG_HYUNDAI_CANFD_HDA2_ALT_STEERING) self.safety.init_tests() @@ -213,7 +215,7 @@ class TestHyundaiCanfdHDA2LongEV(HyundaiLongitudinalBase, TestHyundaiCanfdHDA2EV def setUp(self): self.packer = CANPackerPanda("hyundai_canfd") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, Panda.FLAG_HYUNDAI_CANFD_HDA2 | Panda.FLAG_HYUNDAI_LONG | Panda.FLAG_HYUNDAI_EV_GAS) + self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, HyundaiPandaFlags.FLAG_HYUNDAI_CANFD_HDA2 | HyundaiPandaFlags.FLAG_HYUNDAI_LONG | HyundaiPandaFlags.FLAG_HYUNDAI_EV_GAS) self.safety.init_tests() def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): @@ -227,9 +229,9 @@ def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): # Tests HDA1 longitudinal for ICE, hybrid, EV @parameterized_class([ # Camera SCC is the only supported configuration for HDA1 longitudinal, TODO: allow radar SCC - {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SAFETY_PARAM": Panda.FLAG_HYUNDAI_LONG}, - {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SAFETY_PARAM": Panda.FLAG_HYUNDAI_LONG | Panda.FLAG_HYUNDAI_EV_GAS}, - {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SAFETY_PARAM": Panda.FLAG_HYUNDAI_LONG | Panda.FLAG_HYUNDAI_HYBRID_GAS}, + {"GAS_MSG": ("ACCELERATOR_BRAKE_ALT", "ACCELERATOR_PEDAL_PRESSED"), "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_LONG}, + {"GAS_MSG": ("ACCELERATOR", "ACCELERATOR_PEDAL"), "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_LONG | HyundaiPandaFlags.FLAG_HYUNDAI_EV_GAS}, + {"GAS_MSG": ("ACCELERATOR_ALT", "ACCELERATOR_PEDAL"), "SAFETY_PARAM": HyundaiPandaFlags.FLAG_HYUNDAI_LONG | HyundaiPandaFlags.FLAG_HYUNDAI_HYBRID_GAS}, ]) class TestHyundaiCanfdHDA1Long(HyundaiLongitudinalBase, TestHyundaiCanfdHDA1Base): @@ -253,7 +255,7 @@ def setUpClass(cls): def setUp(self): self.packer = CANPackerPanda("hyundai_canfd") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, Panda.FLAG_HYUNDAI_CAMERA_SCC | self.SAFETY_PARAM) + self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, HyundaiPandaFlags.FLAG_HYUNDAI_CAMERA_SCC | self.SAFETY_PARAM) self.safety.init_tests() def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): diff --git a/tests/safety/test_nissan.py b/tests/safety/test_nissan.py index 4c83ca329e..c5dda2cca9 100755 --- a/tests/safety/test_nissan.py +++ b/tests/safety/test_nissan.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 import unittest + +from opendbc.car.nissan.values import NissanPandaFlags from panda import Panda from panda.tests.libpanda import libpanda_py import panda.tests.safety.common as common @@ -88,7 +90,7 @@ class TestNissanSafetyAltEpsBus(TestNissanSafety): def setUp(self): self.packer = CANPackerPanda("nissan_x_trail_2017_generated") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_NISSAN, Panda.FLAG_NISSAN_ALT_EPS_BUS) + self.safety.set_safety_hooks(Panda.SAFETY_NISSAN, NissanPandaFlags.FLAG_NISSAN_ALT_EPS_BUS) self.safety.init_tests() diff --git a/tests/safety/test_subaru.py b/tests/safety/test_subaru.py index 7d07f79aaf..2afbfe92fb 100755 --- a/tests/safety/test_subaru.py +++ b/tests/safety/test_subaru.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 import enum import unittest + +from opendbc.car.subaru.values import SubaruPandaFlags from panda import Panda from panda.tests.libpanda import libpanda_py import panda.tests.safety.common as common @@ -182,17 +184,17 @@ class TestSubaruGen2TorqueSafetyBase(TestSubaruTorqueSafetyBase): class TestSubaruGen2TorqueStockLongitudinalSafety(TestSubaruStockLongitudinalSafetyBase, TestSubaruGen2TorqueSafetyBase): - FLAGS = Panda.FLAG_SUBARU_GEN2 + FLAGS = SubaruPandaFlags.FLAG_SUBARU_GEN2 TX_MSGS = lkas_tx_msgs(SUBARU_ALT_BUS) class TestSubaruGen1LongitudinalSafety(TestSubaruLongitudinalSafetyBase, TestSubaruTorqueSafetyBase): - FLAGS = Panda.FLAG_SUBARU_LONG + FLAGS = SubaruPandaFlags.FLAG_SUBARU_LONG TX_MSGS = lkas_tx_msgs(SUBARU_MAIN_BUS) + long_tx_msgs(SUBARU_MAIN_BUS) class TestSubaruGen2LongitudinalSafety(TestSubaruLongitudinalSafetyBase, TestSubaruGen2TorqueSafetyBase): - FLAGS = Panda.FLAG_SUBARU_LONG | Panda.FLAG_SUBARU_GEN2 + FLAGS = SubaruPandaFlags.FLAG_SUBARU_LONG | SubaruPandaFlags.FLAG_SUBARU_GEN2 TX_MSGS = lkas_tx_msgs(SUBARU_ALT_BUS) + long_tx_msgs(SUBARU_ALT_BUS) + gen2_long_additional_tx_msgs() def _rdbi_msg(self, did: int): diff --git a/tests/safety/test_subaru_preglobal.py b/tests/safety/test_subaru_preglobal.py index 06c4cdefc8..c555a34df6 100755 --- a/tests/safety/test_subaru_preglobal.py +++ b/tests/safety/test_subaru_preglobal.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 import unittest + +from opendbc.car.subaru.values import SubaruPandaFlags from panda import Panda from panda.tests.libpanda import libpanda_py import panda.tests.safety.common as common @@ -62,7 +64,7 @@ def _pcm_status_msg(self, enable): class TestSubaruPreglobalReversedDriverTorqueSafety(TestSubaruPreglobalSafety): - FLAGS = Panda.FLAG_SUBARU_PREGLOBAL_REVERSED_DRIVER_TORQUE + FLAGS = SubaruPandaFlags.FLAG_SUBARU_PREGLOBAL_REVERSED_DRIVER_TORQUE DBC = "subaru_outback_2019_generated" diff --git a/tests/safety/test_tesla.py b/tests/safety/test_tesla.py index 9461ff68f9..f26c346d46 100755 --- a/tests/safety/test_tesla.py +++ b/tests/safety/test_tesla.py @@ -1,6 +1,8 @@ #!/usr/bin/env python3 import unittest import numpy as np + +from opendbc.car.tesla.values import TeslaPandaFlags from panda import Panda import panda.tests.safety.common as common from panda.tests.libpanda import libpanda_py @@ -112,7 +114,7 @@ class TestTeslaRavenSteeringSafety(TestTeslaSteeringSafety): def setUp(self): self.packer = CANPackerPanda("tesla_can") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_TESLA, Panda.FLAG_TESLA_RAVEN) + self.safety.set_safety_hooks(Panda.SAFETY_TESLA, TeslaPandaFlags.FLAG_TESLA_RAVEN) self.safety.init_tests() def _angle_meas_msg(self, angle: float): @@ -165,7 +167,7 @@ class TestTeslaChassisLongitudinalSafety(TestTeslaLongitudinalSafety): def setUp(self): self.packer = CANPackerPanda("tesla_can") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_TESLA, Panda.FLAG_TESLA_LONG_CONTROL) + self.safety.set_safety_hooks(Panda.SAFETY_TESLA, TeslaPandaFlags.FLAG_TESLA_LONG_CONTROL) self.safety.init_tests() @@ -177,7 +179,7 @@ class TestTeslaPTLongitudinalSafety(TestTeslaLongitudinalSafety): def setUp(self): self.packer = CANPackerPanda("tesla_powertrain") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_TESLA, Panda.FLAG_TESLA_LONG_CONTROL | Panda.FLAG_TESLA_POWERTRAIN) + self.safety.set_safety_hooks(Panda.SAFETY_TESLA, TeslaPandaFlags.FLAG_TESLA_LONG_CONTROL | TeslaPandaFlags.FLAG_TESLA_POWERTRAIN) self.safety.init_tests() diff --git a/tests/safety/test_toyota.py b/tests/safety/test_toyota.py index e60b29c5c2..a8200d61b7 100755 --- a/tests/safety/test_toyota.py +++ b/tests/safety/test_toyota.py @@ -4,6 +4,7 @@ import unittest import itertools +from opendbc.car.toyota.values import ToyotaPandaFlags from panda import Panda from panda.tests.libpanda import libpanda_py import panda.tests.safety.common as common @@ -166,7 +167,7 @@ class TestToyotaSafetyAngle(TestToyotaSafetyBase, common.AngleSteeringSafetyTest def setUp(self): self.packer = CANPackerPanda("toyota_nodsu_pt_generated") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_TOYOTA, self.EPS_SCALE | Panda.FLAG_TOYOTA_LTA) + self.safety.set_safety_hooks(Panda.SAFETY_TOYOTA, self.EPS_SCALE | ToyotaPandaFlags.FLAG_TOYOTA_LTA) self.safety.init_tests() # Only allow LKA msgs with no actuation @@ -268,7 +269,7 @@ class TestToyotaAltBrakeSafety(TestToyotaSafetyTorque): def setUp(self): self.packer = CANPackerPanda("toyota_new_mc_pt_generated") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_TOYOTA, self.EPS_SCALE | Panda.FLAG_TOYOTA_ALT_BRAKE) + self.safety.set_safety_hooks(Panda.SAFETY_TOYOTA, self.EPS_SCALE | ToyotaPandaFlags.FLAG_TOYOTA_ALT_BRAKE) self.safety.init_tests() def _user_brake_msg(self, brake): @@ -313,7 +314,7 @@ class TestToyotaStockLongitudinalTorque(TestToyotaStockLongitudinalBase, TestToy def setUp(self): self.packer = CANPackerPanda("toyota_nodsu_pt_generated") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_TOYOTA, self.EPS_SCALE | Panda.FLAG_TOYOTA_STOCK_LONGITUDINAL) + self.safety.set_safety_hooks(Panda.SAFETY_TOYOTA, self.EPS_SCALE | ToyotaPandaFlags.FLAG_TOYOTA_STOCK_LONGITUDINAL) self.safety.init_tests() @@ -322,7 +323,7 @@ class TestToyotaStockLongitudinalAngle(TestToyotaStockLongitudinalBase, TestToyo def setUp(self): self.packer = CANPackerPanda("toyota_nodsu_pt_generated") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_TOYOTA, self.EPS_SCALE | Panda.FLAG_TOYOTA_STOCK_LONGITUDINAL | Panda.FLAG_TOYOTA_LTA) + self.safety.set_safety_hooks(Panda.SAFETY_TOYOTA, self.EPS_SCALE | ToyotaPandaFlags.FLAG_TOYOTA_STOCK_LONGITUDINAL | ToyotaPandaFlags.FLAG_TOYOTA_LTA) self.safety.init_tests() @@ -335,7 +336,7 @@ class TestToyotaSecOcSafety(TestToyotaStockLongitudinalBase): def setUp(self): self.packer = CANPackerPanda("toyota_rav4_prime_generated") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_TOYOTA, self.EPS_SCALE | Panda.FLAG_TOYOTA_STOCK_LONGITUDINAL | Panda.FLAG_TOYOTA_SECOC) + self.safety.set_safety_hooks(Panda.SAFETY_TOYOTA, self.EPS_SCALE | ToyotaPandaFlags.FLAG_TOYOTA_STOCK_LONGITUDINAL | ToyotaPandaFlags.FLAG_TOYOTA_SECOC) self.safety.init_tests() # This platform also has alternate brake and PCM messages, but same naming in the DBC, so same packers work diff --git a/tests/safety/test_volkswagen_mqb.py b/tests/safety/test_volkswagen_mqb.py index 276ee6c27d..6dd739d792 100755 --- a/tests/safety/test_volkswagen_mqb.py +++ b/tests/safety/test_volkswagen_mqb.py @@ -5,6 +5,7 @@ from panda.tests.libpanda import libpanda_py import panda.tests.safety.common as common from panda.tests.safety.common import CANPackerPanda +from opendbc.car.volkswagen.values import VolkswagenPandaFlags MAX_ACCEL = 2.0 MIN_ACCEL = -3.5 @@ -165,7 +166,7 @@ class TestVolkswagenMqbLongSafety(TestVolkswagenMqbSafety): def setUp(self): self.packer = CANPackerPanda("vw_mqb_2010") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_VOLKSWAGEN_MQB, Panda.FLAG_VOLKSWAGEN_LONG_CONTROL) + self.safety.set_safety_hooks(Panda.SAFETY_VOLKSWAGEN_MQB, VolkswagenPandaFlags.FLAG_VOLKSWAGEN_LONG_CONTROL) self.safety.init_tests() # stock cruise controls are entirely bypassed under openpilot longitudinal control diff --git a/tests/safety/test_volkswagen_pq.py b/tests/safety/test_volkswagen_pq.py index f2bc317868..c557e9a7d3 100755 --- a/tests/safety/test_volkswagen_pq.py +++ b/tests/safety/test_volkswagen_pq.py @@ -1,5 +1,7 @@ #!/usr/bin/env python3 import unittest + +from opendbc.car.volkswagen.values import VolkswagenPandaFlags from panda import Panda from panda.tests.libpanda import libpanda_py import panda.tests.safety.common as common @@ -147,7 +149,7 @@ class TestVolkswagenPqLongSafety(TestVolkswagenPqSafety, common.LongitudinalAcce def setUp(self): self.packer = CANPackerPanda("vw_golf_mk4") self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_VOLKSWAGEN_PQ, Panda.FLAG_VOLKSWAGEN_LONG_CONTROL) + self.safety.set_safety_hooks(Panda.SAFETY_VOLKSWAGEN_PQ, VolkswagenPandaFlags.FLAG_VOLKSWAGEN_LONG_CONTROL) self.safety.init_tests() # stock cruise controls are entirely bypassed under openpilot longitudinal control diff --git a/tests/safety_replay/helpers.py b/tests/safety_replay/helpers.py index a1a6cd3a59..cc4300d5b7 100644 --- a/tests/safety_replay/helpers.py +++ b/tests/safety_replay/helpers.py @@ -1,4 +1,5 @@ import panda.tests.libpanda.libpanda_py as libpanda_py +from opendbc.car.toyota.values import ToyotaPandaFlags from panda import Panda def to_signed(d, bits): @@ -12,7 +13,7 @@ def is_steering_msg(mode, param, addr): if mode in (Panda.SAFETY_HONDA_NIDEC, Panda.SAFETY_HONDA_BOSCH): ret = (addr == 0xE4) or (addr == 0x194) or (addr == 0x33D) or (addr == 0x33DA) or (addr == 0x33DB) elif mode == Panda.SAFETY_TOYOTA: - ret = addr == (0x191 if param & Panda.FLAG_TOYOTA_LTA else 0x2E4) + ret = addr == (0x191 if param & ToyotaPandaFlags.FLAG_TOYOTA_LTA else 0x2E4) elif mode == Panda.SAFETY_GM: ret = addr == 384 elif mode == Panda.SAFETY_HYUNDAI: @@ -33,7 +34,7 @@ def get_steer_value(mode, param, to_send): torque = (to_send.data[0] << 8) | to_send.data[1] torque = to_signed(torque, 16) elif mode == Panda.SAFETY_TOYOTA: - if param & Panda.FLAG_TOYOTA_LTA: + if param & ToyotaPandaFlags.FLAG_TOYOTA_LTA: angle = (to_send.data[1] << 8) | to_send.data[2] angle = to_signed(angle, 16) else: