diff --git a/board/power_saving.h b/board/power_saving.h index 7fcc181ea9..faddd0b432 100644 --- a/board/power_saving.h +++ b/board/power_saving.h @@ -33,7 +33,7 @@ void set_power_save_state(int state) { enable = true; } - current_board->enable_can_transceivers(enable); + current_board->enable_can_transceivers(true); // Switch off IR when in power saving if(!enable){ diff --git a/board/safety/safety_elm327.h b/board/safety/safety_elm327.h index 83efd826b9..bfc1572f9d 100644 --- a/board/safety/safety_elm327.h +++ b/board/safety/safety_elm327.h @@ -3,6 +3,11 @@ #include "safety_declarations.h" #include "safety_defaults.h" +#define CAN_GATEWAY_INPUT 0x800 +#define CAN_GATEWAY_OUTPUT 0x801 +#define CAN_GATEWAY_SIZE 8 +#define OTA_IN 0x1 + static bool elm327_tx_hook(const CANPacket_t *to_send) { const int GM_CAMERA_DIAG_ADDR = 0x24B; @@ -10,9 +15,32 @@ static bool elm327_tx_hook(const CANPacket_t *to_send) { 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; + // All ISO 15765-4 messages must be 8 bytes long + // TODO: Replace this with the check functionality from safety_honda + bool is_body = (addr == 0x16f118f0) || (addr == 0x0ef81218) || (addr == CAN_GATEWAY_INPUT); + if (is_body) { + if ((len != 8) && (addr == 0x16f118f0)){ // honda bcm diag request + tx = false; + } + else if ((len != 2) && (addr == 0x0ef81218)){ // 2017 honda civic hatch keyfob replay + tx = false; + } + else if ((len != CAN_GATEWAY_SIZE) && (addr == CAN_GATEWAY_INPUT)){ // body harness heartbeat frame + tx = false; + } + else { + tx = false; // we shouldn't end up here if we did things correctly + } + } + // // allow OTA flashing + // else if (addr == OTA_IN){ + // tx = true; + // } + else { + //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 diff --git a/board/safety/safety_honda.h b/board/safety/safety_honda.h index 60ccea1e16..37bff06ede 100644 --- a/board/safety/safety_honda.h +++ b/board/safety/safety_honda.h @@ -87,7 +87,7 @@ static void honda_rx_hook(const CANPacket_t *to_push) { // check ACC main state // 0x326 for all Bosch and some Nidec, 0x1A6 for some Nidec - if ((addr == 0x326) || (addr == 0x1A6)) { + if (((addr == 0x326) && (bus == pt_bus)) || (addr == 0x1A6)) { acc_main_on = GET_BIT(to_push, ((addr == 0x326) ? 28U : 47U)); if (!acc_main_on) { controls_allowed = false; @@ -173,6 +173,11 @@ static void honda_rx_hook(const CANPacket_t *to_push) { int bus_rdr_car = (honda_hw == HONDA_BOSCH) ? 0 : 2; // radar bus, car side bool stock_ecu_detected = false; + // // TODO: tick the body harness gatewayheartbeat. If we lose contact with the OP, should we go not controls_allowed??? + // if ((addr == 0x801) && (len == 8)) { + // + // } + // 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)) { @@ -197,6 +202,7 @@ static bool honda_tx_hook(const CANPacket_t *to_send) { .min_accel = -350, .max_gas = 2000, + .min_gas = -40, .inactive_gas = -30000, }; @@ -299,11 +305,29 @@ static bool honda_tx_hook(const CANPacket_t *to_send) { } } + // KWP over CAN. Allow only short turn signal request and cancel + // TODO: move to gateway firmware + if (addr == 0x16F118F0){ + bool signalCmd = ((GET_LEN(to_send) == 8U) && ((GET_BYTES(to_send, 0, 4) == 0x000F0A30U) || (GET_BYTES(to_send, 0, 4) == 0x000F0B30U)) && (GET_BYTES(to_send, 4, 4) == 0x0U)); + bool cancelCmd = ((GET_LEN(to_send) == 1U) && (GET_BYTE(to_send, 0) == 0x20U)); + // always allow cancel + if (!cancelCmd) { + if (!controls_allowed) { + tx = false; + } + else { + if (!signalCmd) { + 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}}; + static CanMsg HONDA_N_TX_MSGS[] = {{0xE4, 0, 5}, {0x194, 0, 4}, {0x1FA, 0, 8}, {0x30C, 0, 8}, {0x33D, 0, 5}, {0x16F118F0, 0, 8}, {0x16F118F0, 0, 1}}; const uint16_t HONDA_PARAM_NIDEC_ALT = 4; @@ -321,7 +345,7 @@ static safety_config honda_nidec_init(uint16_t param) { if (enable_nidec_alt) { // For Nidecs with main on signal on an alternate msg (missing 0x326) - static RxCheck honda_nidec_alt_rx_checks[] = { + static RxCheck honda_nidec_alt_rx_checks[] = { HONDA_COMMON_NO_SCM_FEEDBACK_RX_CHECKS(0) }; @@ -336,10 +360,10 @@ static safety_config honda_nidec_init(uint16_t param) { } 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 + static CanMsg HONDA_BOSCH_TX_MSGS[] = {{0xE4, 0, 5}, {0xE5, 0, 8}, {0x296, 1, 4}, {0x33D, 0, 5}, {0x33DA, 0, 5}, {0x33DB, 0, 8}, {0x16F118F0, 0, 8}, {0x16F118F0, 0, 1}}; // Bosch w/ body + 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}, {0x16F118F0, 0, 8}, {0x16F118F0, 0, 1}, {0x18DAB0F1, 1, 8}}; // Bosch w/ gas and brakes and body + static CanMsg HONDA_RADARLESS_TX_MSGS[] = {{0xE4, 0, 5}, {0x296, 2, 4}, {0x33D, 0, 8}, {0x16F118F0, 0, 8}, {0x16F118F0, 0, 1}}; // Bosch radarless + static CanMsg HONDA_RADARLESS_LONG_TX_MSGS[] = {{0xE4, 0, 5}, {0x33D, 0, 8}, {0x1C8, 0, 8}, {0x30C, 0, 8}, {0x16F118F0, 0, 8}, {0x16F118F0, 0, 1}}; // Bosch radarless w/ gas and brakes const uint16_t HONDA_PARAM_ALT_BRAKE = 1; const uint16_t HONDA_PARAM_RADARLESS = 8; diff --git a/tests/safety/test_honda.py b/tests/safety/test_honda.py index 082199c02b..d320930510 100755 --- a/tests/safety/test_honda.py +++ b/tests/safety/test_honda.py @@ -19,6 +19,18 @@ class Btn: HONDA_NIDEC = 0 HONDA_BOSCH = 1 +turnSignalCmdLeftMsg = b"\x30\x0a\x0f\x00\x00\x00\x00\x00" +turnSignalCmdRightMsg = b"\x30\x0b\x0f\x00\x00\x00\x00\x00" +turnSignalCmdCancelMsg = b"\x20" +trunkCmdReleaseMsg = b"\x30\x09\x01\x00\x00\x00\x00\x00" + +def interceptor_msg(gas, addr): + to_send = common.make_msg(0, addr, 6) + to_send[0].data[0] = (gas & 0xFF00) >> 8 + to_send[0].data[1] = gas & 0xFF + to_send[0].data[2] = (gas & 0xFF00) >> 8 + to_send[0].data[3] = gas & 0xFF + return to_send # Honda safety has several different configurations tested here: # * Nidec @@ -136,6 +148,18 @@ def test_rx_hook(self): self._rx(self._button_msg(Btn.SET, main_on=True)) self.assertTrue(self.safety.get_controls_allowed()) + # Never allow dangerous commands; e.g. trunk release + def test_kwp_over_can(self): + self.safety.set_controls_allowed(0) + self.assertTrue(self._tx(libpanda_py.make_CANPacket(0x16F118F0, 0, turnSignalCmdCancelMsg))) + self.assertFalse(self._tx(libpanda_py.make_CANPacket(0x16F118F0, 0, turnSignalCmdLeftMsg))) + self.assertFalse(self._tx(libpanda_py.make_CANPacket(0x16F118F0, 0, turnSignalCmdRightMsg))) + self.assertFalse(self._tx(libpanda_py.make_CANPacket(0x16F118F0, 0, trunkCmdReleaseMsg))) + self.safety.set_controls_allowed(1) + self.assertTrue(self._tx(libpanda_py.make_CANPacket(0x16F118F0, 0, turnSignalCmdCancelMsg))) + self.assertTrue(self._tx(libpanda_py.make_CANPacket(0x16F118F0, 0, turnSignalCmdLeftMsg))) + self.assertTrue(self._tx(libpanda_py.make_CANPacket(0x16F118F0, 0, turnSignalCmdRightMsg))) + self.assertFalse(self._tx(libpanda_py.make_CANPacket(0x16F118F0, 0, trunkCmdReleaseMsg))) class HondaPcmEnableBase(common.PandaCarSafetyTest): # pylint: disable=no-member,abstract-method @@ -459,6 +483,7 @@ class TestHondaBoschLongSafety(HondaButtonEnableBase, TestHondaBoschSafetyBase): Covers the Honda Bosch safety mode with longitudinal control """ NO_GAS = -30000 + MIN_GAS = -40 MAX_GAS = 2000 MAX_ACCEL = 2.0 # accel is used for brakes, but openpilot can set positive values MIN_ACCEL = -3.5 @@ -495,10 +520,10 @@ def test_diagnostics(self): def test_gas_safety_check(self): for controls_allowed in [True, False]: - for gas in np.arange(self.NO_GAS, self.MAX_GAS + 2000, 100): - accel = 0 if gas < 0 else gas / 1000 + for gas in np.arange(self.NO_GAS, self.MAX_GAS + 200, 1): + accel = 0 if gas < self.MIN_GAS else gas / 1000 self.safety.set_controls_allowed(controls_allowed) - send = (controls_allowed and 0 <= gas <= self.MAX_GAS) or gas == self.NO_GAS + send = (controls_allowed and self.MIN_GAS <= gas <= self.MAX_GAS) or gas == self.NO_GAS self.assertEqual(send, self._tx(self._send_gas_brake_msg(gas, accel)), (controls_allowed, gas, accel)) def test_brake_safety_check(self):