mirror of https://github.com/commaai/panda.git
184 lines
6.2 KiB
C
184 lines
6.2 KiB
C
// Safety-relevant CAN messages for Ford vehicles.
|
|
#define MSG_EngBrakeData 0x165 // RX from PCM, for driver brake pedal and cruise state
|
|
#define MSG_EngVehicleSpThrottle 0x204 // RX from PCM, for driver throttle input
|
|
#define MSG_DesiredTorqBrk 0x213 // RX from ABS, for standstill state
|
|
#define MSG_Steering_Data_FD1 0x083 // TX by OP, various driver switches and LKAS/CC buttons
|
|
#define MSG_ACCDATA_3 0x18A // TX by OP, ACC/TJA user interface
|
|
#define MSG_Lane_Assist_Data1 0x3CA // TX by OP, Lane Keep Assist
|
|
#define MSG_LateralMotionControl 0x3D3 // TX by OP, Traffic Jam Assist
|
|
#define MSG_IPMA_Data 0x3D8 // TX by OP, IPMA and LKAS user interface
|
|
|
|
// CAN bus numbers.
|
|
#define FORD_MAIN_BUS 0U
|
|
#define FORD_CAM_BUS 2U
|
|
|
|
const CanMsg FORD_TX_MSGS[] = {
|
|
{MSG_Steering_Data_FD1, 0, 8},
|
|
{MSG_Steering_Data_FD1, 2, 8},
|
|
{MSG_ACCDATA_3, 0, 8},
|
|
{MSG_Lane_Assist_Data1, 0, 8},
|
|
{MSG_LateralMotionControl, 0, 8},
|
|
{MSG_IPMA_Data, 0, 8},
|
|
};
|
|
#define FORD_TX_LEN (sizeof(FORD_TX_MSGS) / sizeof(FORD_TX_MSGS[0]))
|
|
|
|
AddrCheckStruct ford_addr_checks[] = {
|
|
{.msg = {{MSG_EngBrakeData, 0, 8, .expected_timestep = 100000U}, { 0 }, { 0 }}},
|
|
{.msg = {{MSG_EngVehicleSpThrottle, 0, 8, .expected_timestep = 10000U}, { 0 }, { 0 }}},
|
|
{.msg = {{MSG_DesiredTorqBrk, 0, 8, .expected_timestep = 20000U}, { 0 }, { 0 }}},
|
|
};
|
|
#define FORD_ADDR_CHECK_LEN (sizeof(ford_addr_checks) / sizeof(ford_addr_checks[0]))
|
|
addr_checks ford_rx_checks = {ford_addr_checks, FORD_ADDR_CHECK_LEN};
|
|
|
|
#define INACTIVE_CURVATURE 1000U
|
|
#define INACTIVE_CURVATURE_RATE 4096U
|
|
#define INACTIVE_PATH_OFFSET 512U
|
|
#define INACTIVE_PATH_ANGLE 1000U
|
|
|
|
static bool ford_lkas_msg_check(int addr) {
|
|
return (addr == MSG_ACCDATA_3)
|
|
|| (addr == MSG_Lane_Assist_Data1)
|
|
|| (addr == MSG_LateralMotionControl)
|
|
|| (addr == MSG_IPMA_Data);
|
|
}
|
|
|
|
static int ford_rx_hook(CANPacket_t *to_push) {
|
|
bool valid = addr_safety_check(to_push, &ford_rx_checks, NULL, NULL, NULL);
|
|
|
|
if (valid && (GET_BUS(to_push) == FORD_MAIN_BUS)) {
|
|
int addr = GET_ADDR(to_push);
|
|
|
|
// Update in motion state from standstill signal
|
|
if (addr == MSG_DesiredTorqBrk) {
|
|
// Signal: VehStop_D_Stat
|
|
vehicle_moving = ((GET_BYTE(to_push, 3) >> 3) & 0x3U) == 0U;
|
|
}
|
|
|
|
// Update gas pedal
|
|
if (addr == MSG_EngVehicleSpThrottle) {
|
|
// Pedal position: (0.1 * val) in percent
|
|
// Signal: ApedPos_Pc_ActlArb
|
|
gas_pressed = (((GET_BYTE(to_push, 0) & 0x03U) << 8) | GET_BYTE(to_push, 1)) > 0U;
|
|
}
|
|
|
|
// Update brake pedal and cruise state
|
|
if (addr == MSG_EngBrakeData) {
|
|
// Signal: BpedDrvAppl_D_Actl
|
|
brake_pressed = ((GET_BYTE(to_push, 0) >> 4) & 0x3U) == 2U;
|
|
|
|
// Signal: CcStat_D_Actl
|
|
unsigned int cruise_state = GET_BYTE(to_push, 1) & 0x07U;
|
|
bool cruise_engaged = (cruise_state == 4U) || (cruise_state == 5U);
|
|
pcm_cruise_check(cruise_engaged);
|
|
}
|
|
|
|
// If steering controls messages are received on the destination bus, it's an indication
|
|
// that the relay might be malfunctioning.
|
|
generic_rx_checks(ford_lkas_msg_check(addr));
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
|
|
static int ford_tx_hook(CANPacket_t *to_send) {
|
|
|
|
int tx = 1;
|
|
int addr = GET_ADDR(to_send);
|
|
|
|
if (!msg_allowed(to_send, FORD_TX_MSGS, FORD_TX_LEN)) {
|
|
tx = 0;
|
|
}
|
|
|
|
// Safety check for Steering_Data_FD1 button signals
|
|
// Note: Many other signals in this message are not relevant to safety (e.g. blinkers, wiper switches, high beam)
|
|
// which we passthru in OP.
|
|
if (addr == MSG_Steering_Data_FD1) {
|
|
// Violation if resume button is pressed while controls not allowed, or
|
|
// if cancel button is pressed when cruise isn't engaged.
|
|
bool violation = false;
|
|
violation |= (GET_BIT(to_send, 8U) == 1U) && !cruise_engaged_prev; // Signal: CcAslButtnCnclPress (cancel)
|
|
violation |= (GET_BIT(to_send, 25U) == 1U) && !controls_allowed; // Signal: CcAsllButtnResPress (resume)
|
|
|
|
if (violation) {
|
|
tx = 0;
|
|
}
|
|
}
|
|
|
|
// Safety check for Lane_Assist_Data1 action
|
|
if (addr == MSG_Lane_Assist_Data1) {
|
|
// Do not allow steering using Lane_Assist_Data1 (Lane-Departure Aid).
|
|
// This message must be sent for Lane Centering to work, and can include
|
|
// values such as the steering angle or lane curvature for debugging,
|
|
// but the action (LkaActvStats_D2_Req) must be set to zero.
|
|
unsigned int action = GET_BYTE(to_send, 0) >> 5;
|
|
if (action != 0U) {
|
|
tx = 0;
|
|
}
|
|
}
|
|
|
|
// Safety check for LateralMotionControl action
|
|
if (addr == MSG_LateralMotionControl) {
|
|
// Signal: LatCtl_D_Rq
|
|
unsigned int steer_control_type = (GET_BYTE(to_send, 4) >> 2) & 0x7U;
|
|
unsigned int curvature = (GET_BYTE(to_send, 0) << 3) | (GET_BYTE(to_send, 1) >> 5);
|
|
unsigned int curvature_rate = ((GET_BYTE(to_send, 1) & 0x1FU) << 8) | GET_BYTE(to_send, 2);
|
|
unsigned int path_angle = (GET_BYTE(to_send, 3) << 3) | (GET_BYTE(to_send, 4) >> 5);
|
|
unsigned int path_offset = (GET_BYTE(to_send, 5) << 2) | (GET_BYTE(to_send, 6) >> 6);
|
|
|
|
// These signals are not yet tested with the current safety limits
|
|
if ((curvature_rate != INACTIVE_CURVATURE_RATE) || (path_angle != INACTIVE_PATH_ANGLE) || (path_offset != INACTIVE_PATH_OFFSET)) {
|
|
tx = 0;
|
|
}
|
|
|
|
// No steer control allowed when controls are not allowed
|
|
bool steer_control_enabled = (steer_control_type != 0U) || (curvature != INACTIVE_CURVATURE);
|
|
if (!controls_allowed && steer_control_enabled) {
|
|
tx = 0;
|
|
}
|
|
}
|
|
|
|
// 1 allows the message through
|
|
return tx;
|
|
}
|
|
|
|
static int ford_fwd_hook(int bus_num, CANPacket_t *to_fwd) {
|
|
int addr = GET_ADDR(to_fwd);
|
|
int bus_fwd = -1;
|
|
|
|
switch (bus_num) {
|
|
case FORD_MAIN_BUS: {
|
|
// Forward all traffic from bus 0 onward
|
|
bus_fwd = FORD_CAM_BUS;
|
|
break;
|
|
}
|
|
case FORD_CAM_BUS: {
|
|
// Block stock LKAS messages
|
|
if (!ford_lkas_msg_check(addr)) {
|
|
bus_fwd = FORD_MAIN_BUS;
|
|
}
|
|
break;
|
|
}
|
|
default: {
|
|
// No other buses should be in use; fallback to do-not-forward
|
|
bus_fwd = -1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return bus_fwd;
|
|
}
|
|
|
|
static const addr_checks* ford_init(uint16_t param) {
|
|
UNUSED(param);
|
|
|
|
return &ford_rx_checks;
|
|
}
|
|
|
|
const safety_hooks ford_hooks = {
|
|
.init = ford_init,
|
|
.rx = ford_rx_hook,
|
|
.tx = ford_tx_hook,
|
|
.tx_lin = nooutput_tx_lin_hook,
|
|
.fwd = ford_fwd_hook,
|
|
};
|