GCC Code Coverage Report


Directory: ./
File: safety/safety_ford.h
Date: 2025-02-27 09:09:49
Exec Total Coverage
Lines: 153 153 100.0%
Functions: 9 9 100.0%
Branches: 118 125 94.4%

Line Branch Exec Source
1 #pragma once
2
3 #include "safety_declarations.h"
4
5 // Safety-relevant CAN messages for Ford vehicles.
6 #define FORD_EngBrakeData 0x165 // RX from PCM, for driver brake pedal and cruise state
7 #define FORD_EngVehicleSpThrottle 0x204 // RX from PCM, for driver throttle input
8 #define FORD_DesiredTorqBrk 0x213 // RX from ABS, for standstill state
9 #define FORD_BrakeSysFeatures 0x415 // RX from ABS, for vehicle speed
10 #define FORD_EngVehicleSpThrottle2 0x202 // RX from PCM, for second vehicle speed
11 #define FORD_Yaw_Data_FD1 0x91 // RX from RCM, for yaw rate
12 #define FORD_Steering_Data_FD1 0x083 // TX by OP, various driver switches and LKAS/CC buttons
13 #define FORD_ACCDATA 0x186 // TX by OP, ACC controls
14 #define FORD_ACCDATA_3 0x18A // TX by OP, ACC/TJA user interface
15 #define FORD_Lane_Assist_Data1 0x3CA // TX by OP, Lane Keep Assist
16 #define FORD_LateralMotionControl 0x3D3 // TX by OP, Lateral Control message
17 #define FORD_LateralMotionControl2 0x3D6 // TX by OP, alternate Lateral Control message
18 #define FORD_IPMA_Data 0x3D8 // TX by OP, IPMA and LKAS user interface
19
20 // CAN bus numbers.
21 #define FORD_MAIN_BUS 0U
22 #define FORD_CAM_BUS 2U
23
24 601038 static uint8_t ford_get_counter(const CANPacket_t *to_push) {
25 601038 int addr = GET_ADDR(to_push);
26
27 601038 uint8_t cnt = 0;
28
2/2
✓ Branch 0 taken 295929 times.
✓ Branch 1 taken 305109 times.
601038 if (addr == FORD_BrakeSysFeatures) {
29 // Signal: VehVActlBrk_No_Cnt
30 295929 cnt = (GET_BYTE(to_push, 2) >> 2) & 0xFU;
31
1/2
✓ Branch 0 taken 305109 times.
✗ Branch 1 not taken.
305109 } else if (addr == FORD_Yaw_Data_FD1) {
32 // Signal: VehRollYaw_No_Cnt
33 305109 cnt = GET_BYTE(to_push, 5);
34 } else {
35 }
36 601038 return cnt;
37 }
38
39 601038 static uint32_t ford_get_checksum(const CANPacket_t *to_push) {
40 601038 int addr = GET_ADDR(to_push);
41
42 601038 uint8_t chksum = 0;
43
2/2
✓ Branch 0 taken 295929 times.
✓ Branch 1 taken 305109 times.
601038 if (addr == FORD_BrakeSysFeatures) {
44 // Signal: VehVActlBrk_No_Cs
45 295929 chksum = GET_BYTE(to_push, 3);
46
1/2
✓ Branch 0 taken 305109 times.
✗ Branch 1 not taken.
305109 } else if (addr == FORD_Yaw_Data_FD1) {
47 // Signal: VehRollYawW_No_Cs
48 305109 chksum = GET_BYTE(to_push, 4);
49 } else {
50 }
51 601038 return chksum;
52 }
53
54 601038 static uint32_t ford_compute_checksum(const CANPacket_t *to_push) {
55 601038 int addr = GET_ADDR(to_push);
56
57 601038 uint8_t chksum = 0;
58
2/2
✓ Branch 0 taken 295929 times.
✓ Branch 1 taken 305109 times.
601038 if (addr == FORD_BrakeSysFeatures) {
59 295929 chksum += GET_BYTE(to_push, 0) + GET_BYTE(to_push, 1); // Veh_V_ActlBrk
60 295929 chksum += GET_BYTE(to_push, 2) >> 6; // VehVActlBrk_D_Qf
61 295929 chksum += (GET_BYTE(to_push, 2) >> 2) & 0xFU; // VehVActlBrk_No_Cnt
62 295929 chksum = 0xFFU - chksum;
63
1/2
✓ Branch 0 taken 305109 times.
✗ Branch 1 not taken.
305109 } else if (addr == FORD_Yaw_Data_FD1) {
64 305109 chksum += GET_BYTE(to_push, 0) + GET_BYTE(to_push, 1); // VehRol_W_Actl
65 305109 chksum += GET_BYTE(to_push, 2) + GET_BYTE(to_push, 3); // VehYaw_W_Actl
66 305109 chksum += GET_BYTE(to_push, 5); // VehRollYaw_No_Cnt
67 305109 chksum += GET_BYTE(to_push, 6) >> 6; // VehRolWActl_D_Qf
68 305109 chksum += (GET_BYTE(to_push, 6) >> 4) & 0x3U; // VehYawWActl_D_Qf
69 305109 chksum = 0xFFU - chksum;
70 } else {
71 }
72
73 601038 return chksum;
74 }
75
76 625107 static bool ford_get_quality_flag_valid(const CANPacket_t *to_push) {
77 625107 int addr = GET_ADDR(to_push);
78
79 625107 bool valid = false;
80
2/2
✓ Branch 0 taken 295929 times.
✓ Branch 1 taken 329178 times.
625107 if (addr == FORD_BrakeSysFeatures) {
81 295929 valid = (GET_BYTE(to_push, 2) >> 6) == 0x3U; // VehVActlBrk_D_Qf
82
2/2
✓ Branch 0 taken 24069 times.
✓ Branch 1 taken 305109 times.
329178 } else if (addr == FORD_EngVehicleSpThrottle2) {
83 24069 valid = ((GET_BYTE(to_push, 4) >> 5) & 0x3U) == 0x3U; // VehVActlEng_D_Qf
84
1/2
✓ Branch 0 taken 305109 times.
✗ Branch 1 not taken.
305109 } else if (addr == FORD_Yaw_Data_FD1) {
85 305109 valid = ((GET_BYTE(to_push, 6) >> 4) & 0x3U) == 0x3U; // VehYawWActl_D_Qf
86 } else {
87 }
88 625107 return valid;
89 }
90
91 static bool ford_longitudinal = false;
92
93 #define FORD_INACTIVE_CURVATURE 1000U
94 #define FORD_INACTIVE_CURVATURE_RATE 4096U
95 #define FORD_INACTIVE_PATH_OFFSET 512U
96 #define FORD_INACTIVE_PATH_ANGLE 1000U
97
98 #define FORD_CANFD_INACTIVE_CURVATURE_RATE 1024U
99
100 #define FORD_MAX_SPEED_DELTA 2.0 // m/s
101
102 642006 static bool ford_lkas_msg_check(int addr) {
103 return (addr == FORD_ACCDATA_3)
104
2/2
✓ Branch 0 taken 641994 times.
✓ Branch 1 taken 6 times.
642000 || (addr == FORD_Lane_Assist_Data1)
105
2/2
✓ Branch 0 taken 641988 times.
✓ Branch 1 taken 6 times.
641994 || (addr == FORD_LateralMotionControl)
106
2/2
✓ Branch 0 taken 641982 times.
✓ Branch 1 taken 6 times.
641988 || (addr == FORD_LateralMotionControl2)
107
4/4
✓ Branch 0 taken 642000 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 641976 times.
1284006 || (addr == FORD_IPMA_Data);
108 }
109
110 // Curvature rate limits
111 static const SteeringLimits FORD_STEERING_LIMITS = {
112 .max_steer = 1000,
113 .angle_deg_to_can = 50000, // 1 / (2e-5) rad to can
114 .max_angle_error = 100, // 0.002 * FORD_STEERING_LIMITS.angle_deg_to_can
115 .angle_rate_up_lookup = {
116 {5., 25., 25.},
117 {0.00045, 0.0001, 0.0001}
118 },
119 .angle_rate_down_lookup = {
120 {5., 25., 25.},
121 {0.00045, 0.00015, 0.00015}
122 },
123
124 // no blending at low speed due to lack of torque wind-up and inaccurate current curvature
125 .angle_error_min_speed = 10.0, // m/s
126
127 .enforce_angle_error = true,
128 .inactive_angle_is_zero = true,
129 };
130
131 650454 static void ford_rx_hook(const CANPacket_t *to_push) {
132
2/2
✓ Branch 0 taken 633558 times.
✓ Branch 1 taken 16896 times.
650454 if (GET_BUS(to_push) == FORD_MAIN_BUS) {
133 633558 int addr = GET_ADDR(to_push);
134
135 // Update in motion state from standstill signal
136
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 633534 times.
633558 if (addr == FORD_DesiredTorqBrk) {
137 // Signal: VehStop_D_Stat
138 24 vehicle_moving = ((GET_BYTE(to_push, 3) >> 3) & 0x3U) != 1U;
139 }
140
141 // Update vehicle speed
142
2/2
✓ Branch 0 taken 295890 times.
✓ Branch 1 taken 337668 times.
633558 if (addr == FORD_BrakeSysFeatures) {
143 // Signal: Veh_V_ActlBrk
144 295890 UPDATE_VEHICLE_SPEED(((GET_BYTE(to_push, 0) << 8) | GET_BYTE(to_push, 1)) * 0.01 / 3.6);
145 }
146
147 // Check vehicle speed against a second source
148
2/2
✓ Branch 0 taken 24033 times.
✓ Branch 1 taken 609525 times.
633558 if (addr == FORD_EngVehicleSpThrottle2) {
149 // Disable controls if speeds from ABS and PCM ECUs are too far apart.
150 // Signal: Veh_V_ActlEng
151 24033 float filtered_pcm_speed = ((GET_BYTE(to_push, 6) << 8) | GET_BYTE(to_push, 7)) * 0.01 / 3.6;
152
2/2
✓ Branch 0 taken 11760 times.
✓ Branch 1 taken 12273 times.
24033 bool is_invalid_speed = ABS(filtered_pcm_speed - ((float)vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR)) > FORD_MAX_SPEED_DELTA;
153
2/2
✓ Branch 0 taken 13710 times.
✓ Branch 1 taken 10323 times.
24033 if (is_invalid_speed) {
154 13710 controls_allowed = false;
155 }
156 }
157
158 // Update vehicle yaw rate
159
2/2
✓ Branch 0 taken 305070 times.
✓ Branch 1 taken 328488 times.
633558 if (addr == FORD_Yaw_Data_FD1) {
160 // Signal: VehYaw_W_Actl
161 305070 float ford_yaw_rate = (((GET_BYTE(to_push, 2) << 8U) | GET_BYTE(to_push, 3)) * 0.0002) - 6.5;
162
2/2
✓ Branch 0 taken 304968 times.
✓ Branch 1 taken 102 times.
305070 float current_curvature = ford_yaw_rate / MAX(vehicle_speed.values[0] / VEHICLE_SPEED_FACTOR, 0.1);
163 // convert current curvature into units on CAN for comparison with desired curvature
164 305070 update_sample(&angle_meas, ROUND(current_curvature * FORD_STEERING_LIMITS.angle_deg_to_can));
165 }
166
167 // Update gas pedal
168
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 633525 times.
633558 if (addr == FORD_EngVehicleSpThrottle) {
169 // Pedal position: (0.1 * val) in percent
170 // Signal: ApedPos_Pc_ActlArb
171 33 gas_pressed = (((GET_BYTE(to_push, 0) & 0x03U) << 8) | GET_BYTE(to_push, 1)) > 0U;
172 }
173
174 // Update brake pedal and cruise state
175
2/2
✓ Branch 0 taken 78 times.
✓ Branch 1 taken 633480 times.
633558 if (addr == FORD_EngBrakeData) {
176 // Signal: BpedDrvAppl_D_Actl
177 78 brake_pressed = ((GET_BYTE(to_push, 0) >> 4) & 0x3U) == 2U;
178
179 // Signal: CcStat_D_Actl
180 78 unsigned int cruise_state = GET_BYTE(to_push, 1) & 0x07U;
181
3/4
✓ Branch 0 taken 78 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 30 times.
✓ Branch 3 taken 48 times.
78 bool cruise_engaged = (cruise_state == 4U) || (cruise_state == 5U);
182 78 pcm_cruise_check(cruise_engaged);
183 }
184
185 // If steering controls messages are received on the destination bus, it's an indication
186 // that the relay might be malfunctioning.
187 633558 bool stock_ecu_detected = ford_lkas_msg_check(addr);
188
2/2
✓ Branch 0 taken 422372 times.
✓ Branch 1 taken 211186 times.
633558 if (ford_longitudinal) {
189
4/4
✓ Branch 0 taken 422362 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 422360 times.
422372 stock_ecu_detected = stock_ecu_detected || (addr == FORD_ACCDATA);
190 }
191 633558 generic_rx_checks(stock_ecu_detected);
192 }
193
194 650454 }
195
196 50482 static bool ford_tx_hook(const CANPacket_t *to_send) {
197 const LongitudinalLimits FORD_LONG_LIMITS = {
198 // acceleration cmd limits (used for brakes)
199 // Signal: AccBrkTot_A_Rq
200 .max_accel = 5641, // 1.9999 m/s^s
201 .min_accel = 4231, // -3.4991 m/s^2
202 .inactive_accel = 5128, // -0.0008 m/s^2
203
204 // gas cmd limits
205 // Signal: AccPrpl_A_Rq & AccPrpl_A_Pred
206 .max_gas = 700, // 2.0 m/s^2
207 .min_gas = 450, // -0.5 m/s^2
208 .inactive_gas = 0, // -5.0 m/s^2
209 };
210
211 50482 bool tx = true;
212
213 50482 int addr = GET_ADDR(to_send);
214
215 // Safety check for ACCDATA accel and brake requests
216
2/2
✓ Branch 0 taken 2062 times.
✓ Branch 1 taken 48420 times.
50482 if (addr == FORD_ACCDATA) {
217 // Signal: AccPrpl_A_Rq
218 2062 int gas = ((GET_BYTE(to_send, 6) & 0x3U) << 8) | GET_BYTE(to_send, 7);
219 // Signal: AccPrpl_A_Pred
220 2062 int gas_pred = ((GET_BYTE(to_send, 2) & 0x3U) << 8) | GET_BYTE(to_send, 3);
221 // Signal: AccBrkTot_A_Rq
222 2062 int accel = ((GET_BYTE(to_send, 0) & 0x1FU) << 8) | GET_BYTE(to_send, 1);
223 // Signal: CmbbDeny_B_Actl
224 2062 bool cmbb_deny = GET_BIT(to_send, 37U);
225
226 // Signal: AccBrkPrchg_B_Rq & AccBrkDecel_B_Rq
227
3/4
✓ Branch 0 taken 1032 times.
✓ Branch 1 taken 1030 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1032 times.
2062 bool brake_actuation = GET_BIT(to_send, 54U) || GET_BIT(to_send, 55U);
228
229 2062 bool violation = false;
230 2062 violation |= longitudinal_accel_checks(accel, FORD_LONG_LIMITS);
231 2062 violation |= longitudinal_gas_checks(gas, FORD_LONG_LIMITS);
232 2062 violation |= longitudinal_gas_checks(gas_pred, FORD_LONG_LIMITS);
233
234 // Safety check for stock AEB
235 2062 violation |= cmbb_deny; // do not prevent stock AEB actuation
236
237
4/4
✓ Branch 1 taken 1032 times.
✓ Branch 2 taken 1030 times.
✓ Branch 3 taken 380 times.
✓ Branch 4 taken 652 times.
2062 violation |= !get_longitudinal_allowed() && brake_actuation;
238
239
2/2
✓ Branch 0 taken 1504 times.
✓ Branch 1 taken 558 times.
2062 if (violation) {
240 1504 tx = false;
241 }
242 }
243
244 // Safety check for Steering_Data_FD1 button signals
245 // Note: Many other signals in this message are not relevant to safety (e.g. blinkers, wiper switches, high beam)
246 // which we passthru in OP.
247
2/2
✓ Branch 0 taken 42 times.
✓ Branch 1 taken 50440 times.
50482 if (addr == FORD_Steering_Data_FD1) {
248 // Violation if resume button is pressed while controls not allowed, or
249 // if cancel button is pressed when cruise isn't engaged.
250 42 bool violation = false;
251
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
42 violation |= GET_BIT(to_send, 8U) && !cruise_engaged_prev; // Signal: CcAslButtnCnclPress (cancel)
252
4/4
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 6 times.
42 violation |= GET_BIT(to_send, 25U) && !controls_allowed; // Signal: CcAsllButtnResPress (resume)
253
254
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 30 times.
42 if (violation) {
255 12 tx = false;
256 }
257 }
258
259 // Safety check for Lane_Assist_Data1 action
260
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 50473 times.
50482 if (addr == FORD_Lane_Assist_Data1) {
261 // Do not allow steering using Lane_Assist_Data1 (Lane-Departure Aid).
262 // This message must be sent for Lane Centering to work, and can include
263 // values such as the steering angle or lane curvature for debugging,
264 // but the action (LkaActvStats_D2_Req) must be set to zero.
265 9 unsigned int action = GET_BYTE(to_send, 0) >> 5;
266
2/2
✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
9 if (action != 0U) {
267 6 tx = false;
268 }
269 }
270
271 // Safety check for LateralMotionControl action
272
2/2
✓ Branch 0 taken 16121 times.
✓ Branch 1 taken 34361 times.
50482 if (addr == FORD_LateralMotionControl) {
273 // Signal: LatCtl_D_Rq
274 16121 bool steer_control_enabled = ((GET_BYTE(to_send, 4) >> 2) & 0x7U) != 0U;
275 16121 unsigned int raw_curvature = (GET_BYTE(to_send, 0) << 3) | (GET_BYTE(to_send, 1) >> 5);
276 16121 unsigned int raw_curvature_rate = ((GET_BYTE(to_send, 1) & 0x1FU) << 8) | GET_BYTE(to_send, 2);
277 16121 unsigned int raw_path_angle = (GET_BYTE(to_send, 3) << 3) | (GET_BYTE(to_send, 4) >> 5);
278 16121 unsigned int raw_path_offset = (GET_BYTE(to_send, 5) << 2) | (GET_BYTE(to_send, 6) >> 6);
279
280 // These signals are not yet tested with the current safety limits
281
6/6
✓ Branch 0 taken 6440 times.
✓ Branch 1 taken 9681 times.
✓ Branch 2 taken 2040 times.
✓ Branch 3 taken 4400 times.
✓ Branch 4 taken 400 times.
✓ Branch 5 taken 1640 times.
16121 bool violation = (raw_curvature_rate != FORD_INACTIVE_CURVATURE_RATE) || (raw_path_angle != FORD_INACTIVE_PATH_ANGLE) || (raw_path_offset != FORD_INACTIVE_PATH_OFFSET);
282
283 // Check angle error and steer_control_enabled
284 16121 int desired_curvature = raw_curvature - FORD_INACTIVE_CURVATURE; // /FORD_STEERING_LIMITS.angle_deg_to_can to get real curvature
285 16121 violation |= steer_angle_cmd_checks(desired_curvature, steer_control_enabled, FORD_STEERING_LIMITS);
286
287
2/2
✓ Branch 0 taken 15299 times.
✓ Branch 1 taken 822 times.
16121 if (violation) {
288 15299 tx = false;
289 }
290 }
291
292 // Safety check for LateralMotionControl2 action
293
2/2
✓ Branch 0 taken 32242 times.
✓ Branch 1 taken 18240 times.
50482 if (addr == FORD_LateralMotionControl2) {
294 // Signal: LatCtl_D2_Rq
295 32242 bool steer_control_enabled = ((GET_BYTE(to_send, 0) >> 4) & 0x7U) != 0U;
296 32242 unsigned int raw_curvature = (GET_BYTE(to_send, 2) << 3) | (GET_BYTE(to_send, 3) >> 5);
297 32242 unsigned int raw_curvature_rate = (GET_BYTE(to_send, 6) << 3) | (GET_BYTE(to_send, 7) >> 5);
298 32242 unsigned int raw_path_angle = ((GET_BYTE(to_send, 3) & 0x1FU) << 6) | (GET_BYTE(to_send, 4) >> 2);
299 32242 unsigned int raw_path_offset = ((GET_BYTE(to_send, 4) & 0x3U) << 8) | GET_BYTE(to_send, 5);
300
301 // These signals are not yet tested with the current safety limits
302
6/6
✓ Branch 0 taken 12880 times.
✓ Branch 1 taken 19362 times.
✓ Branch 2 taken 4080 times.
✓ Branch 3 taken 8800 times.
✓ Branch 4 taken 800 times.
✓ Branch 5 taken 3280 times.
32242 bool violation = (raw_curvature_rate != FORD_CANFD_INACTIVE_CURVATURE_RATE) || (raw_path_angle != FORD_INACTIVE_PATH_ANGLE) || (raw_path_offset != FORD_INACTIVE_PATH_OFFSET);
303
304 // Check angle error and steer_control_enabled
305 32242 int desired_curvature = raw_curvature - FORD_INACTIVE_CURVATURE; // /FORD_STEERING_LIMITS.angle_deg_to_can to get real curvature
306 32242 violation |= steer_angle_cmd_checks(desired_curvature, steer_control_enabled, FORD_STEERING_LIMITS);
307
308
2/2
✓ Branch 0 taken 30598 times.
✓ Branch 1 taken 1644 times.
32242 if (violation) {
309 30598 tx = false;
310 }
311 }
312
313 50482 return tx;
314 }
315
316 25344 static int ford_fwd_hook(int bus_num, int addr) {
317 25344 int bus_fwd = -1;
318
319
3/3
✓ Branch 0 taken 8448 times.
✓ Branch 1 taken 8448 times.
✓ Branch 2 taken 8448 times.
25344 switch (bus_num) {
320 8448 case FORD_MAIN_BUS: {
321 // Forward all traffic from bus 0 onward
322 8448 bus_fwd = FORD_CAM_BUS;
323 8448 break;
324 }
325 8448 case FORD_CAM_BUS: {
326
2/2
✓ Branch 1 taken 15 times.
✓ Branch 2 taken 8433 times.
8448 if (ford_lkas_msg_check(addr)) {
327 // Block stock LKAS and UI messages
328 15 bus_fwd = -1;
329
4/4
✓ Branch 0 taken 5622 times.
✓ Branch 1 taken 2811 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 5620 times.
8433 } else if (ford_longitudinal && (addr == FORD_ACCDATA)) {
330 // Block stock ACC message
331 2 bus_fwd = -1;
332 } else {
333 // Forward remaining traffic
334 8431 bus_fwd = FORD_MAIN_BUS;
335 }
336 8448 break;
337 }
338 8448 default: {
339 // No other buses should be in use; fallback to do-not-forward
340 8448 bus_fwd = -1;
341 8448 break;
342 }
343 }
344
345 25344 return bus_fwd;
346 }
347
348 96 static safety_config ford_init(uint16_t param) {
349 96 bool ford_canfd = false;
350
351 // warning: quality flags are not yet checked in openpilot's CAN parser,
352 // this may be the cause of blocked messages
353 static RxCheck ford_rx_checks[] = {
354 {.msg = {{FORD_BrakeSysFeatures, 0, 8, .check_checksum = true, .max_counter = 15U, .quality_flag=true, .frequency = 50U}, { 0 }, { 0 }}},
355 // FORD_EngVehicleSpThrottle2 has a counter that either randomly skips or by 2, likely ECU bug
356 // Some hybrid models also experience a bug where this checksum mismatches for one or two frames under heavy acceleration with ACC
357 // It has been confirmed that the Bronco Sport's camera only disallows ACC for bad quality flags, not counters or checksums, so we match that
358 {.msg = {{FORD_EngVehicleSpThrottle2, 0, 8, .check_checksum = false, .quality_flag=true, .frequency = 50U}, { 0 }, { 0 }}},
359 {.msg = {{FORD_Yaw_Data_FD1, 0, 8, .check_checksum = true, .max_counter = 255U, .quality_flag=true, .frequency = 100U}, { 0 }, { 0 }}},
360 // These messages have no counter or checksum
361 {.msg = {{FORD_EngBrakeData, 0, 8, .frequency = 10U}, { 0 }, { 0 }}},
362 {.msg = {{FORD_EngVehicleSpThrottle, 0, 8, .frequency = 100U}, { 0 }, { 0 }}},
363 {.msg = {{FORD_DesiredTorqBrk, 0, 8, .frequency = 50U}, { 0 }, { 0 }}},
364 };
365
366 #define FORD_COMMON_TX_MSGS \
367 {FORD_Steering_Data_FD1, 0, 8}, \
368 {FORD_Steering_Data_FD1, 2, 8}, \
369 {FORD_ACCDATA_3, 0, 8}, \
370 {FORD_Lane_Assist_Data1, 0, 8}, \
371 {FORD_IPMA_Data, 0, 8}, \
372
373 static const CanMsg FORD_CANFD_LONG_TX_MSGS[] = {
374 FORD_COMMON_TX_MSGS
375 {FORD_ACCDATA, 0, 8},
376 {FORD_LateralMotionControl2, 0, 8},
377 };
378
379 static const CanMsg FORD_CANFD_STOCK_TX_MSGS[] = {
380 FORD_COMMON_TX_MSGS
381 {FORD_LateralMotionControl2, 0, 8},
382 };
383
384 static const CanMsg FORD_STOCK_TX_MSGS[] = {
385 FORD_COMMON_TX_MSGS
386 {FORD_LateralMotionControl, 0, 8},
387 };
388
389 static const CanMsg FORD_LONG_TX_MSGS[] = {
390 FORD_COMMON_TX_MSGS
391 {FORD_ACCDATA, 0, 8},
392 {FORD_LateralMotionControl, 0, 8},
393 };
394
395 UNUSED(param);
396 #ifdef ALLOW_DEBUG
397 96 const uint16_t FORD_PARAM_LONGITUDINAL = 1;
398 96 const uint16_t FORD_PARAM_CANFD = 2;
399 96 ford_longitudinal = GET_FLAG(param, FORD_PARAM_LONGITUDINAL);
400 96 ford_canfd = GET_FLAG(param, FORD_PARAM_CANFD);
401 #endif
402
403 // Longitudinal is the default for CAN, and optional for CAN FD w/ ALLOW_DEBUG
404
4/4
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 33 times.
✓ Branch 2 taken 33 times.
✓ Branch 3 taken 30 times.
96 ford_longitudinal = !ford_canfd || ford_longitudinal;
405
406 safety_config ret;
407 // FIXME: cppcheck thinks that ford_canfd is always false. This is not true
408 // if ALLOW_DEBUG is defined but cppcheck is run without ALLOW_DEBUG
409 // cppcheck-suppress knownConditionTrueFalse
410
2/2
✓ Branch 0 taken 63 times.
✓ Branch 1 taken 33 times.
96 if (ford_canfd) {
411
2/2
✓ Branch 0 taken 33 times.
✓ Branch 1 taken 30 times.
63 ret = ford_longitudinal ? BUILD_SAFETY_CFG(ford_rx_checks, FORD_CANFD_LONG_TX_MSGS) : \
412 BUILD_SAFETY_CFG(ford_rx_checks, FORD_CANFD_STOCK_TX_MSGS);
413 } else {
414 // cppcheck-suppress knownConditionTrueFalse
415
1/2
✓ Branch 0 taken 33 times.
✗ Branch 1 not taken.
33 ret = ford_longitudinal ? BUILD_SAFETY_CFG(ford_rx_checks, FORD_LONG_TX_MSGS) : \
416 BUILD_SAFETY_CFG(ford_rx_checks, FORD_STOCK_TX_MSGS);
417 }
418 96 return ret;
419 }
420
421 const safety_hooks ford_hooks = {
422 .init = ford_init,
423 .rx = ford_rx_hook,
424 .tx = ford_tx_hook,
425 .fwd = ford_fwd_hook,
426 .get_counter = ford_get_counter,
427 .get_checksum = ford_get_checksum,
428 .compute_checksum = ford_compute_checksum,
429 .get_quality_flag_valid = ford_get_quality_flag_valid,
430 };
431