volt checks

This commit is contained in:
firestar5683
2026-04-07 20:26:13 -05:00
parent 3f2dc76051
commit c2ff6b573a
38 changed files with 118 additions and 60 deletions
+1 -1
View File
@@ -200,7 +200,6 @@ class CarInterface(CarInterfaceBase):
if candidate in EV_CAR:
ret.transmissionType = TransmissionType.direct
ret.safetyConfigs[0].safetyParam |= GMSafetyFlags.EV.value
else:
ret.transmissionType = TransmissionType.automatic
@@ -615,6 +614,7 @@ class CarInterface(CarInterfaceBase):
if (ret.networkLocation == NetworkLocation.fwdCamera or candidate in CC_ONLY_CAR) and CAM_MSG not in fingerprint[CanBus.CAMERA] and candidate not in SDGM_CAR:
ret.flags |= GMFlags.NO_CAMERA.value
ret.safetyConfigs[0].safetyParam |= GMSafetyFlags.FLAG_GM_NO_CAMERA.value
if ACCELERATOR_POS_MSG not in fingerprint[CanBus.POWERTRAIN]:
ret.flags |= GMFlags.NO_ACCELERATOR_POS_MSG.value
+2 -1
View File
@@ -157,7 +157,8 @@ class CarControllerParams:
class GMSafetyFlags(IntFlag):
HW_CAM = 1
HW_CAM_LONG = 2
EV = 4
# Reuses the retired EV safety bit. EV-specific safety handling is no longer needed.
FLAG_GM_NO_CAMERA = 4
FLAG_GM_CC_LONG = 8
FLAG_GM_GAS_INTERCEPTOR = 16
+1
View File
@@ -50,6 +50,7 @@ GEAR_SHIFTER_MAP: dict[str, structs.CarState.GearShifter] = {
'D': GearShifter.drive, 'DRIVE': GearShifter.drive,
'S': GearShifter.sport, 'SPORT': GearShifter.sport,
'L': GearShifter.low, 'LOW': GearShifter.low,
'L2': GearShifter.low, 'L3': GearShifter.low,
'B': GearShifter.brake, 'BRAKE': GearShifter.brake,
}
+46 -51
View File
@@ -522,7 +522,7 @@ static bool gm_fwd_hook(int bus_num, int addr) {
static safety_config gm_init(uint16_t param) {
const uint16_t GM_PARAM_HW_CAM = 1;
const uint16_t GM_PARAM_HW_CAM_LONG = 2;
const uint16_t GM_PARAM_EV = 4;
const uint16_t GM_PARAM_NO_CAMERA = 4;
const uint16_t GM_PARAM_CC_LONG = 8;
const uint16_t GM_PARAM_PEDAL_INTERCEPTOR = 16;
const uint16_t GM_PARAM_NO_ACC = 32;
@@ -566,18 +566,23 @@ static safety_config gm_init(uint16_t param) {
{0x200, 0, 6, .check_relay = false}, {0x1E1, 0, 7, .check_relay = false},
{0xBD, 0, 7, .check_relay = false}, {0x1F5, 0, 8, .check_relay = false}}; // pt bus
static const CanMsg GM_CAM_LONG_NO_CAMERA_TX_MSGS[] = {{0x180, 0, 4, .check_relay = false}, {0x315, 0, 5, .check_relay = false}, {0x2CB, 0, 8, .check_relay = false}, {0x370, 0, 6, .check_relay = false}, {0x3D1, 0, 8, .check_relay = false}, // pt bus
{0x184, 2, 8, .check_relay = false}, // camera bus
{0x200, 0, 6, .check_relay = false}, {0x1E1, 0, 7, .check_relay = false},
{0xBD, 0, 7, .check_relay = false}, {0x1F5, 0, 8, .check_relay = false}}; // pt bus
static RxCheck gm_rx_checks[] = {
GM_COMMON_RX_CHECKS
GM_ACC_RX_CHECKS
};
static RxCheck gm_ev_rx_checks[] = {
GM_COMMON_RX_CHECKS
{.msg = {{0xBD, 0, 7, 40U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
GM_ACC_RX_CHECKS
{.msg = {{0x184, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{0x34A, 0, 5, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{0x1E1, 0, 7, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true},
{0x1E1, 2, 7, 100000U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true},
{ 0 }}},
{.msg = {{0xF1, 0, 6, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true},
{0xF1, 2, 6, 100000U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true},
{ 0 }}},
{.msg = {{0x1C4, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{0xC9, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
};
static RxCheck gm_ascm_int_stock_cam_rx_checks[] = {
@@ -591,11 +596,11 @@ static safety_config gm_init(uint16_t param) {
{0x1E1, 0, 7, .check_relay = false},
{0xBD, 0, 7, .check_relay = false}, {0x1F5, 0, 8, .check_relay = false}}; // pt bus
static RxCheck gm_no_acc_ev_rx_checks[] = {
GM_COMMON_RX_CHECKS
{.msg = {{0xBD, 0, 7, 40U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{0x3D1, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // Non-ACC PCM
};
static const CanMsg GM_CAM_NO_CAMERA_TX_MSGS[] = {{0x180, 0, 4, .check_relay = false}, {0x370, 0, 6, .check_relay = false}, {0x3D1, 0, 8, .check_relay = false}, // pt bus
{0x1E1, 2, 7, .check_relay = false}, {0x184, 2, 8, .check_relay = false}, // camera bus
{0x200, 0, 6, .check_relay = false},
{0x1E1, 0, 7, .check_relay = false},
{0xBD, 0, 7, .check_relay = false}, {0x1F5, 0, 8, .check_relay = false}}; // pt bus
static RxCheck gm_no_acc_rx_checks[] = {
GM_COMMON_RX_CHECKS
@@ -615,12 +620,6 @@ static safety_config gm_init(uint16_t param) {
{.msg = {{0xC9, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
};
static RxCheck gm_cam_acc_rx_checks[] = {
GM_COMMON_RX_CHECKS
GM_ACC_RX_CHECKS
{.msg = {{0x370, 2, 6, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}}, // camera ACC status
};
static RxCheck gm_cam_acc_pedal_rx_checks[] = {
{.msg = {{0x184, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{0x34A, 0, 5, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
@@ -634,26 +633,18 @@ static safety_config gm_init(uint16_t param) {
{.msg = {{0xC9, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
};
static RxCheck gm_sdgm_acc_rx_checks[] = {
{.msg = {{0x184, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{0x34A, 0, 5, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{0x1E1, 0, 7, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true},
{0x1E1, 2, 7, 100000U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true},
{ 0 }}},
{.msg = {{0xF1, 0, 6, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true},
{0xF1, 2, 6, 100000U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true},
{ 0 }}},
{.msg = {{0x1C4, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
{.msg = {{0xC9, 0, 8, 10U, .ignore_checksum = true, .ignore_counter = true, .ignore_quality_flag = true}, { 0 }, { 0 }}},
};
static const CanMsg GM_CC_LONG_TX_MSGS[] = {{0x180, 0, 4, .check_relay = true}, {0x370, 0, 6, .check_relay = false}, {0x1E1, 0, 7, .check_relay = false}, {0x3D1, 0, 8, .check_relay = false}, // pt bus
{0xBD, 0, 7, .check_relay = false}, {0x1F5, 0, 8, .check_relay = false},
{0x184, 2, 8, .check_relay = true}, {0x1E1, 2, 7, .check_relay = false}}; // camera bus
static const CanMsg GM_CC_LONG_NO_CAMERA_TX_MSGS[] = {{0x180, 0, 4, .check_relay = false}, {0x370, 0, 6, .check_relay = false}, {0x1E1, 0, 7, .check_relay = false}, {0x3D1, 0, 8, .check_relay = false}, // pt bus
{0xBD, 0, 7, .check_relay = false}, {0x1F5, 0, 8, .check_relay = false},
{0x184, 2, 8, .check_relay = false}, {0x1E1, 2, 7, .check_relay = false}}; // camera bus
gm_hw = GET_FLAG(param, GM_PARAM_HW_CAM) ? GM_CAM : GM_ASCM;
gm_sdgm = GET_FLAG(param, GM_PARAM_HW_SDGM);
gm_ascm_int = GET_FLAG(param, GM_PARAM_HW_ASCM_INT);
const bool gm_no_camera = GET_FLAG(param, GM_PARAM_NO_CAMERA);
gm_cc_long = GET_FLAG(param, GM_PARAM_CC_LONG);
gm_has_acc = !GET_FLAG(param, GM_PARAM_NO_ACC);
@@ -704,46 +695,50 @@ static safety_config gm_init(uint16_t param) {
}
safety_config ret;
if (gm_hw == GM_CAM) {
// SDGM behaves like a forwarding camera path for whitelist/forwarding purposes.
if ((gm_hw == GM_CAM) || gm_sdgm) {
// 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
if (gm_cc_long) {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CC_LONG_TX_MSGS);
if (gm_no_camera) {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CC_LONG_NO_CAMERA_TX_MSGS);
} else {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CC_LONG_TX_MSGS);
}
} else if (gm_cam_long) {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CAM_LONG_TX_MSGS);
if (gm_no_camera) {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CAM_LONG_NO_CAMERA_TX_MSGS);
} else {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CAM_LONG_TX_MSGS);
}
} else {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CAM_TX_MSGS);
if (gm_no_camera) {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CAM_NO_CAMERA_TX_MSGS);
} else {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CAM_TX_MSGS);
}
}
} else {
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_ASCM_TX_MSGS);
}
const bool gm_ev = GET_FLAG(param, GM_PARAM_EV);
if (enable_gas_interceptor) {
if (gm_has_acc && (gm_hw == GM_CAM || gm_sdgm)) {
SET_RX_CHECKS(gm_cam_acc_pedal_rx_checks, ret);
} else {
SET_RX_CHECKS(gm_pedal_rx_checks, ret);
}
} else if (gm_has_acc && gm_sdgm) {
SET_RX_CHECKS(gm_sdgm_acc_rx_checks, ret);
} else if (gm_has_acc && (gm_hw == GM_CAM || gm_sdgm)) {
SET_RX_CHECKS(gm_cam_acc_rx_checks, ret);
} else if (!gm_has_acc && gm_ev) {
SET_RX_CHECKS(gm_no_acc_ev_rx_checks, ret);
} else if (!gm_has_acc && !gm_ev) {
} else if (!gm_has_acc) {
SET_RX_CHECKS(gm_no_acc_rx_checks, ret);
} else if (gm_ev) {
SET_RX_CHECKS(gm_ev_rx_checks, ret);
}
if (gm_ascm_int_stock_cam || gm_ascm_int_no_accel_pos) {
SET_RX_CHECKS(gm_ascm_int_stock_cam_rx_checks, ret);
}
// ASCM does not forward any messages
if (gm_hw == GM_ASCM) {
// ASCM does not forward any messages. SDGM still forwards between PT and camera.
if ((gm_hw == GM_ASCM) && !gm_sdgm) {
ret.disable_forwarding = true;
}
return ret;
+64 -3
View File
@@ -139,7 +139,7 @@ class TestGmSafetyBase(common.CarSafetyTest, common.DriverTorqueSteeringSafetyTe
class TestGmEVSafetyBase(TestGmSafetyBase):
EXTRA_SAFETY_PARAM = GMSafetyFlags.EV
EXTRA_SAFETY_PARAM = 0
# existence of _user_regen_msg adds regen tests
def _user_regen_msg(self, regen):
@@ -233,8 +233,21 @@ class TestGmCameraSafety(TestGmCameraSafetyBase):
self.assertEqual(enabled, self._tx(self._button_msg(Buttons.CANCEL)))
def _prime_gm_ascm_int_stock_cam_rx_checks(safety, f1_bus: int) -> None:
# This path should only accept the Volt/Malibu ASCM_INT stock-camera status on bus 0.
class TestGmSdgmSafety(TestGmSafetyBase):
TX_MSGS = [[0x180, 0], [0x370, 0], [0x200, 0], [0x1E1, 0], [0x3D1, 0], [0xBD, 0], [0x1F5, 0], # pt bus
[0x1E1, 2], [0x184, 2]] # camera bus
FWD_BLACKLISTED_ADDRS = {2: [0x180], 0: [0x184]} # block LKAS message and PSCMStatus
BUTTONS_BUS = 2 # tx only
def setUp(self):
self.packer = CANPackerSafety("gm_global_a_powertrain_generated")
self.packer_chassis = CANPackerSafety("gm_global_a_chassis")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_SDGM | self.EXTRA_SAFETY_PARAM)
self.safety.init_tests()
def _prime_gm_base_rx_checks(safety, f1_bus: int) -> None:
for bus, addr, length in (
(0, 0x184, 8),
(0, 0x34A, 5),
@@ -246,6 +259,20 @@ def _prime_gm_ascm_int_stock_cam_rx_checks(safety, f1_bus: int) -> None:
safety.safety_rx_hook(common.make_msg(bus, addr, length))
def test_gm_camera_stock_acc_uses_base_rx_checks():
safety = libsafety_py.libsafety
safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_CAM)
safety.init_tests()
_prime_gm_base_rx_checks(safety, 0)
assert safety.safety_config_valid()
def _prime_gm_ascm_int_stock_cam_rx_checks(safety, f1_bus: int) -> None:
# This path should only accept the Volt/Malibu ASCM_INT stock-camera status on bus 0.
_prime_gm_base_rx_checks(safety, f1_bus)
def test_gm_ascm_int_stock_cam_f1_rx_pinning():
safety = libsafety_py.libsafety
safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_CAM | GMSafetyFlags.HW_ASCM_INT)
@@ -275,6 +302,17 @@ class TestGmCameraEVSafety(GmCameraAccEVRegenMixin, TestGmCameraSafety, TestGmEV
pass
class TestGmCameraNoCameraSafety(TestGmCameraSafety):
RELAY_MALFUNCTION_ADDRS = {0: (), 2: ()}
def setUp(self):
self.packer = CANPackerSafety("gm_global_a_powertrain_generated")
self.packer_chassis = CANPackerSafety("gm_global_a_chassis")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_CAM | GMSafetyFlags.FLAG_GM_NO_CAMERA)
self.safety.init_tests()
class TestGmCameraLongitudinalSafety(GmLongitudinalBase, TestGmCameraSafetyBase):
TX_MSGS = [[0x180, 0], [0x315, 0], [0x2CB, 0], [0x370, 0], [0x200, 0], [0x1E1, 0], [0x3D1, 0], [0xBD, 0], [0x1F5, 0], # pt bus
[0x184, 2]] # camera bus
@@ -298,6 +336,17 @@ class TestGmCameraLongitudinalEVSafety(GmCameraAccEVRegenMixin, TestGmCameraLong
pass
class TestGmCameraLongitudinalNoCameraSafety(TestGmCameraLongitudinalSafety):
RELAY_MALFUNCTION_ADDRS = {0: (), 2: ()}
def setUp(self):
self.packer = CANPackerSafety("gm_global_a_powertrain_generated")
self.packer_chassis = CANPackerSafety("gm_global_a_chassis")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_CAM | GMSafetyFlags.HW_CAM_LONG | GMSafetyFlags.FLAG_GM_NO_CAMERA)
self.safety.init_tests()
def interceptor_msg(gas, addr):
to_send = common.make_msg(0, addr, 6)
to_send[0].data[0] = (gas & 0xFF00) >> 8
@@ -400,6 +449,18 @@ class TestGmCcLongitudinalSafety(TestGmCameraSafety):
self.assertEqual(enabled, self._tx(self._button_msg(btn)))
class TestGmCcLongitudinalNoCameraSafety(TestGmCcLongitudinalSafety):
RELAY_MALFUNCTION_ADDRS = {0: (), 2: ()}
def setUp(self):
self.packer = CANPackerPanda("gm_global_a_powertrain_generated")
self.packer_chassis = CANPackerPanda("gm_global_a_chassis")
self.safety = libsafety_py.libsafety
self.safety.set_safety_hooks(CarParams.SafetyModel.gm, GMSafetyFlags.HW_CAM | GMSafetyFlags.FLAG_GM_NO_ACC |
GMSafetyFlags.FLAG_GM_CC_LONG | GMSafetyFlags.FLAG_GM_NO_CAMERA)
self.safety.init_tests()
class TestGmCcLongitudinalPandaSchedSafety(TestGmCcLongitudinalSafety):
FWD_BLACKLISTED_ADDRS = {2: [0x180, 0x370], 0: [0x184, 0x3D1]}
INTERCEPTOR_GAS_PRESSED = 596
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,2 +1,2 @@
extern const uint8_t gitversion[19];
const uint8_t gitversion[19] = "DEV-5ddabfcc-DEBUG";
const uint8_t gitversion[19] = "DEV-2b280bd5-DEBUG";
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
DEV-5ddabfcc-DEBUG
DEV-2b280bd5-DEBUG
+2 -2
View File
@@ -276,8 +276,8 @@ def migrate_pandaStates(msgs):
"TOYOTA_PRIUS": EPS_SCALE["TOYOTA_PRIUS"] | ToyotaSafetyFlags.STOCK_LONGITUDINAL,
"TOYOTA_RAV4": EPS_SCALE["TOYOTA_RAV4"] | ToyotaSafetyFlags.ALT_BRAKE,
"KIA_EV6": HyundaiSafetyFlags.EV_GAS | HyundaiSafetyFlags.CANFD_LKA_STEERING,
"CHEVROLET_VOLT": GMSafetyFlags.EV,
"CHEVROLET_BOLT_EUV": GMSafetyFlags.EV | GMSafetyFlags.HW_CAM,
"CHEVROLET_VOLT": 0,
"CHEVROLET_BOLT_EUV": GMSafetyFlags.HW_CAM,
}
# TODO: get new Ford route
safety_param_migration |= dict.fromkeys((set(FORD) - FORD.with_flags(FordFlags.CANFD)), FordSafetyFlags.LONG_CONTROL)