From 28a4de1c9eab58fc54da9a539db7f2038d326b51 Mon Sep 17 00:00:00 2001 From: LowkeyNEXT Date: Sun, 19 Jul 2026 17:55:06 -0500 Subject: [PATCH] safety(hyundai): allow EV9 CCNC angle-long messages --- .../opendbc/safety/modes/hyundai_canfd.h | 29 ++++++++++++++++++- .../safety/tests/test_hyundai_canfd.py | 12 ++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h b/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h index bdeeffae8..cb6633b4c 100644 --- a/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h +++ b/opendbc_repo/opendbc/safety/modes/hyundai_canfd.h @@ -61,6 +61,7 @@ static bool hyundai_canfd_alt_buttons = false; static bool hyundai_canfd_lka_steering_alt = false; static bool hyundai_canfd_angle_steering = false; static bool hyundai_ccnc = false; +static bool hyundai_canfd_ccnc_angle_long = false; static bool hyundai_canfd_lka_alt_drive_gear = false; static uint8_t hyundai_canfd_inactive_accel_tx_count = 0U; @@ -237,6 +238,10 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *msg) { const int lfa_angle_active = (msg->data[3] >> 4U) & 0xFU; const bool steer_angle_req = lfa_angle_active == 2; + if (steer_angle_req && hyundai_canfd_ccnc_angle_long && !hyundai_canfd_lka_alt_openpilot_allowed()) { + tx = false; + } + int desired_angle = (((uint32_t)(msg->data[5] & 0x3FU)) << 8) | (uint32_t)msg->data[4]; desired_angle = to_signed(desired_angle, 14); @@ -400,6 +405,24 @@ static safety_config hyundai_canfd_init(uint16_t param) { {0x1DA, 1, 32, .check_relay = false}, // ADRV_0x1da }; + static const CanMsg HYUNDAI_CANFD_CCNC_ANGLE_LONG_TX_MSGS[] = { + HYUNDAI_CANFD_LKA_STEERING_ALT_COMMON_TX_MSGS(0, 1) + HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(1) + HYUNDAI_CANFD_SCC_CONTROL_COMMON_TX_MSGS(1, true) + {0x1BA, 1, 24, .check_relay = false}, // BLINDSPOTS_REAR_CORNERS + {0x1E5, 1, 16, .check_relay = false}, // BLINDSPOTS_FRONT_CORNER_1 + {0x100, 0, 24, .check_relay = false}, // ACCELERATOR_BRAKE_ALT radar heartbeat + {0x730, 1, 8, .check_relay = false}, // tester present for ADAS ECU disable + {0x160, 1, 16, .check_relay = false}, // ADRV_0x160 + {0x161, 1, 32, .check_relay = false}, // CCNC_0x161 + {0x162, 1, 32, .check_relay = false}, // CCNC_0x162 + {0x1EA, 1, 32, .check_relay = false}, // ADRV_0x1ea + {0x200, 1, 8, .check_relay = false}, // ADRV_0x200 + {0x345, 1, 8, .check_relay = false}, // ADRV_0x345 + {0x38C, 1, 32, .check_relay = false}, // CCNC support frame + {0x1DA, 1, 32, .check_relay = false}, // ADRV_0x1da + }; + static const CanMsg HYUNDAI_CANFD_LFA_STEERING_TX_MSGS[] = { HYUNDAI_CANFD_CRUISE_BUTTON_TX_MSGS(2) HYUNDAI_CANFD_LFA_STEERING_COMMON_TX_MSGS(0) @@ -439,6 +462,8 @@ static safety_config hyundai_canfd_init(uint16_t param) { hyundai_canfd_lka_steering_alt = GET_FLAG(param, HYUNDAI_PARAM_CANFD_LKA_STEERING_ALT); hyundai_canfd_angle_steering = GET_FLAG(param, HYUNDAI_PARAM_CANFD_ANGLE_STEERING); hyundai_ccnc = GET_FLAG(param, HYUNDAI_PARAM_CCNC); + hyundai_canfd_ccnc_angle_long = hyundai_longitudinal && hyundai_canfd_lka_steering && + hyundai_canfd_lka_steering_alt && hyundai_canfd_angle_steering && hyundai_ccnc; hyundai_canfd_lka_alt_drive_gear = false; hyundai_canfd_inactive_accel_tx_count = 0U; @@ -458,7 +483,9 @@ static safety_config hyundai_canfd_init(uint16_t param) { } else { SET_RX_CHECKS(hyundai_canfd_lka_steering_long_rx_checks, ret); } - if (hyundai_canfd_lka_steering_alt) { + if (hyundai_canfd_ccnc_angle_long) { + SET_TX_MSGS(HYUNDAI_CANFD_CCNC_ANGLE_LONG_TX_MSGS, ret); + } else if (hyundai_canfd_lka_steering_alt) { SET_TX_MSGS(HYUNDAI_CANFD_LKA_STEERING_ALT_LONG_TX_MSGS, ret); } else { SET_TX_MSGS(HYUNDAI_CANFD_LKA_STEERING_LONG_TX_MSGS, ret); diff --git a/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py b/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py index aa8f09bb9..87d1068d0 100755 --- a/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py +++ b/opendbc_repo/opendbc/safety/tests/test_hyundai_canfd.py @@ -740,6 +740,18 @@ class TestHyundaiCanfdLKASteeringAltAngleLongEV(HyundaiLongitudinalBase, TestHyu self.assertEqual(controls_allowed, self._tx(self._angle_cmd_msg(angle_cmd, True))) self.assertEqual(controls_allowed and angle_cmd == angle_meas, self._tx(self._angle_cmd_msg(angle_cmd, False))) + def test_ccnc_angle_long_tx_messages(self): + self.safety.set_safety_hooks(CarParams.SafetyModel.hyundaiCanfd, self.SAFETY_PARAM | HyundaiSafetyFlags.CCNC) + self.safety.init_tests() + + for address, length in ((0x161, 32), (0x162, 32), (0x1BA, 24), (0x1E5, 16), (0x38C, 32)): + with self.subTest(address=address): + self.assertTrue(self._tx(common.make_msg(1, address, length))) + + for address, length in ((0x51, 32), (0x31A, 32), (0x3B5, 32), (0x3C1, 8)): + with self.subTest(address=address): + self.assertFalse(self._tx(common.make_msg(1 if address != 0x51 else 0, address, length))) + def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): values = { "aReqRaw": accel,