#include "safety_hyundai_common.h" 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, }; const CanMsg HYUNDAI_CANFD_HDA2_TX_MSGS[] = { {0x50, 0, 16}, // LKAS {0x1CF, 1, 8}, // CRUISE_BUTTON {426, 1, 16}, // CRUISE_BUTTONS_ALT {0x2A4, 0, 24}, // CAM_0x2A4 }; const CanMsg HYUNDAI_CANFD_HDA2_ALT_STEERING_TX_MSGS[] = { {0x110, 0, 32}, // LKAS_ALT {0x1CF, 1, 8}, // CRUISE_BUTTON {426, 1, 16}, // CRUISE_BUTTONS_ALT {0x362, 0, 32}, // CAM_0x362 }; const CanMsg HYUNDAI_CANFD_HDA2_LONG_TX_MSGS[] = { {0x50, 0, 16}, // LKAS {0x1CF, 1, 8}, // CRUISE_BUTTON {426, 1, 16}, // CRUISE_BUTTONS_ALT {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 }; 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 }; // *** 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 }}}, \ #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 }}}, \ // *** Non-HDA2 checks *** // Camera sends SCC messages on HDA1. // Both button messages exist on some platforms, so we ensure we track the correct one using flag RxCheck hyundai_canfd_rx_checks[] = { HYUNDAI_CANFD_COMMON_RX_CHECKS(0) HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0) HYUNDAI_CANFD_SCC_ADDR_CHECK(2) }; 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) }; // Longitudinal checks for HDA1 RxCheck hyundai_canfd_long_rx_checks[] = { HYUNDAI_CANFD_COMMON_RX_CHECKS(0) HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(0) }; RxCheck hyundai_canfd_long_alt_buttons_rx_checks[] = { HYUNDAI_CANFD_COMMON_RX_CHECKS(0) HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(0) }; // Radar sends SCC messages on these cars instead of camera 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) }; 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) }; // *** HDA2 checks *** // E-CAN is on bus 1, ADAS unit sends SCC messages on HDA2. // Does not use the alt buttons message RxCheck hyundai_canfd_hda2_rx_checks[] = { HYUNDAI_CANFD_COMMON_RX_CHECKS(1) HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(1) HYUNDAI_CANFD_SCC_ADDR_CHECK(1) }; RxCheck hyundai_canfd_hda2_long_rx_checks[] = { HYUNDAI_CANFD_COMMON_RX_CHECKS(1) HYUNDAI_CANFD_BUTTONS_ADDR_CHECK(1) }; const int HYUNDAI_PARAM_CANFD_ALT_BUTTONS = 32; const int HYUNDAI_PARAM_CANFD_HDA2_ALT_STEERING = 128; bool hyundai_canfd_alt_buttons = false; bool hyundai_canfd_hda2_alt_steering = false; 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; // Todo: test: // BO_ 1345 CGW1: 8 BCM // SG_ C_SunRoofOpenState : 57|1@1+ (1.0,0.0) [0.0|1.0] "" CLU,DATC,IBOX,DATC,IBOX // BO_ 68 DATC11: 8 DATC // SG_ CR_Datc_OutTempC : 24|8@1+ (0.5,-41.0) [-41.0|86.5] "deg" CLU,FPCM // SG_ CR_Datc_OutTempF : 32|8@1+ (1.0,-42.0) [-42.0|213.0] "deg" CLU // SG_ CF_Datc_IncarTemp : 40|8@1+ (0.5,-40.0) [-40.0|60.0] "deg" BCM,CLU // BO_ 64 DATC14: 8 DATC // SG_ CF_Datc_AqsLevelOut : 0|4@1+ (1.0,0.0) [0.0|3.0] "" CLU // SG_ CF_Datc_DiagMode : 6|2@1+ (1.0,0.0) [0.0|3.0] "" CLU // SG_ CR_Datc_SelfDiagCode : 8|8@1+ (1.0,-1.0) [0.0|254.0] "" CLU // SG_ DATC_SyncDisp : 16|4@1+ (1.0,0.0) [0.0|3.0] "" CLU // SG_ DATC_OffDisp : 20|2@1+ (1.0,0.0) [0.0|3.0] "" CLU // SG_ DATC_SmartVentDisp : 22|2@1+ (1.0,0.0) [0.0|3.0] "" CLU // SG_ DATC_SmartVentOnOffStatus : 24|2@1+ (1.0,0.0) [0.0|3.0] "" CLU // SG_ DATC_AutoDefogSysOff_Disp : 26|2@1+ (1.0,0.0) [0.0|3.0] "" CLU // SG_ DATC_ADSDisp : 28|2@1+ (1.0,0.0) [0.0|3.0] "" CLU // VAL_ 1144 DRIVE_MODE2 3 "Set Sport" 1 "Set Normal" 2 "Set Eco"; // BO_ 1151 HVAC_TOUCH_BUTTONS: 8 XXX // SG_ AUTO_BUTTON : 8|1@0+ (1,0) [0|1] "" XXX // SG_ SYNC_BUTTON : 12|1@0+ (1,0) [0|1] "" XXX // SG_ FR_DEFROST_BUTTON : 20|1@0+ (1,0) [0|1] "" XXX // SG_ RR_DEFROST_BUTTON : 22|1@0+ (1,0) [0|1] "" XXX // SG_ FAN_SPEED_UP_BUTTON : 24|1@0+ (1,0) [0|1] "" XXX // SG_ FAN_SPEED_DOWN_BUTTON : 26|1@0+ (1,0) [0|1] "" XXX // SG_ AIR_DIRECTION_BUTTON : 28|1@0+ (1,0) [0|1] "" XXX // SG_ AC_BUTTON : 40|1@0+ (1,0) [0|1] "" XXX // SG_ DRIVER_ONLY_BUTTON : 44|1@0+ (1,0) [0|1] "" XXX // SG_ RECIRC_BUTTON : 48|1@0+ (1,0) [0|1] "" XXX // SG_ HEAT_BUTTON : 52|1@0+ (1,0) [0|1] "" XXX // BO_ 304 GEAR_SHIFTER: 16 XXX // SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX // SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX // SG_ PARK_BUTTON : 32|2@1+ (1,0) [0|3] "" XXX // SG_ GEAR : 64|3@1+ (1,0) [0|7] "" XXX // SG_ KNOB_POSITION : 40|3@1+ (1,0) [0|3] "" XXX // BO_ 1322 CLU15: 8 CLU // SG_ CF_Clu_VehicleSpeed : 0|8@1+ (1.0,0.0) [0.0|255.0] "" BCM // SG_ CF_Clu_Gear : 9|4@1+ (1,0) [0|15] "" BCM // SG_ CF_Clu_HudInfoSet : 13|7@1+ (1.0,0.0) [0.0|127.0] "" HUD // SG_ CF_Clu_HudFontColorSet : 20|2@1+ (1.0,0.0) [0.0|3.0] "" HUD // SG_ CF_Clu_HudBrightUpSW : 22|2@1+ (1.0,0.0) [0.0|3.0] "" HUD // SG_ CF_Clu_HudBrightDnSW : 24|2@1+ (1.0,0.0) [0.0|3.0] "" HUD // SG_ CF_Clu_HudHeightUpSW : 26|2@1+ (1.0,0.0) [0.0|3.0] "" HUD // SG_ CF_Clu_HudHeightDnSW : 28|2@1+ (1.0,0.0) [0.0|3.0] "" HUD // SG_ CF_Clu_HudSet : 30|1@1+ (1.0,0.0) [0.0|1.0] "" HUD // SG_ CF_Clu_HudFontSizeSet : 31|2@1+ (1.0,0.0) [0.0|3.0] "" HUD // SG_ CF_Clu_LanguageInfo : 33|5@1+ (1.0,0.0) [0.0|31.0] "" BCM,PGS // SG_ CF_Clu_ClusterSound : 38|1@1- (1.0,0.0) [0.0|0.0] "" BCM,CGW,FATC // SG_ CF_Clu_VehicleSpeed2 : 48|8@1+ (1,0) [0|255] "" XXX // BO_ 1292 CLU13: 8 CLU // SG_ CF_Clu_LowfuelWarn : 0|2@1+ (1.0,0.0) [0.0|3.0] "" BCM,FPCM,IBOX // SG_ CF_Clu_RefDetMod : 2|1@1+ (1.0,0.0) [0.0|1.0] "" IBOX // SG_ CF_Clu_AvgFCU : 3|2@1+ (1.0,0.0) [0.0|3.0] "" IBOX // SG_ CF_Clu_AvsmCur : 5|1@1+ (1.0,0.0) [0.0|1.0] "" ESC,SCC // SG_ CF_Clu_AvgFCI : 6|10@1+ (0.1,0.0) [0.0|102.2] "" IBOX // SG_ CF_Clu_DrivingModeSwi : 16|2@1+ (1.0,0.0) [0.0|3.0] "" DATC,ECS,EMS,ESC,IAP,MDPS,TCU // SG_ CF_Clu_FuelDispLvl : 18|5@1+ (1.0,0.0) [0.0|31.0] "" CGW,IBOX // SG_ CF_Clu_FlexSteerSW : 23|1@1+ (1.0,0.0) [0.0|1.0] "" MDPS // SG_ CF_Clu_DTE : 24|10@1+ (1.0,0.0) [0.0|1023.0] "" DATC // SG_ CF_Clu_TripUnit : 34|2@1+ (1.0,0.0) [0.0|3.0] "" DATC // SG_ CF_Clu_SWL_Stat : 36|3@1+ (1.0,0.0) [0.0|7.0] "" ACU,EMS // SG_ CF_Clu_ActiveEcoSW : 39|1@1+ (1.0,0.0) [0.0|1.0] "" DATC,EMS,TCU // SG_ CF_Clu_EcoDriveInf : 40|3@1+ (1.0,0.0) [0.0|7.0] "" CUBIS,EMS,IAP,IBOX // SG_ CF_Clu_IsaMainSW : 43|1@1+ (1.0,0.0) [0.0|1.0] "" EMS // SG_ CF_Clu_LdwsLkasSW : 56|1@1+ (1.0,0.0) [0.0|1.0] "" LDWS_LKAS // SG_ CF_Clu_AltLStatus : 59|1@1+ (1.0,0.0) [0.0|1.0] "" BCM,DATC,EMS // SG_ CF_Clu_AliveCnt2 : 60|4@1+ (1.0,0.0) [0.0|15.0] "" EMS,LDWS_LKAS 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 // todo: allow paddle shifter presses through 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) { 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 /* BO_ 463 CRUISE_BUTTONS: 8 XXX SG_ _CHECKSUM : 0|8@1+ (1,0) [0|65535] "" XXX SG_ LKAS_BTN : 23|1@1+ (1,0) [0|1] "" XXX SG_ SET_ME_1 : 29|1@1+ (1,0) [0|1] "" XXX SG_ ADAPTIVE_CRUISE_MAIN_BTN : 19|1@1+ (1,0) [0|1] "" XXX SG_ NORMAL_CRUISE_MAIN_BTN : 21|1@1+ (1,0) [0|1] "" XXX SG_ COUNTER : 12|4@1+ (1,0) [0|255] "" XXX SG_ CRUISE_BUTTONS : 16|3@1+ (1,0) [0|3] "" XXX */ // Pass all desired buttons for now // 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 is_set = (button == HYUNDAI_BTN_SET); // bool allowed = // (is_cancel && cruise_engaged_prev) || // (is_resume && controls_allowed); // (is_set && controls_allowed) // ; // if (!allowed) { // tx = false; // } // } // 'alt' buttons check /* BO_ 426 CRUISE_BUTTONS_ALT: 16 XXX SG_ CHECKSUM : 0|16@1+ (1,0) [0|65535] "" XXX SG_ COUNTER : 16|8@1+ (1,0) [0|255] "" XXX SG_ NEW_SIGNAL_1 : 24|4@1+ (1,0) [0|15] "" XXX SG_ SET_ME_1 : 28|2@1+ (1,0) [0|3] "" XXX SG_ DISTANCE_UNIT : 30|1@1+ (1,0) [0|1] "" XXX SG_ NEW_SIGNAL_2 : 31|3@1+ (1,0) [0|7] "" XXX SG_ ADAPTIVE_CRUISE_MAIN_BTN : 34|1@1+ (1,0) [0|1] "" XXX SG_ NEW_SIGNAL_3 : 35|1@1+ (1,0) [0|1] "" XXX SG_ LFA_BTN : 39|1@1+ (1,0) [0|1] "" XXX SG_ CRUISE_BUTTONS : 36|3@1+ (1,0) [0|4] "" XXX SG_ NEW_SIGNAL_4 : 40|1@1+ (1,0) [0|1] "" XXX SG_ NORMAL_CRUISE_MAIN_BTN : 41|1@1+ (1,0) [0|1] "" XXX SG_ NEW_SIGNAL_5 : 42|2@1+ (1,0) [0|3] "" XXX SG_ SET_ME_2 : 44|3@1+ (1,0) [0|7] "" XXX SG_ NEW_SIGNAL_6 : 47|1@1+ (1,0) [0|1] "" XXX SG_ BYTE6 : 48|8@1+ (1,0) [0|255] "" XXX SG_ BYTE7 : 56|8@1+ (1,0) [0|255] "" XXX SG_ BYTE8 : 64|8@1+ (1,0) [0|255] "" XXX SG_ BYTE9 : 72|8@1+ (1,0) [0|255] "" XXX SG_ BYTE10 : 80|8@1+ (1,0) [0|255] "" XXX SG_ BYTE11 : 88|8@1+ (1,0) [0|255] "" XXX SG_ BYTE12 : 96|8@1+ (1,0) [0|255] "" XXX SG_ BYTE13 : 104|8@1+ (1,0) [0|255] "" XXX SG_ BYTE14 : 112|8@1+ (1,0) [0|255] "" XXX SG_ BYTE15 : 120|8@1+ (1,0) [0|255] "" XXX */ // HVAC /* BO_ 1151 HVAC_TOUCH_BUTTONS: 8 XXX SG_ AUTO_BUTTON : 8|1@0+ (1,0) [0|1] "" XXX SG_ SYNC_BUTTON : 12|1@0+ (1,0) [0|1] "" XXX SG_ FR_DEFROST_BUTTON : 20|1@0+ (1,0) [0|1] "" XXX SG_ RR_DEFROST_BUTTON : 22|1@0+ (1,0) [0|1] "" XXX SG_ FAN_SPEED_UP_BUTTON : 24|1@0+ (1,0) [0|1] "" XXX SG_ FAN_SPEED_DOWN_BUTTON : 26|1@0+ (1,0) [0|1] "" XXX SG_ AIR_DIRECTION_BUTTON : 28|1@0+ (1,0) [0|1] "" XXX SG_ AC_BUTTON : 40|1@0+ (1,0) [0|1] "" XXX SG_ DRIVER_ONLY_BUTTON : 44|1@0+ (1,0) [0|1] "" XXX SG_ RECIRC_BUTTON : 48|1@0+ (1,0) [0|1] "" XXX SG_ HEAT_BUTTON : 52|1@0+ (1,0) [0|1] "" XXX */ // 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) { 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) { ret = BUILD_SAFETY_CFG(hyundai_canfd_hda2_long_rx_checks, HYUNDAI_CANFD_HDA2_LONG_TX_MSGS); } else { 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) { 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) { 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 { 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, };