From c596c000aa7566abb0c706d5e467f13dc8616a75 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Tue, 10 Mar 2026 13:31:06 -0500 Subject: [PATCH] malibu --- panda/board/safety/safety_gm.h | 5 ++++- selfdrive/car/gm/interface.py | 13 +++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/panda/board/safety/safety_gm.h b/panda/board/safety/safety_gm.h index d924e8df1..eff88ba6f 100644 --- a/panda/board/safety/safety_gm.h +++ b/panda/board/safety/safety_gm.h @@ -263,6 +263,9 @@ static void gm_rx_hook(const CANPacket_t *to_push) { // ACC steering wheel buttons (GM_CAM is tied to the PCM) if ((addr == 0x1E1) && (!gm_pcm_cruise || gm_cc_long)) { int button = (GET_BYTE(to_push, 5) & 0x70U) >> 4; + // Malibu Hybrid pedal-long observed format uses byte3 bit0 set (typically 0x01/0x41) on ASCMSteeringButton. + // Don't treat that physical CANCEL frame as OP disengage. + bool malibu_cancel_passthrough = gm_bolt_2022_pedal && gm_pedal_long && ((GET_BYTE(to_push, 3) & 0x1U) != 0U); // enter controls on falling edge of set or rising edge of resume (avoids fault) bool set = (button != GM_BTN_SET) && (cruise_button_prev == GM_BTN_SET); @@ -272,7 +275,7 @@ static void gm_rx_hook(const CANPacket_t *to_push) { } // exit controls on cancel press - if (button == GM_BTN_CANCEL) { + if ((button == GM_BTN_CANCEL) && !malibu_cancel_passthrough) { controls_allowed = false; } diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 1bae56403..4cfed386f 100644 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -609,9 +609,15 @@ class CarInterface(CarInterfaceBase): ret, fp_ret = self.CS.update(self.cp, self.cp_cam, self.cp_loopback, frogpilot_toggles) # Don't add event if transitioning from INIT, unless it's to an actual button + cruise_button_map = BUTTONS_DICT + if self.CP.carFingerprint == CAR.CHEVROLET_MALIBU_HYBRID_CC and self.CP.openpilotLongitudinalControl: + # Malibu Hybrid only: keep all wheel-button functionality, but don't map CANCEL + # to ButtonType.cancel so OP long isn't disengaged by the physical cancel button. + cruise_button_map = {k: v for k, v in BUTTONS_DICT.items() if k != CruiseButtons.CANCEL} + if self.CS.cruise_buttons != CruiseButtons.UNPRESS or self.CS.prev_cruise_buttons != CruiseButtons.INIT: ret.buttonEvents = [ - *create_button_events(self.CS.cruise_buttons, self.CS.prev_cruise_buttons, BUTTONS_DICT, + *create_button_events(self.CS.cruise_buttons, self.CS.prev_cruise_buttons, cruise_button_map, unpressed_btn=CruiseButtons.UNPRESS), *create_button_events(self.CS.distance_button, self.CS.prev_distance_button, {1: ButtonType.gapAdjustCruise}), @@ -619,11 +625,6 @@ class CarInterface(CarInterfaceBase): {1: FrogPilotButtonType.lkas}), ] - # Malibu Hybrid only: allow physical CANCEL to cancel stock cruise without disabling OP long. - # Brake still disengages through normal common-event handling. - if self.CP.carFingerprint == CAR.CHEVROLET_MALIBU_HYBRID_CC and self.CP.openpilotLongitudinalControl: - ret.buttonEvents = [b for b in ret.buttonEvents if b.type != ButtonType.cancel] - # The ECM allows enabling on falling edge of set, but only rising edge of resume events = self.create_common_events(ret, extra_gears=[GearShifter.sport, GearShifter.low, GearShifter.eco, GearShifter.manumatic],