version: sunnypilot v2026.002.000 (staging) date: 2026-07-21T07:44:02 master commit: 2c334ede443d7391d27575af8c854a095ba702a8
172 lines
5.0 KiB
Python
172 lines
5.0 KiB
Python
import os
|
|
import subprocess
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
from cffi import FFI
|
|
|
|
from opendbc.safety import LEN_TO_DLC
|
|
|
|
libsafety_dir = os.path.dirname(os.path.abspath(__file__))
|
|
|
|
|
|
def _build_libsafety(release: bool = False) -> str:
|
|
"""Compile libsafety.so to a temp file and return its path."""
|
|
root = str(Path(libsafety_dir).parents[3])
|
|
safety_c = os.path.join(libsafety_dir, "safety.c")
|
|
|
|
cflags = [
|
|
'-Wall', '-Wextra', '-Werror', '-nostdlib', '-fno-builtin',
|
|
'-std=gnu11', '-Wfatal-errors', '-Wno-pointer-to-int-cast',
|
|
'-g', '-O0', '-fno-omit-frame-pointer',
|
|
]
|
|
ldflags = [
|
|
'-fsanitize=undefined', '-fno-sanitize-recover=undefined',
|
|
]
|
|
if not release:
|
|
cflags += ['-DALLOW_DEBUG', '-fprofile-arcs', '-ftest-coverage']
|
|
ldflags += ['-fprofile-arcs', '-ftest-coverage']
|
|
|
|
fd, safety_os = tempfile.mkstemp(suffix='.os', dir=libsafety_dir)
|
|
os.close(fd)
|
|
fd, libsafety_so = tempfile.mkstemp(suffix='.so')
|
|
os.close(fd)
|
|
|
|
subprocess.check_call(['cc', '-fPIC', *cflags, '-I', root, '-c', safety_c, '-o', safety_os])
|
|
subprocess.check_call(['cc', '-shared', safety_os, '-o', libsafety_so, *ldflags])
|
|
return libsafety_so
|
|
|
|
|
|
ffi = FFI()
|
|
|
|
ffi.cdef("""
|
|
typedef struct {
|
|
unsigned char fd : 1;
|
|
unsigned char bus : 3;
|
|
unsigned char data_len_code : 4;
|
|
unsigned char rejected : 1;
|
|
unsigned char returned : 1;
|
|
unsigned char extended : 1;
|
|
unsigned int addr : 29;
|
|
unsigned char checksum;
|
|
unsigned char data[64];
|
|
} CANPacket_t;
|
|
""", packed=True)
|
|
class CANPacket:
|
|
pass
|
|
|
|
ffi.cdef("""
|
|
bool safety_rx_hook(CANPacket_t *msg);
|
|
bool safety_tx_hook(CANPacket_t *msg);
|
|
int safety_fwd_hook(int bus_num, int addr);
|
|
int set_safety_hooks(uint16_t mode, uint16_t param);
|
|
|
|
void set_controls_allowed(bool c);
|
|
bool get_controls_allowed(void);
|
|
bool get_longitudinal_allowed(void);
|
|
void set_alternative_experience(int mode);
|
|
int get_alternative_experience(void);
|
|
void set_relay_malfunction(bool c);
|
|
bool get_relay_malfunction(void);
|
|
bool get_gas_pressed_prev(void);
|
|
void set_gas_pressed_prev(bool);
|
|
bool get_brake_pressed_prev(void);
|
|
bool get_regen_braking_prev(void);
|
|
bool get_steering_disengage_prev(void);
|
|
bool get_acc_main_on(void);
|
|
float get_vehicle_speed_min(void);
|
|
float get_vehicle_speed_max(void);
|
|
int get_current_safety_mode(void);
|
|
int get_current_safety_param(void);
|
|
|
|
void set_torque_meas(int min, int max);
|
|
int get_torque_meas_min(void);
|
|
int get_torque_meas_max(void);
|
|
void set_torque_driver(int min, int max);
|
|
int get_torque_driver_min(void);
|
|
int get_torque_driver_max(void);
|
|
void set_desired_torque_last(int t);
|
|
void set_rt_torque_last(int t);
|
|
void set_desired_angle_last(int t);
|
|
int get_desired_angle_last();
|
|
void set_angle_meas(int min, int max);
|
|
int get_angle_meas_min(void);
|
|
int get_angle_meas_max(void);
|
|
void set_desired_curvature_last(int t);
|
|
int get_desired_curvature_last();
|
|
void set_curvature_meas(int min, int max);
|
|
int get_curvature_meas_min(void);
|
|
int get_curvature_meas_max(void);
|
|
|
|
bool get_cruise_engaged_prev(void);
|
|
void set_cruise_engaged_prev(bool engaged);
|
|
bool get_vehicle_moving(void);
|
|
void set_timer(uint32_t t);
|
|
|
|
void safety_tick_current_safety_config();
|
|
bool safety_config_valid();
|
|
|
|
void init_tests(void);
|
|
|
|
void set_honda_fwd_brake(bool c);
|
|
bool get_honda_fwd_brake(void);
|
|
void set_honda_alt_brake_msg(bool c);
|
|
void set_honda_bosch_long(bool c);
|
|
int get_honda_hw(void);
|
|
|
|
void mutation_set_active_mutant(int id);
|
|
int mutation_get_active_mutant(void);
|
|
|
|
void ignition_can_hook(const CANPacket_t *msg);
|
|
bool get_ignition_can(void);
|
|
void set_ignition_can(bool c);
|
|
|
|
bool get_controls_allowed_lateral(void);
|
|
bool get_controls_requested_lateral(void);
|
|
void set_current_safety_param_sp(uint16_t param);
|
|
uint16_t get_current_safety_param_sp(void);
|
|
bool get_enable_mads(void);
|
|
bool get_disengage_lateral_on_brake(void);
|
|
bool get_pause_lateral_on_brake(void);
|
|
void set_mads_button_press(int mads_button_press);
|
|
void set_controls_allowed_lateral(bool c);
|
|
void set_controls_requested_lateral(bool c);
|
|
bool get_mads_acc_main(void);
|
|
void set_acc_main_on(bool c);
|
|
int get_mads_button_press(void);
|
|
void mads_set_current_disengage_reason(int reason);
|
|
int mads_get_current_disengage_reason(void);
|
|
int get_temp_debug(void);
|
|
uint32_t get_acc_main_on_mismatches(void);
|
|
void set_mads_params(bool enable_mads, bool disengage_lateral_on_brake, bool pause_lateral_on_brake);
|
|
void mads_apply_alternative_experience(int mode);
|
|
void tick_mads_state(bool vm, bool acc_main, bool op_allowed, bool braking, bool steering_disengage);
|
|
void set_heartbeat_engaged_mads(bool c);
|
|
void mads_heartbeat_engaged_check(void);
|
|
void set_steering_disengage(bool c);
|
|
int get_gas_interceptor_prev(void);
|
|
""")
|
|
|
|
class LibSafety:
|
|
pass
|
|
libsafety: LibSafety
|
|
|
|
def load(path):
|
|
global libsafety
|
|
libsafety = ffi.dlopen(str(path))
|
|
|
|
def __getattr__(name):
|
|
if name == "libsafety":
|
|
load(_build_libsafety())
|
|
return libsafety
|
|
raise AttributeError(name)
|
|
|
|
def make_CANPacket(addr: int, bus: int, dat):
|
|
ret = ffi.new('CANPacket_t *')
|
|
ret[0].extended = 1 if addr >= 0x800 else 0
|
|
ret[0].addr = addr
|
|
ret[0].data_len_code = LEN_TO_DLC[len(dat)]
|
|
ret[0].bus = bus
|
|
ret[0].data = bytes(dat)
|
|
return ret
|