From d0eb7b69ecdcc2480f79eb5cd423c8e09947bf98 Mon Sep 17 00:00:00 2001 From: ccdunder Date: Sat, 14 Dec 2024 11:03:55 -0800 Subject: [PATCH 1/3] Handle ALT_BUTTONS w/ HDA2. The 2025 Kia Carnival w/ HDA2 uses ALT_BUTTONS. --- board/safety/safety_hyundai_canfd.h | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/board/safety/safety_hyundai_canfd.h b/board/safety/safety_hyundai_canfd.h index b42889bb0e..8d00b9dfc7 100644 --- a/board/safety/safety_hyundai_canfd.h +++ b/board/safety/safety_hyundai_canfd.h @@ -237,6 +237,8 @@ static safety_config hyundai_canfd_init(uint16_t param) { static const CanMsg HYUNDAI_CANFD_HDA2_ALT_STEERING_TX_MSGS[] = { {0x110, 0, 32}, // LKAS_ALT {0x1CF, 1, 8}, // CRUISE_BUTTON + // Needed for cruise control in case of ALT_BUTTONS. + {0x1A0, 1, 32}, // CRUISE_INFO {0x362, 0, 32}, // CAM_0x362 }; @@ -303,15 +305,23 @@ static safety_config hyundai_canfd_init(uint16_t param) { 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); + if (hyundai_canfd_alt_buttons) { + static RxCheck hyundai_canfd_hda2_alt_buttons_rx_checks[] = { + HYUNDAI_CANFD_COMMON_RX_CHECKS(1) + HYUNDAI_CANFD_ALT_BUTTONS_ADDR_CHECK(1) + HYUNDAI_CANFD_SCC_ADDR_CHECK(1) + }; + ret = hyundai_canfd_hda2_alt_steering ? BUILD_SAFETY_CFG(hyundai_canfd_hda2_alt_buttons_rx_checks, HYUNDAI_CANFD_HDA2_ALT_STEERING_TX_MSGS) : \ + BUILD_SAFETY_CFG(hyundai_canfd_hda2_alt_buttons_rx_checks, HYUNDAI_CANFD_HDA2_TX_MSGS); + } else { + 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) From 0401f642d24b66e44e2182968be6548c7e3d917e Mon Sep 17 00:00:00 2001 From: ccdunder Date: Mon, 16 Dec 2024 06:05:35 +0000 Subject: [PATCH 2/3] Add tests for ALT_BUTTONS w/ HDA2. --- tests/safety/test_hyundai_canfd.py | 127 +++++++++++++---------------- 1 file changed, 57 insertions(+), 70 deletions(-) diff --git a/tests/safety/test_hyundai_canfd.py b/tests/safety/test_hyundai_canfd.py index 7f280b6319..0e15ce1568 100755 --- a/tests/safety/test_hyundai_canfd.py +++ b/tests/safety/test_hyundai_canfd.py @@ -9,7 +9,7 @@ class TestHyundaiCanfdBase(HyundaiButtonBase, common.PandaCarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest): - + SAFETY_PARAM = 0 TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]] STANDSTILL_THRESHOLD = 12 # 0.375 kph FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]} @@ -45,6 +45,12 @@ def setUpClass(cls): cls.safety = None raise unittest.SkipTest + def setUp(self): + self.packer = CANPackerPanda("hyundai_canfd") + self.safety = libpanda_py.libpanda + self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, self.SAFETY_PARAM) + self.safety.init_tests() + def _torque_driver_msg(self, torque): values = {"STEERING_COL_TORQUE": torque} return self.packer.make_can_msg_panda("MDPS", self.PT_BUS, values) @@ -79,6 +85,29 @@ def _button_msg(self, buttons, main_button=0, bus=None): return self.packer.make_can_msg_panda("CRUISE_BUTTONS", bus, values) +class HyundaiCanfdAltButtonsMixin: + @classmethod + def setUpClass(cls): + super().setUpClass() + cls.SAFETY_PARAM |= Panda.FLAG_HYUNDAI_CANFD_ALT_BUTTONS + + def _button_msg(self, buttons, main_button=0, bus=1): + values = { + "CRUISE_BUTTONS": buttons, + "ADAPTIVE_CRUISE_MAIN_BTN": main_button, + } + return self.packer.make_can_msg_panda("CRUISE_BUTTONS_ALT", self.PT_BUS, values) + + def test_button_sends(self): + """ + No button send allowed with alt buttons. + """ + for enabled in (True, False): + for btn in range(8): + self.safety.set_controls_allowed(enabled) + self.assertFalse(self._tx(self._button_msg(btn))) + + class TestHyundaiCanfdHDA1Base(TestHyundaiCanfdBase): TX_MSGS = [[0x12A, 0], [0x1A0, 1], [0x1CF, 0], [0x1E0, 0]] @@ -88,7 +117,6 @@ class TestHyundaiCanfdHDA1Base(TestHyundaiCanfdBase): STEER_MSG = "LFA" BUTTONS_TX_BUS = 2 - SAFETY_PARAM: int @classmethod def setUpClass(cls): @@ -98,12 +126,6 @@ def setUpClass(cls): cls.safety = None raise unittest.SkipTest - def setUp(self): - self.packer = CANPackerPanda("hyundai_canfd") - self.safety = libpanda_py.libpanda - self.safety.set_safety_hooks(Panda.SAFETY_HYUNDAI_CANFD, self.SAFETY_PARAM) - self.safety.init_tests() - @parameterized_class([ # Radar SCC, test with long flag to ensure flag is not respected until it is supported @@ -129,71 +151,45 @@ class TestHyundaiCanfdHDA1(TestHyundaiCanfdHDA1Base): {"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}, ]) -class TestHyundaiCanfdHDA1AltButtons(TestHyundaiCanfdHDA1Base): - - SAFETY_PARAM: int - - 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.init_tests() - - def _button_msg(self, buttons, main_button=0, bus=1): - values = { - "CRUISE_BUTTONS": buttons, - "ADAPTIVE_CRUISE_MAIN_BTN": main_button, - } - return self.packer.make_can_msg_panda("CRUISE_BUTTONS_ALT", self.PT_BUS, values) - - def test_button_sends(self): - """ - No button send allowed with alt buttons. - """ - for enabled in (True, False): - for btn in range(8): - self.safety.set_controls_allowed(enabled) - self.assertFalse(self._tx(self._button_msg(btn))) +class TestHyundaiCanfdHDA1AltButtons(HyundaiCanfdAltButtonsMixin, TestHyundaiCanfdHDA1Base): + pass -class TestHyundaiCanfdHDA2EV(TestHyundaiCanfdBase): +# ********************* HDA2 ********************** - TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]] - RELAY_MALFUNCTION_ADDRS = {0: (0x50,)} # LKAS - FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]} - FWD_BUS_LOOKUP = {0: 2, 2: 0} +# TODO: Handle ICE and HEV configurations. +class TestHyundaiCanfdHDA2EVBase(TestHyundaiCanfdBase): PT_BUS = 1 SCC_BUS = 1 - STEER_MSG = "LKAS" GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL") + FWD_BUS_LOOKUP = {0: 2, 2: 0} - 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.init_tests() +class TestHyundaiCanfdHDA2EV(TestHyundaiCanfdHDA2EVBase): + TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]] + RELAY_MALFUNCTION_ADDRS = {0: (0x50,)} + FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]} + STEER_MSG = "LKAS" + SAFETY_PARAM = Panda.FLAG_HYUNDAI_CANFD_HDA2 | Panda.FLAG_HYUNDAI_EV_GAS -# TODO: Handle ICE and HEV configurations once we see cars that use the new messages -class TestHyundaiCanfdHDA2EVAltSteering(TestHyundaiCanfdBase): +class TestHyundaiCanfdHDA2EVAltSteering(TestHyundaiCanfdHDA2EVBase): TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x362, 0]] - RELAY_MALFUNCTION_ADDRS = {0: (0x110,)} # LKAS_ALT + RELAY_MALFUNCTION_ADDRS = {0: (0x110,)} FWD_BLACKLISTED_ADDRS = {2: [0x110, 0x362]} - FWD_BUS_LOOKUP = {0: 2, 2: 0} - - PT_BUS = 1 - SCC_BUS = 1 STEER_MSG = "LKAS_ALT" - GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL") + SAFETY_PARAM = Panda.FLAG_HYUNDAI_CANFD_HDA2 | Panda.FLAG_HYUNDAI_EV_GAS | Panda.FLAG_HYUNDAI_CANFD_HDA2_ALT_STEERING - 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.init_tests() + +class TestHyundaiCanfdHDA2EVAltButtons(HyundaiCanfdAltButtonsMixin, TestHyundaiCanfdHDA2EV): + pass + +class TestHyundaiCanfdHDA2EVAltSteeringAltButtons(HyundaiCanfdAltButtonsMixin, TestHyundaiCanfdHDA2EVAltSteering): + pass + + +# ********************* LONG ********************** class TestHyundaiCanfdHDA2LongEV(HyundaiLongitudinalBase, TestHyundaiCanfdHDA2EV): @@ -209,12 +205,7 @@ class TestHyundaiCanfdHDA2LongEV(HyundaiLongitudinalBase, TestHyundaiCanfdHDA2EV STEER_MSG = "LFA" GAS_MSG = ("ACCELERATOR", "ACCELERATOR_PEDAL") STEER_BUS = 1 - - 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.init_tests() + SAFETY_PARAM = Panda.FLAG_HYUNDAI_CANFD_HDA2 | Panda.FLAG_HYUNDAI_LONG | Panda.FLAG_HYUNDAI_EV_GAS def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): values = { @@ -246,16 +237,12 @@ class TestHyundaiCanfdHDA1Long(HyundaiLongitudinalBase, TestHyundaiCanfdHDA1Base @classmethod def setUpClass(cls): + super().setUpClass() + cls.SAFETY_PARAM |= Panda.FLAG_HYUNDAI_CAMERA_SCC if cls.__name__ == "TestHyundaiCanfdHDA1Long": cls.safety = None raise unittest.SkipTest - 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.init_tests() - def _accel_msg(self, accel, aeb_req=False, aeb_decel=0): values = { "aReqRaw": accel, From a09c1cc1fb28f20aeff9a36ca9ee5635fc8c4861 Mon Sep 17 00:00:00 2001 From: ccdunder Date: Mon, 16 Dec 2024 23:26:51 +0000 Subject: [PATCH 3/3] Support cruise control button tx/rx for ALT_BUTTONS. This is needed for the Kia Caravan '25. --- board/safety/safety_hyundai_canfd.h | 17 +++++++++++++---- tests/safety/test_hyundai_canfd.py | 26 ++++++++++---------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/board/safety/safety_hyundai_canfd.h b/board/safety/safety_hyundai_canfd.h index 8d00b9dfc7..2efbe203e9 100644 --- a/board/safety/safety_hyundai_canfd.h +++ b/board/safety/safety_hyundai_canfd.h @@ -154,10 +154,16 @@ static bool hyundai_canfd_tx_hook(const CANPacket_t *to_send) { } // 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); + const int button_addr = hyundai_canfd_alt_buttons ? 0x1aa : 0x1cf; + if (addr == button_addr) { + int cruise_button = 0; + if (addr == 0x1cf) { + cruise_button = GET_BYTE(to_send, 2) & 0x7U; + } else { + cruise_button = (GET_BYTE(to_send, 4) >> 4) & 0x7U; + } + bool is_cancel = (cruise_button == HYUNDAI_BTN_CANCEL); + bool is_resume = (cruise_button == HYUNDAI_BTN_RESUME); bool allowed = (is_cancel && cruise_engaged_prev) || (is_resume && controls_allowed); if (!allowed) { @@ -231,12 +237,14 @@ static safety_config hyundai_canfd_init(uint16_t param) { static const CanMsg HYUNDAI_CANFD_HDA2_TX_MSGS[] = { {0x50, 0, 16}, // LKAS {0x1CF, 1, 8}, // CRUISE_BUTTON + {0x1AA, 1, 16}, // CRUISE_BUTTONS_ALT {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 + {0x1AA, 1, 16}, // CRUISE_BUTTONS_ALT // Needed for cruise control in case of ALT_BUTTONS. {0x1A0, 1, 32}, // CRUISE_INFO {0x362, 0, 32}, // CAM_0x362 @@ -262,6 +270,7 @@ static safety_config hyundai_canfd_init(uint16_t param) { {0x12A, 0, 16}, // LFA {0x1A0, 0, 32}, // CRUISE_INFO {0x1CF, 2, 8}, // CRUISE_BUTTON + {0x1AA, 2, 16}, // CRUISE_BUTTONS_ALT {0x1E0, 0, 16}, // LFAHDA_CLUSTER }; diff --git a/tests/safety/test_hyundai_canfd.py b/tests/safety/test_hyundai_canfd.py index 0e15ce1568..cbb172112f 100755 --- a/tests/safety/test_hyundai_canfd.py +++ b/tests/safety/test_hyundai_canfd.py @@ -10,7 +10,7 @@ class TestHyundaiCanfdBase(HyundaiButtonBase, common.PandaCarSafetyTest, common.DriverTorqueSteeringSafetyTest, common.SteerRequestCutSafetyTest): SAFETY_PARAM = 0 - TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]] + TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x1AA, 1], [0x2A4, 0]] STANDSTILL_THRESHOLD = 12 # 0.375 kph FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]} FWD_BUS_LOOKUP = {0: 2, 2: 0} @@ -91,26 +91,20 @@ def setUpClass(cls): super().setUpClass() cls.SAFETY_PARAM |= Panda.FLAG_HYUNDAI_CANFD_ALT_BUTTONS - def _button_msg(self, buttons, main_button=0, bus=1): + def _button_msg(self, buttons, main_button=0, bus=None): + if bus is None: + bus = self.PT_BUS values = { "CRUISE_BUTTONS": buttons, "ADAPTIVE_CRUISE_MAIN_BTN": main_button, } - return self.packer.make_can_msg_panda("CRUISE_BUTTONS_ALT", self.PT_BUS, values) - - def test_button_sends(self): - """ - No button send allowed with alt buttons. - """ - for enabled in (True, False): - for btn in range(8): - self.safety.set_controls_allowed(enabled) - self.assertFalse(self._tx(self._button_msg(btn))) + msg = self.packer.make_can_msg_panda("CRUISE_BUTTONS_ALT", bus, values) + return msg class TestHyundaiCanfdHDA1Base(TestHyundaiCanfdBase): - TX_MSGS = [[0x12A, 0], [0x1A0, 1], [0x1CF, 0], [0x1E0, 0]] + TX_MSGS = [[0x12A, 0], [0x1A0, 1], [0x1CF, 2], [0x1AA, 2], [0x1E0, 0]] RELAY_MALFUNCTION_ADDRS = {0: (0x12A,)} # LFA FWD_BLACKLISTED_ADDRS = {2: [0x12A, 0x1E0]} FWD_BUS_LOOKUP = {0: 2, 2: 0} @@ -167,7 +161,7 @@ class TestHyundaiCanfdHDA2EVBase(TestHyundaiCanfdBase): class TestHyundaiCanfdHDA2EV(TestHyundaiCanfdHDA2EVBase): - TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0]] + TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x1AA, 1], [0x2A4, 0]] RELAY_MALFUNCTION_ADDRS = {0: (0x50,)} FWD_BLACKLISTED_ADDRS = {2: [0x50, 0x2a4]} STEER_MSG = "LKAS" @@ -175,7 +169,7 @@ class TestHyundaiCanfdHDA2EV(TestHyundaiCanfdHDA2EVBase): class TestHyundaiCanfdHDA2EVAltSteering(TestHyundaiCanfdHDA2EVBase): - TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x362, 0]] + TX_MSGS = [[0x110, 0], [0x1CF, 1], [0x1AA, 1], [0x362, 0]] RELAY_MALFUNCTION_ADDRS = {0: (0x110,)} FWD_BLACKLISTED_ADDRS = {2: [0x110, 0x362]} STEER_MSG = "LKAS_ALT" @@ -194,7 +188,7 @@ class TestHyundaiCanfdHDA2EVAltSteeringAltButtons(HyundaiCanfdAltButtonsMixin, T class TestHyundaiCanfdHDA2LongEV(HyundaiLongitudinalBase, TestHyundaiCanfdHDA2EV): - TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x2A4, 0], [0x51, 0], [0x730, 1], [0x12a, 1], [0x160, 1], + TX_MSGS = [[0x50, 0], [0x1CF, 1], [0x1AA, 1], [0x2A4, 0], [0x51, 0], [0x730, 1], [0x12a, 1], [0x160, 1], [0x1e0, 1], [0x1a0, 1], [0x1ea, 1], [0x200, 1], [0x345, 1], [0x1da, 1]] RELAY_MALFUNCTION_ADDRS = {0: (0x50,), 1: (0x1a0,)} # LKAS, SCC_CONTROL