mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-10-28 00:53:45 +08:00
Support Toyota DSU bypass on camera bus
This commit is contained in:
@@ -142,6 +142,8 @@ class CarController(CarControllerBase):
|
||||
self.brake_hold_active = False
|
||||
|
||||
def update(self, CC, CS, now_nanos):
|
||||
from opendbc.car.toyota import dsu_bypass
|
||||
bypass_long = dsu_bypass.enabled(self.CP)
|
||||
_projection = self.learning_projection_observer
|
||||
if _projection is not None:
|
||||
_projection.begin(CC.actuators.torque, self.frame)
|
||||
@@ -177,6 +179,14 @@ class CarController(CarControllerBase):
|
||||
pedal_owner = pedal.configured(self.CP)
|
||||
if pedal_owner:
|
||||
filter_allowed = filter_allowed and bool(self.pedal_input is not None and self.pedal_input.update(now_nanos) and CS.pedal_ready)
|
||||
if bypass_long:
|
||||
preference = getattr(self, 'bypass_input', None)
|
||||
filter_allowed = filter_allowed and bool(
|
||||
preference is not None and preference.update(now_nanos) and CS.out.canValid and not CS.out.canTimeout and
|
||||
CS.out.cruiseState.available and not CS.out.accFaulted and not CS.out.stockAeb and
|
||||
not CS.out.steerFaultTemporary and not CS.out.steerFaultPermanent and not CS.out.doorOpen and
|
||||
not CS.out.seatbeltUnlatched and not CS.out.gasPressed and not CS.out.brakePressed and
|
||||
CS.out.gearShifter in (structs.CarState.GearShifter.drive, structs.CarState.GearShifter.sport))
|
||||
long_active = CC.longActive and filter_allowed
|
||||
if guarded_advert:
|
||||
long_active = long_active and not (CS.out.seatbeltUnlatched or CS.out.gasPressed or CS.out.brakePressed)
|
||||
@@ -184,9 +194,12 @@ class CarController(CarControllerBase):
|
||||
stopping = actuators.longControlState == LongCtrlState.stopping
|
||||
hud_control = CC.hudControl
|
||||
pcm_cancel_cmd = CC.cruiseControl.cancel
|
||||
if (rav4h_long or pedal_owner or advert_long or original_prius_long) and not filter_allowed and CS.out.cruiseState.enabled:
|
||||
if (bypass_long or rav4h_long or pedal_owner or advert_long or original_prius_long) and not filter_allowed and CS.out.cruiseState.enabled:
|
||||
pcm_cancel_cmd = True
|
||||
lat_active = CC.latActive and abs(CS.out.steeringTorque) < MAX_USER_TORQUE
|
||||
if dsu_bypass.configured(self.CP):
|
||||
lat_active = lat_active and CS.out.canValid and not CS.out.canTimeout and CS.out.cruiseState.available and not (
|
||||
CS.out.steerFaultTemporary or CS.out.steerFaultPermanent or CS.out.doorOpen)
|
||||
if self.original_prius_filter:
|
||||
lat_active = lat_active and CS.out.canValid and not CS.out.canTimeout and CS.out.cruiseState.available and not (
|
||||
CS.out.accFaulted or CS.out.steerFaultTemporary or CS.out.steerFaultPermanent or CS.out.doorOpen)
|
||||
@@ -329,7 +342,7 @@ class CarController(CarControllerBase):
|
||||
if not should_resume and CS.out.cruiseState.standstill:
|
||||
self.standstill_req = True
|
||||
|
||||
if (rav4h_long or pedal_owner or advert_long or original_prius_long) and (not filter_allowed or not long_active and CS.out.standstill):
|
||||
if (bypass_long or rav4h_long or pedal_owner or advert_long or original_prius_long) and (not filter_allowed or not long_active and CS.out.standstill):
|
||||
self.standstill_req = True
|
||||
|
||||
if pedal_owner and (self.CP.carFingerprint in pedal.RADAR_PEDAL_CARS or pedal_composite.configured(self.CP)) and not long_active:
|
||||
@@ -348,7 +361,7 @@ class CarController(CarControllerBase):
|
||||
|
||||
# internal PCM gas command can get stuck unwinding from negative accel so we apply a generous rate limit
|
||||
pcm_accel_cmd = actuators.accel if filter_allowed else 0.
|
||||
if (self.prius_longitudinal or rav4h_long or advert_long) and not long_active:
|
||||
if (bypass_long or self.prius_longitudinal or rav4h_long or advert_long) and not long_active:
|
||||
pcm_accel_cmd = 0.
|
||||
if long_active:
|
||||
pcm_accel_cmd = rate_limit(pcm_accel_cmd, self.prev_accel, ACCEL_WINDDOWN_LIMIT, ACCEL_WINDUP_LIMIT)
|
||||
@@ -419,7 +432,7 @@ class CarController(CarControllerBase):
|
||||
self.permit_braking = True
|
||||
self.standstill_req = True
|
||||
|
||||
if (rav4h_long or pedal_owner or advert_long or original_prius_long) and not long_active:
|
||||
if (bypass_long or rav4h_long or pedal_owner or advert_long or original_prius_long) and not long_active:
|
||||
pcm_accel_cmd = 0.
|
||||
main_accel_cmd = 0. if self.CP.flags & ToyotaFlags.SECOC.value else pcm_accel_cmd
|
||||
can_sends.append(toyotacan.create_accel_command(self.packer, main_accel_cmd, pcm_cancel_cmd, self.permit_braking, self.standstill_req, lead,
|
||||
|
||||
@@ -2,7 +2,7 @@ import copy
|
||||
import math
|
||||
|
||||
from opendbc.can import CANDefine, CANParser
|
||||
from opendbc.car.toyota import pedal_composite, pedal, legacy_sdsu, advert_filter, legacy_advert_filter, prius_sdsu, prius_advert_filter
|
||||
from opendbc.car.toyota import dsu_bypass, pedal_composite, pedal, legacy_sdsu, advert_filter, legacy_advert_filter, prius_sdsu, prius_advert_filter
|
||||
from opendbc.car.toyota.lexus_is import LexusIsCANParser
|
||||
from opendbc.car import Bus, DT_CTRL, create_button_events, structs
|
||||
from opendbc.car.common.conversions import Conversions as CV
|
||||
@@ -78,7 +78,8 @@ class CarState(CarStateBase):
|
||||
self.pre_collision_2 = copy.copy(cp_cam.vl["PRE_COLLISION_2"])
|
||||
|
||||
ret = structs.CarState()
|
||||
cp_acc = cp_cam if (self.CP.flags & ToyotaFlags.TSS2) and not (self.CP.flags & ToyotaFlags.RADAR_ACC) else cp
|
||||
bypass = dsu_bypass.configured(self.CP)
|
||||
cp_acc = cp_cam if bypass or (self.CP.flags & ToyotaFlags.TSS2) and not (self.CP.flags & ToyotaFlags.RADAR_ACC) else cp
|
||||
|
||||
if not self.CP.flags & ToyotaFlags.SECOC.value:
|
||||
self.gvc = cp.vl["VSC1S07"]["GVC"]
|
||||
@@ -177,6 +178,18 @@ class CarState(CarStateBase):
|
||||
ret.cruiseState.speed = cp.vl["PCM_CRUISE_2"]["SET_SPEED"] * CV.KPH_TO_MS
|
||||
cluster_set_speed = cp.vl["PCM_CRUISE_SM"]["UI_SET_SPEED"]
|
||||
|
||||
if bypass:
|
||||
main = 'DSU_CRUISE' if self.CP.carFingerprint in dsu_bypass.ALT_MAIN_CARS else 'PCM_CRUISE_2'
|
||||
stamp = cp.ts_nanos[main]['MAIN_ON']
|
||||
ret.cruiseState.available &= bool(cp.main_valid and stamp > 0 and 0 <= cp._last_update_nanos - stamp <= 303_031_000)
|
||||
stamp = cp.ts_nanos['EPS_STATUS']['LKA_STATE']
|
||||
ret.steerFaultTemporary |= not (cp.eps_valid and stamp > 0 and 0 <= cp._last_update_nanos - stamp <= 400_000_000)
|
||||
stamp = cp_cam.ts_nanos['ACC_CONTROL']['ACC_TYPE']
|
||||
ret.accFaulted |= not (cp_cam.acc_valid and stamp > 0 and 0 <= cp_cam._last_update_nanos - stamp <= 303_031_000)
|
||||
ret.accFaulted |= bool(cp_acc.vl['ACC_CONTROL']['ACC_MALFUNCTION'] or cp_acc.vl['ACC_CONTROL']['RADAR_DIRTY'] or cp.ambiguous or cp_cam.ambiguous)
|
||||
self.acc_type = cp_acc.vl['ACC_CONTROL']['ACC_TYPE']
|
||||
ret.stockFcw = bool(cp_acc.vl['PCS_HUD']['FCW'])
|
||||
|
||||
# UI_SET_SPEED is always non-zero when main is on, hide until first enable
|
||||
is_metric = cp.vl["BODY_CONTROL_STATE_2"]["UNITS"] in (1, 2)
|
||||
if ret.cruiseState.speed != 0:
|
||||
@@ -317,6 +330,15 @@ class CarState(CarStateBase):
|
||||
parent[Bus.pt] = pedal_composite.ParentPedalParser(parent[Bus.pt])
|
||||
parent[Bus.alt] = pedal.PedalCANParser(DBC[CP.carFingerprint][Bus.pt], [('GAS_SENSOR', 50)], 0)
|
||||
return parent
|
||||
if dsu_bypass.configured(CP):
|
||||
alternate = CP.carFingerprint in dsu_bypass.ALT_MAIN_CARS
|
||||
main = 'DSU_CRUISE' if alternate else 'PCM_CRUISE_2'
|
||||
kwargs = {'eps_length': 8 if CP.carFingerprint in dsu_bypass.EPS8_CARS or CP.carFingerprint == CAR.TOYOTA_PRIUS else 5,
|
||||
'alternate_main': alternate}
|
||||
return {
|
||||
Bus.pt: dsu_bypass.BypassCANParser(DBC[CP.carFingerprint][Bus.pt], [(main, 10), ('EPS_STATUS', 25)], 0, **kwargs),
|
||||
Bus.cam: dsu_bypass.BypassCANParser(DBC[CP.carFingerprint][Bus.pt], [('ACC_CONTROL', 33)], 2, **kwargs),
|
||||
}
|
||||
dbc_name = DBC[CP.carFingerprint][Bus.pt]
|
||||
cam_messages = [("RSA1", math.nan)] if "RSA1" in CANDBC(dbc_name).name_to_msg else []
|
||||
if CP.flags & ToyotaFlags.AUTO_BRAKE_HOLD and uses_toyota_auto_hold_aeb(CP):
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
"""Camera-bus DSU bypass identity and independent physical source ownership."""
|
||||
|
||||
from opendbc.can import CANParser
|
||||
from opendbc.car import structs
|
||||
from opendbc.car.toyota.toyotacan import toyota_checksum
|
||||
from opendbc.car.toyota.values import CAR, ToyotaFlags
|
||||
|
||||
EPS5_CARS = frozenset(
|
||||
(CAR.TOYOTA_AVALON, CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_RAV4, CAR.TOYOTA_RAV4H, CAR.TOYOTA_SIENNA, CAR.LEXUS_ES, CAR.LEXUS_NX, CAR.LEXUS_RX)
|
||||
)
|
||||
EPS8_CARS = frozenset((CAR.TOYOTA_AVALON_2019, CAR.TOYOTA_CAMRY, CAR.TOYOTA_CHR, CAR.LEXUS_LS, CAR.TOYOTA_PRIUS_RETROFIT))
|
||||
ALT_MAIN_CARS = frozenset((CAR.LEXUS_IS, CAR.LEXUS_RC, CAR.LEXUS_GS_F))
|
||||
PROFILES = dict.fromkeys(EPS5_CARS, 0x8849)
|
||||
PROFILES.update(dict.fromkeys(EPS8_CARS, 0x9849))
|
||||
PROFILES.update(
|
||||
{
|
||||
CAR.TOYOTA_PRIUS: 0x9842,
|
||||
CAR.TOYOTA_COROLLA: 0x8958,
|
||||
CAR.TOYOTA_MATRIX_RETROFIT: 0x8958,
|
||||
CAR.TOYOTA_PRIUS_V: 0x8964,
|
||||
CAR.LEXUS_CTH: 0x8964,
|
||||
CAR.LEXUS_IS: 0xC84D,
|
||||
CAR.LEXUS_RC: 0xC84D,
|
||||
CAR.LEXUS_GS_F: 0xC949,
|
||||
}
|
||||
)
|
||||
PROFILES.update({CAR.TOYOTA_RAV4: 0x8949, CAR.LEXUS_ES: 0x8949})
|
||||
AUTO_RESUME_CARS = frozenset((CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_PRIUS_V, CAR.TOYOTA_RAV4H, CAR.TOYOTA_SIENNA))
|
||||
WORDS = frozenset(word | stock for word in PROFILES.values() for stock in (0, 0x200))
|
||||
|
||||
|
||||
def hardware_supported(candidate, fingerprint, car_fw):
|
||||
if candidate not in PROFILES or any(address in frames for frames in fingerprint.values() for address in (0x201, 0x2FF, 0x2AA)):
|
||||
return False
|
||||
camera = fingerprint.get(2, {})
|
||||
if not any(camera.get(address) == 8 for address in (0x343, 0x4CB)) or any(camera.get(address, 8) != 8 for address in (0x343, 0x4CB)):
|
||||
return False
|
||||
late_prius = candidate in (CAR.TOYOTA_PRIUS, CAR.TOYOTA_PRIUS_RETROFIT) and any(
|
||||
fw.ecu == structs.CarParams.Ecu.fwdCamera and bytes(fw.fwVersion).startswith(b'8646F4705') for fw in car_fw
|
||||
)
|
||||
if candidate in (CAR.LEXUS_IS, CAR.TOYOTA_CAMRY) or late_prius:
|
||||
if not (
|
||||
(camera.get(0x343) == 8 and not any(0x343 in fingerprint.get(bus, {}) for bus in (0, 1)))
|
||||
or (camera.get(0x4CB) == 8 and 0x4CB not in fingerprint.get(0, {}))
|
||||
):
|
||||
return False
|
||||
if candidate == CAR.TOYOTA_MATRIX_RETROFIT:
|
||||
# This is a manual fingerprint, not a firmware-catalog identity.
|
||||
return not car_fw and all(fingerprint.get(0, {}).get(a) == length for a, length in ((0x260, 8), (0x262, 5), (0x224, 8), (0x1D2, 8), (0x1D3, 8)))
|
||||
from opendbc.car.toyota.fingerprints import FW_VERSIONS
|
||||
|
||||
known = FW_VERSIONS[CAR.TOYOTA_PRIUS if candidate == CAR.TOYOTA_PRIUS_RETROFIT else candidate]
|
||||
for ecu in (structs.CarParams.Ecu.eps, structs.CarParams.Ecu.fwdCamera, structs.CarParams.Ecu.fwdRadar):
|
||||
if not any(key[0] == ecu for key in known) and candidate != CAR.TOYOTA_PRIUS_RETROFIT:
|
||||
continue
|
||||
observed = [fw for fw in car_fw if fw.ecu == ecu]
|
||||
if not observed:
|
||||
return False
|
||||
for fw in observed:
|
||||
version = bytes(fw.fwVersion)
|
||||
allowed = (
|
||||
(version == b'8965B47070' + bytes(6))
|
||||
if ecu == structs.CarParams.Ecu.eps and candidate == CAR.TOYOTA_PRIUS_RETROFIT
|
||||
else version in known.get((ecu, fw.address, fw.subAddress or None), ())
|
||||
)
|
||||
if fw.logging or fw.bus != 0 or fw.brand != 'toyota' or not allowed:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def apply(cp):
|
||||
cp.flags |= int(ToyotaFlags.DSU_BYPASS)
|
||||
cp.safetyConfigs[0].safetyParam = PROFILES[cp.carFingerprint]
|
||||
cp.openpilotLongitudinalControl = True
|
||||
cp.alphaLongitudinalAvailable = False
|
||||
cp.autoResumeSng = cp.carFingerprint in AUTO_RESUME_CARS
|
||||
if cp.carFingerprint in (CAR.TOYOTA_MATRIX_RETROFIT, CAR.TOYOTA_PRIUS_RETROFIT):
|
||||
cp.dashcamOnly = False
|
||||
|
||||
|
||||
def configured(cp):
|
||||
if (
|
||||
cp is None
|
||||
or cp.brand != 'toyota'
|
||||
or cp.carFingerprint not in PROFILES
|
||||
or cp.notCar
|
||||
or cp.passive
|
||||
or cp.dashcamOnly
|
||||
or cp.secOcRequired
|
||||
or not cp.pcmCruise
|
||||
or cp.steerControlType != structs.CarParams.SteerControlType.torque
|
||||
or len(cp.safetyConfigs) != 1
|
||||
):
|
||||
return False
|
||||
required = int(CAR[cp.carFingerprint].config.flags | ToyotaFlags.DSU_BYPASS)
|
||||
allowed = required | int(ToyotaFlags.HYBRID | ToyotaFlags.ZSS)
|
||||
cfg = cp.safetyConfigs[0]
|
||||
return (
|
||||
cp.flags & required == required
|
||||
and not cp.flags & ~allowed
|
||||
and not cp.alphaLongitudinalAvailable
|
||||
and cp.autoResumeSng == (cp.openpilotLongitudinalControl and cp.carFingerprint in AUTO_RESUME_CARS)
|
||||
and cfg.safetyModel == structs.CarParams.SafetyModel.toyota
|
||||
and cfg.safetyParam == PROFILES[cp.carFingerprint] | (0 if cp.openpilotLongitudinalControl else 0x200)
|
||||
)
|
||||
|
||||
|
||||
def enabled(cp):
|
||||
return configured(cp) and cp.openpilotLongitudinalControl
|
||||
|
||||
|
||||
def prepare_stock(cp):
|
||||
if not configured(cp):
|
||||
return False
|
||||
cp.openpilotLongitudinalControl = False
|
||||
cp.autoResumeSng = False
|
||||
cp.safetyConfigs[0].safetyParam = PROFILES[cp.carFingerprint] | 0x200
|
||||
return True
|
||||
|
||||
|
||||
class BypassCANParser(CANParser):
|
||||
def __init__(self, *args, eps_length=8, alternate_main=False):
|
||||
super().__init__(*args)
|
||||
self.eps_length = eps_length
|
||||
self.main_address = 0x365 if alternate_main else 0x1D3
|
||||
self.main_length = 7 if alternate_main else 8
|
||||
self.main_valid = False
|
||||
self.eps_valid = False
|
||||
self.acc_valid = False
|
||||
self.ambiguous = False
|
||||
|
||||
def update(self, strings, sendcan=False):
|
||||
batches = []
|
||||
for stamp, frames in strings:
|
||||
accepted = []
|
||||
for address, data, bus in frames:
|
||||
if address in (0x201, 0x2FF, 0x2AA):
|
||||
self.ambiguous = True
|
||||
if bus == self.bus:
|
||||
if address in (self.main_address, 0x262, 0x343):
|
||||
size = self.main_length if address == self.main_address else self.eps_length if address == 0x262 else 8
|
||||
valid = len(data) == size and (address == 0x365 or data[-1] == toyota_checksum(address, None, bytearray(data)))
|
||||
field = 'main_valid' if address == self.main_address else 'eps_valid' if address == 0x262 else 'acc_valid'
|
||||
setattr(self, field, valid)
|
||||
if not valid:
|
||||
continue
|
||||
accepted.append((address, data, bus))
|
||||
batches.append((stamp, accepted))
|
||||
return super().update(batches, sendcan)
|
||||
@@ -252,6 +252,9 @@ class CarInterface(CarInterfaceBase):
|
||||
from opendbc.car.toyota import prius_advert_filter
|
||||
if prius_advert_filter.hardware_supported(candidate, fingerprint, car_fw):
|
||||
prius_advert_filter.apply(ret)
|
||||
from opendbc.car.toyota import dsu_bypass
|
||||
if dsu_bypass.hardware_supported(candidate, fingerprint, car_fw):
|
||||
dsu_bypass.apply(ret)
|
||||
from opendbc.car.toyota import pedal
|
||||
if ret.openpilotLongitudinalControl and pedal.hardware_supported(candidate, fingerprint, car_fw):
|
||||
ret.flags |= int(ToyotaFlags.GAS_INTERCEPTOR)
|
||||
|
||||
@@ -6,6 +6,9 @@ CARS = frozenset((CAR.TOYOTA_CAMRY, CAR.TOYOTA_CHR, CAR.TOYOTA_AVALON_2019,
|
||||
|
||||
|
||||
def enabled(cp):
|
||||
from opendbc.car.toyota import dsu_bypass
|
||||
if dsu_bypass.enabled(cp):
|
||||
return cp.carFingerprint not in dsu_bypass.AUTO_RESUME_CARS
|
||||
if cp is None or cp.carFingerprint not in CARS or not cp.openpilotLongitudinalControl:
|
||||
return False
|
||||
from opendbc.car.toyota import rav4h_filter, advert_filter, radar_filter
|
||||
|
||||
@@ -84,6 +84,7 @@ class ToyotaFlags(IntFlag):
|
||||
AUTO_BRAKE_HOLD = 4096
|
||||
RADAR_CAN_FILTER = 1 << 18 # Exact radar adapter; includes four-byte 2FF, distinct from legacy SDSU status
|
||||
GAS_INTERCEPTOR = 1 << 17 # Exact paired pedal owner
|
||||
DSU_BYPASS = 1 << 19 # Camera-bus DSU adapter; independent of smartDSU/filter
|
||||
ZSS = 1 << 16 # Detected Prius secondary steering sensor; host-only, no safetyParam allocation
|
||||
|
||||
# deprecated flags
|
||||
|
||||
@@ -110,12 +110,12 @@ static bool toyota_legacy_main_current(void) {
|
||||
|
||||
static bool toyota_legacy_advert_ready(void) {
|
||||
bool ready = true;
|
||||
if (toyota_pedal_composite || toyota_legacy_advert() || toyota_camera_2aa() || toyota_prius_filter()) {
|
||||
if (toyota_dsu_bypass || toyota_pedal_composite || toyota_legacy_advert() || toyota_camera_2aa() || toyota_prius_filter()) {
|
||||
static const uint32_t timeout[4] = {303031U, 10000000U, 3333334U, 400000U};
|
||||
const uint32_t now = microsecond_timer_get();
|
||||
ready = aol_rx_healthy() && toyota_aol_main && toyota_aol_drive && toyota_aol_doors_closed && toyota_aol_eps &&
|
||||
(!toyota_camera_2aa() || !toyota_camera_2aa_ambiguous) &&
|
||||
(!toyota_prius_filter() || !toyota_prius_sdsu_ambiguous);
|
||||
(!toyota_prius_filter() || !toyota_prius_sdsu_ambiguous) && (!toyota_dsu_bypass || !toyota_bypass_ambiguous);
|
||||
for (unsigned int i = 0U; i < 4U; i++) {
|
||||
ready &= toyota_aol_seen[i] && (safety_get_ts_elapsed(now, toyota_aol_ts[i]) <= timeout[i]);
|
||||
}
|
||||
@@ -193,6 +193,19 @@ static bool toyota_get_quality_flag_valid(const CANPacket_t *msg) {
|
||||
}
|
||||
|
||||
static void toyota_optional_rx_hook(const CANPacket_t *msg) {
|
||||
if (toyota_dsu_bypass) {
|
||||
if (msg_matches(msg, 0x343U, 2U)) {
|
||||
// A malformed packet outside the required catalog cannot retain LONG.
|
||||
toyota_bypass_control = false;
|
||||
}
|
||||
if ((msg->addr == 0x201U) || (msg->addr == 0x2FFU) || (msg->addr == 0x2AAU)) {
|
||||
toyota_bypass_ambiguous = true;
|
||||
}
|
||||
if (msg_matches(msg, 0x283U, 2U)) {
|
||||
const bool valid = (GET_LEN(msg) == 7U) && (toyota_get_checksum(msg) == toyota_compute_checksum(msg));
|
||||
toyota_bypass_aeb = !valid || (GET_BIT(msg, 41U) && GET_BIT(msg, 23U));
|
||||
}
|
||||
}
|
||||
if (toyota_prius_advert() && ((msg->addr == 0x201U) || (msg->addr == 0x2AAU) ||
|
||||
((msg->addr == 0x2FFU) && (((msg->bus != 0U) && (msg->bus != 2U)) || (GET_LEN(msg) != 4U))))) {
|
||||
toyota_prius_sdsu_ambiguous = true;
|
||||
@@ -208,10 +221,10 @@ static void toyota_optional_rx_hook(const CANPacket_t *msg) {
|
||||
toyota_camera_2aa_ambiguous = true;
|
||||
}
|
||||
const bool aol_checksum_source = (!toyota_alt_cruise && (msg->addr == 0x1D3U)) || (msg->addr == 0x262U) || (toyota_aol_secoc && (msg->addr == 0x127U));
|
||||
const unsigned int aol_source_len = ((toyota_aol_rav4h_filter || toyota_alt_cruise || toyota_legacy_sdsu || toyota_legacy_advert() || (current_safety_param == 856U)) && (msg->addr == 0x262U)) ? 5U : 8U;
|
||||
const unsigned int aol_source_len = (((toyota_dsu_bypass && toyota_bypass_eps5) || toyota_aol_rav4h_filter || toyota_alt_cruise || toyota_legacy_sdsu || toyota_legacy_advert() || (current_safety_param == 856U)) && (msg->addr == 0x262U)) ? 5U : 8U;
|
||||
if (!aol_checksum_source || ((GET_LEN(msg) == aol_source_len) && (toyota_get_checksum(msg) == toyota_compute_checksum(msg)))) {
|
||||
toyota_aol_observe(msg);
|
||||
} else if ((toyota_pedal_composite || toyota_aol_enabled || toyota_legacy_advert() || toyota_camera_2aa() || toyota_prius_filter()) && (msg->bus == 0U)) {
|
||||
} else if ((toyota_dsu_bypass || toyota_pedal_composite || toyota_aol_enabled || toyota_legacy_advert() || toyota_camera_2aa() || toyota_prius_filter()) && (msg->bus == 0U)) {
|
||||
unsigned int index = 3U;
|
||||
if (msg->addr == 0x1D3U) {
|
||||
index = 0U;
|
||||
@@ -244,9 +257,12 @@ static void toyota_optional_rx_hook(const CANPacket_t *msg) {
|
||||
}
|
||||
|
||||
static void toyota_rx_hook(const CANPacket_t *msg) {
|
||||
if (toyota_dsu_bypass && msg_matches(msg, 0x343U, 2U)) {
|
||||
toyota_bypass_control = !GET_BIT(msg, 18U) && !GET_BIT(msg, 19U);
|
||||
}
|
||||
// Required sources have already passed RX length/checksum validation here.
|
||||
// Optional ingress only runs for messages outside the required RX catalog.
|
||||
if ((toyota_pedal_composite || toyota_legacy_advert() || toyota_camera_2aa() || toyota_prius_filter() || (current_safety_param == 856U)) && ((msg->addr == 0x262U) || (!toyota_alt_cruise && (msg->addr == 0x1D3U)))) {
|
||||
if ((toyota_dsu_bypass || toyota_pedal_composite || toyota_legacy_advert() || toyota_camera_2aa() || toyota_prius_filter() || (current_safety_param == 856U)) && ((msg->addr == 0x262U) || (!toyota_alt_cruise && (msg->addr == 0x1D3U)))) {
|
||||
toyota_aol_observe(msg);
|
||||
}
|
||||
if (toyota_alt_cruise && msg_matches(msg, 0x365U, 0U) && (GET_LEN(msg) == 7U)) {
|
||||
@@ -398,7 +414,8 @@ static bool toyota_tx_hook(const CANPacket_t *msg) {
|
||||
};
|
||||
|
||||
const bool filter_ready = (!(toyota_sdsu_status || toyota_pedal) || aol_rx_healthy()) && toyota_legacy_main_current() && toyota_legacy_advert_ready();
|
||||
const bool filter_long_ready = filter_ready && (!toyota_sdsu_status || toyota_sdsu_control);
|
||||
const bool filter_long_ready = filter_ready && (!toyota_sdsu_status || toyota_sdsu_control) &&
|
||||
(!toyota_dsu_bypass || (toyota_bypass_control && !toyota_bypass_aeb));
|
||||
|
||||
bool tx = true;
|
||||
if (toyota_pedal && (msg->addr == 0x200U)) {
|
||||
@@ -580,14 +597,20 @@ static bool toyota_tx_hook(const CANPacket_t *msg) {
|
||||
}
|
||||
|
||||
// Required physical DSU MAIN cannot be manufactured through host TX.
|
||||
if ((toyota_legacy_sdsu || toyota_legacy_advert()) && toyota_alt_cruise && msg_matches(msg, 0x365U, 0U)) {
|
||||
if ((toyota_dsu_bypass || toyota_legacy_sdsu || toyota_legacy_advert()) && toyota_alt_cruise && msg_matches(msg, 0x365U, 0U)) {
|
||||
tx = false;
|
||||
}
|
||||
return tx;
|
||||
}
|
||||
|
||||
static safety_config toyota_init(uint16_t param) {
|
||||
const uint16_t base_param = toyota_pedal_parent_param(param);
|
||||
const uint16_t base_param = toyota_bypass_base_param(toyota_pedal_parent_param(param));
|
||||
toyota_dsu_bypass = toyota_bypass_param(param);
|
||||
toyota_bypass_eps5 = toyota_dsu_bypass && ((param & 0x1000U) == 0U);
|
||||
toyota_bypass_alt_main = toyota_dsu_bypass && ((param & 0x4000U) != 0U);
|
||||
toyota_bypass_ambiguous = false;
|
||||
toyota_bypass_control = false;
|
||||
toyota_bypass_aeb = false;
|
||||
toyota_pedal_composite = toyota_pedal_composite_param(param);
|
||||
toyota_composite_pcm_gas = false;
|
||||
toyota_composite_pedal_gas = false;
|
||||
@@ -653,7 +676,7 @@ static safety_config toyota_init(uint16_t param) {
|
||||
|
||||
toyota_alt_brake = GET_FLAG(base_param, TOYOTA_PARAM_ALT_BRAKE);
|
||||
toyota_stock_longitudinal = GET_FLAG(base_param, TOYOTA_PARAM_STOCK_LONGITUDINAL);
|
||||
toyota_radar_diagnostics_allowed = !toyota_stock_longitudinal && !toyota_secoc && (base_param != 0x1049U) && (base_param != 0x1449U) && !toyota_eps8_sdsu && !toyota_legacy_sdsu && !toyota_legacy_advert_param(base_param) && !toyota_camera_2aa_param(base_param) && !toyota_prius_filter_param(base_param);
|
||||
toyota_radar_diagnostics_allowed = !toyota_dsu_bypass && !toyota_stock_longitudinal && !toyota_secoc && (base_param != 0x1049U) && (base_param != 0x1449U) && !toyota_eps8_sdsu && !toyota_legacy_sdsu && !toyota_legacy_advert_param(base_param) && !toyota_camera_2aa_param(base_param) && !toyota_prius_filter_param(base_param);
|
||||
toyota_lta = !toyota_legacy_advert_param(base_param) && GET_FLAG(base_param, TOYOTA_PARAM_LTA);
|
||||
toyota_dbc_eps_torque_factor = base_param & TOYOTA_EPS_FACTOR;
|
||||
|
||||
@@ -742,6 +765,16 @@ static safety_config toyota_init(uint16_t param) {
|
||||
} else {
|
||||
ret.rx_checks_len = 4;
|
||||
}
|
||||
if (toyota_dsu_bypass) {
|
||||
toyota_rx_checks[4].msg[0] = (CanMsgCheck){.addr = 0x343, .bus = 2U, .len = 8, .frequency = 33U,
|
||||
.ignore_counter = true, .ignore_quality_flag = true};
|
||||
toyota_rx_checks[5].msg[0] = (CanMsgCheck){.addr = 0x262, .bus = 0U, .len = toyota_bypass_eps5 ? 5 : 8, .frequency = 25U,
|
||||
.ignore_counter = true, .ignore_quality_flag = true};
|
||||
toyota_rx_checks[6].msg[0] = (CanMsgCheck){.addr = toyota_alt_cruise ? 0x365 : 0x1D3, .bus = 0U,
|
||||
.len = toyota_alt_cruise ? 7 : 8, .frequency = 10U, .ignore_checksum = toyota_alt_cruise,
|
||||
.ignore_counter = true, .ignore_quality_flag = true};
|
||||
ret.rx_checks_len = 7;
|
||||
}
|
||||
if (toyota_pedal_composite) {
|
||||
// Keep all parent checks, including smartDSU status, independently required.
|
||||
toyota_rx_checks[5].msg[0] = (CanMsgCheck){.addr = 0x201, .bus = 0U, .len = 6, .frequency = 50U,
|
||||
@@ -764,8 +797,9 @@ static safety_config toyota_init(uint16_t param) {
|
||||
}
|
||||
|
||||
static bool toyota_fwd_hook(int bus_num, int addr) {
|
||||
return (bus_num == 2) && (addr == 0x344) && toyota_hold_ready(ALT_EXP_TOYOTA_AEB_HOLD) &&
|
||||
toyota_hold_host_seen && (safety_get_ts_elapsed(microsecond_timer_get(), toyota_hold_host_ts) <= 100000U);
|
||||
return (toyota_dsu_bypass && !toyota_stock_longitudinal && (bus_num == 2) && (addr == 0x343)) ||
|
||||
((bus_num == 2) && (addr == 0x344) && toyota_hold_ready(ALT_EXP_TOYOTA_AEB_HOLD) &&
|
||||
toyota_hold_host_seen && (safety_get_ts_elapsed(microsecond_timer_get(), toyota_hold_host_ts) <= 100000U));
|
||||
}
|
||||
|
||||
const safety_hooks toyota_hooks = {
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
static bool toyota_dsu_bypass = false;
|
||||
static bool toyota_bypass_eps5 = false;
|
||||
static bool toyota_bypass_alt_main = false;
|
||||
static bool toyota_bypass_ambiguous = false;
|
||||
static bool toyota_bypass_control = false;
|
||||
static bool toyota_bypass_aeb = false;
|
||||
|
||||
static bool toyota_bypass_param(uint16_t param) {
|
||||
return (param == 0x8949U) || (param == 0x8B49U) || (param == 0x8849U) || (param == 0x8A49U) || (param == 0x9849U) || (param == 0x9A49U) || (param == 0x9842U) || (param == 0x9A42U) || (param == 0x8958U) || (param == 0x8B58U) || (param == 0x8964U) || (param == 0x8B64U) || (param == 0xC84DU) || (param == 0xCA4DU) || (param == 0xC949U) || (param == 0xCB49U);
|
||||
}
|
||||
|
||||
static uint16_t toyota_bypass_base_param(uint16_t param) {
|
||||
return toyota_bypass_param(param) ? (uint16_t)(param & 0x3FFU) : param;
|
||||
}
|
||||
|
||||
static bool toyota_prius_sdsu_param(uint16_t param) {
|
||||
return (param == 0x8042U) || (param == 0x8242U);
|
||||
}
|
||||
@@ -115,10 +130,10 @@ static uint8_t toyota_aol_permission(void) {
|
||||
uint8_t permission = 0U;
|
||||
if (fresh && toyota_aol_main && toyota_aol_drive && toyota_aol_doors_closed && toyota_aol_eps &&
|
||||
(!toyota_camera_2aa() || !toyota_camera_2aa_ambiguous) &&
|
||||
(!toyota_prius_filter() || !toyota_prius_sdsu_ambiguous)) {
|
||||
(!toyota_prius_filter() || !toyota_prius_sdsu_ambiguous) && (!toyota_dsu_bypass || !toyota_bypass_ambiguous)) {
|
||||
permission = request & 1U;
|
||||
if (!toyota_aol_stock && controls_allowed && toyota_aol_belt && !gas_pressed && !brake_pressed &&
|
||||
(!toyota_sdsu_status || toyota_sdsu_control)) {
|
||||
(!toyota_sdsu_status || toyota_sdsu_control) && (!toyota_dsu_bypass || (toyota_bypass_control && !toyota_bypass_aeb))) {
|
||||
permission |= request & 2U;
|
||||
}
|
||||
}
|
||||
@@ -131,11 +146,11 @@ static void toyota_aol_observe(const CANPacket_t *msg) {
|
||||
unsigned int expected_len = 8U;
|
||||
if (toyota_alt_cruise && (msg->addr == main_addr)) {
|
||||
expected_len = 7U;
|
||||
} else if ((toyota_aol_rav4h_filter || toyota_alt_cruise || toyota_legacy_sdsu || toyota_legacy_advert() || (current_safety_param == 856U)) && (msg->addr == 0x262U)) {
|
||||
} else if (((toyota_dsu_bypass && toyota_bypass_eps5) || toyota_aol_rav4h_filter || toyota_alt_cruise || toyota_legacy_sdsu || toyota_legacy_advert() || (current_safety_param == 856U)) && (msg->addr == 0x262U)) {
|
||||
expected_len = 5U;
|
||||
} else {
|
||||
}
|
||||
if ((toyota_pedal_composite || toyota_aol_enabled || toyota_legacy_advert() || toyota_camera_2aa() || toyota_prius_filter()) && (msg->bus == 0U) && (GET_LEN(msg) != expected_len)) {
|
||||
if ((toyota_dsu_bypass || toyota_pedal_composite || toyota_aol_enabled || toyota_legacy_advert() || toyota_camera_2aa() || toyota_prius_filter()) && (msg->bus == 0U) && (GET_LEN(msg) != expected_len)) {
|
||||
unsigned int index = 4U;
|
||||
if (msg->addr == main_addr) {
|
||||
index = 0U;
|
||||
@@ -150,7 +165,7 @@ static void toyota_aol_observe(const CANPacket_t *msg) {
|
||||
if (index < 4U) {
|
||||
toyota_aol_seen[index] = false;
|
||||
}
|
||||
} else if ((toyota_pedal_composite || toyota_aol_enabled || toyota_legacy_advert() || toyota_camera_2aa() || toyota_prius_filter()) && (msg->bus == 0U) && (GET_LEN(msg) == expected_len)) {
|
||||
} else if ((toyota_dsu_bypass || toyota_pedal_composite || toyota_aol_enabled || toyota_legacy_advert() || toyota_camera_2aa() || toyota_prius_filter()) && (msg->bus == 0U) && (GET_LEN(msg) == expected_len)) {
|
||||
unsigned int index = 4U;
|
||||
if (msg->addr == main_addr) {
|
||||
index = 0U;
|
||||
@@ -194,18 +209,18 @@ static void toyota_aol_configure(uint16_t param) {
|
||||
toyota_prius_sdsu_ambiguous = false;
|
||||
toyota_eps8_sdsu = (param == 0x8049U) || (param == 0x8249U) || (param == 0x8449U) || (param == 0x8649U);
|
||||
toyota_legacy_sdsu = (param == 0x9158U) || (param == 0x9358U) || (param == 0x9149U) || (param == 0x9349U) || (param == 0x9164U) || (param == 0x9364U) || (param == 0xd149U) || (param == 0xd349U) || (param == 0xd04dU) || (param == 0xd24dU);
|
||||
toyota_alt_cruise = (param == 0x424DU) || ((toyota_legacy_sdsu || toyota_legacy_advert_param(param)) && ((param & 0x4000U) != 0U));
|
||||
toyota_alt_cruise = toyota_bypass_alt_main || (param == 0x424DU) || ((toyota_legacy_sdsu || toyota_legacy_advert_param(param)) && ((param & 0x4000U) != 0U));
|
||||
toyota_aol_lta = (param == 0x2449U) || (param == 0x2649U) || (param == 0x449U) || (param == 0x649U) || (param == 0x1449U) || (param == 0x1649U) || (param == 0x8449U) || (param == 0x8649U);
|
||||
toyota_pedal = (param == 0x2049U) || (param == 0x2249U) || (param == 0x2449U) || (param == 0x2649U);
|
||||
toyota_aol_rav4h_filter = (param == 0x9049U) || (param == 0x9249U);
|
||||
toyota_sdsu_status = toyota_aol_rav4h_filter || toyota_eps8_sdsu || toyota_legacy_sdsu || toyota_prius_sdsu_param(param);
|
||||
toyota_aol_stock = (param == 0x2649U) || (param == 585U) || (param == 856U) || (param == 4681U) || (param == 0x9249U) || (param == 0x2249U) || (param == 0x424DU) || (param == 0x649U) || (param == 0x1649U) || (param == 0x8249U) || (param == 0x8649U) || ((toyota_legacy_sdsu || toyota_legacy_advert_param(param) || toyota_camera_2aa_param(param) || toyota_prius_filter_param(param)) && ((param & 0x200U) != 0U));
|
||||
toyota_aol_stock = (toyota_dsu_bypass && ((param & 0x200U) != 0U)) || (param == 0x2649U) || (param == 585U) || (param == 856U) || (param == 4681U) || (param == 0x9249U) || (param == 0x2249U) || (param == 0x424DU) || (param == 0x649U) || (param == 0x1649U) || (param == 0x8249U) || (param == 0x8649U) || ((toyota_legacy_sdsu || toyota_legacy_advert_param(param) || toyota_camera_2aa_param(param) || toyota_prius_filter_param(param)) && ((param & 0x200U) != 0U));
|
||||
#ifdef ALLOW_DEBUG
|
||||
toyota_aol_secoc = (param == 2121U);
|
||||
#else
|
||||
toyota_aol_secoc = false;
|
||||
#endif
|
||||
toyota_aol_enabled = ((toyota_eps8_sdsu || toyota_legacy_sdsu || toyota_legacy_advert_param(param) || toyota_camera_2aa_param(param) || toyota_prius_filter_param(param)) && (alternative_experience == 32)) || (toyota_aol_lta && (alternative_experience == 32)) || (toyota_aol_stock && (alternative_experience == 32)) ||
|
||||
toyota_aol_enabled = (toyota_dsu_bypass && (alternative_experience == 32)) || ((toyota_eps8_sdsu || toyota_legacy_sdsu || toyota_legacy_advert_param(param) || toyota_camera_2aa_param(param) || toyota_prius_filter_param(param)) && (alternative_experience == 32)) || (toyota_aol_lta && (alternative_experience == 32)) || (toyota_aol_stock && (alternative_experience == 32)) ||
|
||||
#ifdef ALLOW_DEBUG
|
||||
(toyota_aol_secoc && (alternative_experience == 32)) ||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
"""Actual camera ACC, physical MAIN/EPS and native TX/forwarding ownership."""
|
||||
|
||||
import pytest
|
||||
from opendbc.can import CANPacker
|
||||
from opendbc.car import Bus, structs
|
||||
from opendbc.car.toyota import dsu_bypass
|
||||
from opendbc.car.toyota.values import CAR, DBC
|
||||
from opendbc.safety.tests.libsafety import libsafety_py
|
||||
from openpilot.starpilot.car.toyota.tests import test_rav4h_caller_native as helpers
|
||||
|
||||
source_matched_native = helpers.source_matched_native
|
||||
REPRESENTATIVES = (CAR.TOYOTA_RAV4H, CAR.LEXUS_ES, CAR.TOYOTA_CAMRY, CAR.TOYOTA_PRIUS, CAR.TOYOTA_COROLLA, CAR.TOYOTA_PRIUS_V, CAR.LEXUS_IS, CAR.LEXUS_GS_F)
|
||||
|
||||
|
||||
class Sources:
|
||||
def __init__(self, candidate, stock=False):
|
||||
self.candidate, self.stock = candidate, stock
|
||||
self.safety = libsafety_py.libsafety
|
||||
self.safety.init_tests()
|
||||
self.safety.set_alternative_experience(32)
|
||||
assert self.safety.set_safety_hooks(structs.CarParams.SafetyModel.toyota, dsu_bypass.PROFILES[candidate] | (0x200 if stock else 0)) == 0
|
||||
self.safety.set_aol_test_heartbeat(True)
|
||||
self.packer = CANPacker(DBC[candidate][Bus.pt])
|
||||
self.now = 1_000_000
|
||||
for _ in range(30):
|
||||
self.tick()
|
||||
|
||||
def rx(self, frame):
|
||||
a, d, b = frame
|
||||
return bool(self.safety.safety_rx_hook(libsafety_py.make_CANPacket(a, b, d)))
|
||||
|
||||
def tick(self, fault=None, cruise=True):
|
||||
self.now += 10_000
|
||||
self.safety.set_timer(self.now)
|
||||
fields = {
|
||||
'cruise': cruise,
|
||||
'sdsu': None,
|
||||
'main': fault != 'main-off',
|
||||
'eps': 9 if fault == 'eps-state' else 1,
|
||||
'gear': 16 if fault == 'reverse' else 0,
|
||||
'gas': fault == 'gas',
|
||||
'brake': fault == 'brake',
|
||||
}
|
||||
frames = helpers.physical(self.packer, **fields)
|
||||
if self.candidate in dsu_bypass.ALT_MAIN_CARS:
|
||||
frames += [self.packer.make_can_msg('DSU_CRUISE', 0, {'MAIN_ON': fields['main'], 'SET_SPEED': 90})]
|
||||
frames += [
|
||||
self.packer.make_can_msg('ACC_CONTROL', 2, {'ACC_TYPE': 1, 'ACC_MALFUNCTION': fault == 'acc-fault'}),
|
||||
self.packer.make_can_msg('PRE_COLLISION', 2, {'PRECOLLISION_ACTIVE': fault == 'aeb', 'FORCE': -20 if fault == 'aeb' else 0}),
|
||||
]
|
||||
selected = (
|
||||
0x343
|
||||
if fault and fault.startswith('acc-')
|
||||
else (0x365 if self.candidate in dsu_bypass.ALT_MAIN_CARS else 0x1D3)
|
||||
if fault and fault.startswith('main-')
|
||||
else 0x262
|
||||
)
|
||||
for a, d, b in frames:
|
||||
if fault and a == selected and b == (2 if selected == 0x343 else 0):
|
||||
if fault.endswith('-drop'):
|
||||
continue
|
||||
if fault.endswith('-dlc'):
|
||||
d = d[:-1]
|
||||
elif fault.endswith('-crc'):
|
||||
d = d[:-1] + bytes([d[-1] ^ 1])
|
||||
accepted = self.rx((a, d, b))
|
||||
if fault and fault.endswith('-crc') and a == selected and b == (2 if selected == 0x343 else 0):
|
||||
assert not accepted
|
||||
else:
|
||||
assert accepted, (hex(a), d.hex(), b)
|
||||
if fault == 'mixed-pedal':
|
||||
self.rx((0x201, bytes(6), 0))
|
||||
self.safety.safety_tick()
|
||||
self.safety.aol_set_host_request(3)
|
||||
|
||||
def accel(self, value):
|
||||
return self.rx_tx('ACC_CONTROL', {'ACCEL_CMD': value, 'PERMIT_BRAKING': 1, 'RELEASE_STANDSTILL': value != 0})
|
||||
|
||||
def rx_tx(self, name, fields):
|
||||
a, d, b = self.packer.make_can_msg(name, 0, fields)
|
||||
return bool(self.safety.safety_tx_hook(libsafety_py.make_CANPacket(a, b, d)))
|
||||
|
||||
def close(self):
|
||||
self.safety.set_alternative_experience(0)
|
||||
self.safety.set_safety_hooks(structs.CarParams.SafetyModel.noOutput, 0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('candidate', REPRESENTATIVES)
|
||||
@pytest.mark.parametrize('stock', (False, True))
|
||||
def test_exact_native_health_permission_accel_and_forwarding(candidate, stock):
|
||||
src = Sources(candidate, stock)
|
||||
try:
|
||||
assert src.safety.safety_config_valid()
|
||||
assert src.safety.aol_get_permission_mask() == (1 if stock else 3)
|
||||
assert src.accel(0.05) == (not stock)
|
||||
assert src.safety.safety_fwd_hook(2, 0x343) == (0 if stock else -1)
|
||||
assert src.safety.safety_fwd_hook(2, 0x4CB) == 0
|
||||
assert src.safety.safety_fwd_hook(2, 0x283) == 0
|
||||
finally:
|
||||
src.close()
|
||||
|
||||
|
||||
@pytest.mark.parametrize('candidate', REPRESENTATIVES)
|
||||
@pytest.mark.parametrize(
|
||||
'fault',
|
||||
('acc-drop', 'acc-dlc', 'acc-crc', 'acc-fault', 'main-off', 'eps-drop', 'eps-dlc', 'eps-crc', 'eps-state', 'reverse', 'gas', 'brake', 'aeb', 'mixed-pedal'),
|
||||
)
|
||||
def test_independent_sources_and_physical_vetoes(candidate, fault):
|
||||
src = Sources(candidate)
|
||||
try:
|
||||
assert src.accel(0.05)
|
||||
for _ in range(41): # Strictly exceed the existing 400ms EPS lease.
|
||||
src.tick(fault)
|
||||
assert not src.accel(0.05), fault
|
||||
if fault != 'mixed-pedal':
|
||||
for _ in range(30):
|
||||
src.tick(cruise=False)
|
||||
for _ in range(30):
|
||||
src.tick()
|
||||
assert src.accel(0.05), fault
|
||||
else:
|
||||
src.tick(cruise=False)
|
||||
src.tick()
|
||||
assert not src.accel(0.05)
|
||||
finally:
|
||||
src.close()
|
||||
@@ -179,7 +179,7 @@ int main() {
|
||||
}
|
||||
|
||||
for (uint32_t word = 0U; word <= 65535U; ++word) {
|
||||
const bool expected = (word == 0xB049U) || (word == 0xB249U) || (word == 0xD049U) || (word == 0xD249U) || (word == 0xC042U) || (word == 0xC242U) || (word == 0x8042U) || (word == 0x8242U) || (word == 0xC049U) || (word == 0xC249U) || (word == 73U) || (word == 585U) || (word == 856U) || (word == 4169U) || (word == 4681U) || (word == 2121U) || (word == 0x9049U) || (word == 0x9249U) || (word == 0x2449U) || (word == 0x2649U) || (word == 0x2049U) || (word == 0x2249U) || (word == 0x424DU) || (word == 0x449U) || (word == 0x649U) || (word == 0x1449U) || (word == 0x1649U) || (word == 0x8049U) || (word == 0x8249U) || (word == 0x8449U) || (word == 0x8649U) || (word == 0x9158U) || (word == 0x9358U) || (word == 0x9149U) || (word == 0x9349U) || (word == 0x9164U) || (word == 0x9364U) || (word == 0xd149U) || (word == 0xd349U) || (word == 0xd04dU) || (word == 0xd24dU) || (word == 0x9449U) || (word == 0x9549U) || (word == 0x9558U) || (word == 0x9564U) || (word == 0x9649U) || (word == 0x9749U) || (word == 0x9758U) || (word == 0x9764U) || (word == 0xD44DU) || (word == 0xD549U) || (word == 0xD64DU) || (word == 0xD749U);
|
||||
const bool expected = (word == 0x8949U) || (word == 0x8B49U) || (word == 0x8849U) || (word == 0x8A49U) || (word == 0x9849U) || (word == 0x9A49U) || (word == 0x9842U) || (word == 0x9A42U) || (word == 0x8958U) || (word == 0x8B58U) || (word == 0x8964U) || (word == 0x8B64U) || (word == 0xC84DU) || (word == 0xCA4DU) || (word == 0xC949U) || (word == 0xCB49U) || (word == 0xB049U) || (word == 0xB249U) || (word == 0xD049U) || (word == 0xD249U) || (word == 0xC042U) || (word == 0xC242U) || (word == 0x8042U) || (word == 0x8242U) || (word == 0xC049U) || (word == 0xC249U) || (word == 73U) || (word == 585U) || (word == 856U) || (word == 4169U) || (word == 4681U) || (word == 2121U) || (word == 0x9049U) || (word == 0x9249U) || (word == 0x2449U) || (word == 0x2649U) || (word == 0x2049U) || (word == 0x2249U) || (word == 0x424DU) || (word == 0x449U) || (word == 0x649U) || (word == 0x1449U) || (word == 0x1649U) || (word == 0x8049U) || (word == 0x8249U) || (word == 0x8449U) || (word == 0x8649U) || (word == 0x9158U) || (word == 0x9358U) || (word == 0x9149U) || (word == 0x9349U) || (word == 0x9164U) || (word == 0x9364U) || (word == 0xd149U) || (word == 0xd349U) || (word == 0xd04dU) || (word == 0xd24dU) || (word == 0x9449U) || (word == 0x9549U) || (word == 0x9558U) || (word == 0x9564U) || (word == 0x9649U) || (word == 0x9749U) || (word == 0x9758U) || (word == 0x9764U) || (word == 0xD44DU) || (word == 0xD549U) || (word == 0xD64DU) || (word == 0xD749U);
|
||||
auto toyota = status();
|
||||
toyota.safety_mode = 2U;
|
||||
toyota.safety_param = static_cast<uint16_t>(word);
|
||||
|
||||
@@ -6,6 +6,8 @@ from openpilot.starpilot.aol.policy import AolVehiclePolicy
|
||||
from openpilot.starpilot.aol.intent import AolCardIntent, AOL_TOGGLE
|
||||
|
||||
AOL_WORDS = frozenset((
|
||||
0x8949, 0x8B49,
|
||||
0x8849, 0x8A49, 0x9849, 0x9A49, 0x9842, 0x9A42, 0x8958, 0x8B58, 0x8964, 0x8B64, 0xC84D, 0xCA4D, 0xC949, 0xCB49,
|
||||
0x8042, 0x8242, 0xC042, 0xC242, 0xD049, 0xD249,
|
||||
0xC049, 0xC249,
|
||||
0x9449, 0x9549, 0x9558, 0x9564, 0x9649, 0x9749, 0x9758, 0x9764, 0xD44D, 0xD549, 0xD64D, 0xD749,
|
||||
@@ -97,6 +99,9 @@ def stock_prius_retrofit_qualified(cp, *, marked_only=False):
|
||||
|
||||
|
||||
def qualified(cp, *, marked_only=False):
|
||||
from opendbc.car.toyota import dsu_bypass
|
||||
if dsu_bypass.configured(cp):
|
||||
return cp.alternativeExperience in ((32,) if marked_only else (0, 32))
|
||||
from opendbc.car.toyota import pedal_composite
|
||||
if pedal_composite.configured(cp):
|
||||
return qualified(pedal_composite.parent_cp(cp), marked_only=marked_only)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "selfdrive/pandad/aol_protocol.h"
|
||||
|
||||
inline bool toyota_aol_param(uint16_t param) {
|
||||
return (param == 0xB049U) || (param == 0xB249U) || (param == 0xD049U || param == 0xD249U || param == 0xC042U || param == 0xC242U || param == 0x8042U || param == 0x8242U || param == 0xC049U) || (param == 0xC249U) || (param == 73U) || (param == 585U) || (param == 856U) || (param == 4169U) || (param == 4681U) || (param == 2121U) || (param == 0x9049U) || (param == 0x9249U) || (param == 0x2449U) || (param == 0x2649U) || (param == 0x2049U) || (param == 0x2249U) || (param == 0x424DU) || (param == 0x449U) || (param == 0x649U) || (param == 0x1449U) || (param == 0x1649U) || (param == 0x8049U) || (param == 0x8249U) || (param == 0x8449U) || (param == 0x8649U) || (param == 0x9158U) || (param == 0x9358U) || (param == 0x9149U) || (param == 0x9349U) || (param == 0x9164U) || (param == 0x9364U) || (param == 0xd149U) || (param == 0xd349U) || (param == 0xd04dU) || (param == 0xd24dU) || (param == 0x9449U) || (param == 0x9549U) || (param == 0x9558U) || (param == 0x9564U) || (param == 0x9649U) || (param == 0x9749U) || (param == 0x9758U) || (param == 0x9764U) || (param == 0xD44DU) || (param == 0xD549U) || (param == 0xD64DU) || (param == 0xD749U);
|
||||
return (param == 0x8949U) || (param == 0x8B49U) || (param == 0x8849U) || (param == 0x8A49U) || (param == 0x9849U) || (param == 0x9A49U) || (param == 0x9842U) || (param == 0x9A42U) || (param == 0x8958U) || (param == 0x8B58U) || (param == 0x8964U) || (param == 0x8B64U) || (param == 0xC84DU) || (param == 0xCA4DU) || (param == 0xC949U) || (param == 0xCB49U) || (param == 0xB049U) || (param == 0xB249U) || (param == 0xD049U || param == 0xD249U || param == 0xC042U || param == 0xC242U || param == 0x8042U || param == 0x8242U || param == 0xC049U) || (param == 0xC249U) || (param == 73U) || (param == 585U) || (param == 856U) || (param == 4169U) || (param == 4681U) || (param == 2121U) || (param == 0x9049U) || (param == 0x9249U) || (param == 0x2449U) || (param == 0x2649U) || (param == 0x2049U) || (param == 0x2249U) || (param == 0x424DU) || (param == 0x449U) || (param == 0x649U) || (param == 0x1449U) || (param == 0x1649U) || (param == 0x8049U) || (param == 0x8249U) || (param == 0x8449U) || (param == 0x8649U) || (param == 0x9158U) || (param == 0x9358U) || (param == 0x9149U) || (param == 0x9349U) || (param == 0x9164U) || (param == 0x9364U) || (param == 0xd149U) || (param == 0xd349U) || (param == 0xd04dU) || (param == 0xd24dU) || (param == 0x9449U) || (param == 0x9549U) || (param == 0x9558U) || (param == 0x9564U) || (param == 0x9649U) || (param == 0x9749U) || (param == 0x9758U) || (param == 0x9764U) || (param == 0xD44DU) || (param == 0xD549U) || (param == 0xD64DU) || (param == 0xD749U);
|
||||
}
|
||||
|
||||
inline constexpr AolSafetyProfile TOYOTA_AOL_PROFILE{2U, toyota_aol_param, true};
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
from opendbc.car.toyota.dsu_bypass import enabled
|
||||
from openpilot.starpilot.car.toyota.prius_preferences import filter_preference_enabled
|
||||
|
||||
|
||||
class BypassPreference:
|
||||
def __init__(self, cp, params):
|
||||
self.cp, self.params = cp, params
|
||||
self.read_ns = 0
|
||||
self.enabled = False
|
||||
|
||||
def update(self, now_ns):
|
||||
if type(now_ns) is not int or now_ns <= 0 or now_ns < self.read_ns or not enabled(self.cp):
|
||||
self.read_ns = 0
|
||||
self.enabled = False
|
||||
return False
|
||||
if self.read_ns == 0 or now_ns - self.read_ns >= 250_000_000:
|
||||
self.read_ns = now_ns
|
||||
self.enabled = filter_preference_enabled(self.params)
|
||||
return self.enabled
|
||||
@@ -2,15 +2,17 @@
|
||||
from opendbc.car import structs
|
||||
from opendbc.car.toyota.values import CAR
|
||||
from opendbc.car.toyota.rav4h_filter import configured
|
||||
from opendbc.car.toyota import legacy_sdsu, legacy_advert_filter
|
||||
from opendbc.car.toyota import dsu_bypass, legacy_sdsu, legacy_advert_filter
|
||||
from openpilot.starpilot.aol.runtime import AXIS_MAX_AGE_NS, INTENT_MAX_AGE_NS, SAFETY_MAX_AGE_NS, native_inventory_matches_cp
|
||||
|
||||
|
||||
def below_engage_lateral_allowed(cp, cs, intent, native, *, source_ns, now_ns, axis_session_id):
|
||||
try:
|
||||
bypass = dsu_bypass.configured(cp)
|
||||
legacy_advert = legacy_advert_filter.configured(cp)
|
||||
return bool((configured(cp) or legacy_advert) and
|
||||
(cp.carFingerprint in (CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_AVALON) or legacy_sdsu.configured(cp) or legacy_advert) and cp.alternativeExperience == 32 and
|
||||
return bool((bypass or configured(cp) or legacy_advert) and
|
||||
(bypass or cp.carFingerprint in (CAR.TOYOTA_HIGHLANDER, CAR.TOYOTA_AVALON) or legacy_sdsu.configured(cp) or legacy_advert) and
|
||||
cp.alternativeExperience == 32 and
|
||||
cp.steerAtStandstill and cp.minSteerSpeed <= 0 and cp.minEnableSpeed > 0 and 0 <= cs.vEgo < cp.minEnableSpeed and
|
||||
intent is not None and intent.settingsQualified and intent.allowedLatch and intent.lateralArmed and not intent.pauseLateral and
|
||||
intent.producerSessionId and intent.carStateLogMonoTime == source_ns and
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
"""Dom bypass topology, unchanged tune projection and exact stock pairing."""
|
||||
|
||||
import pytest
|
||||
from opendbc.car import structs
|
||||
from opendbc.car.toyota import dsu_bypass
|
||||
from opendbc.car.toyota.interface import CarInterface
|
||||
from opendbc.car.toyota.values import CAR, ToyotaFlags
|
||||
from openpilot.starpilot.car.toyota.aol import qualified
|
||||
from openpilot.starpilot.car.toyota.tests.test_rav4h_caller_native import firmware
|
||||
|
||||
|
||||
def acquired(candidate):
|
||||
if candidate == CAR.TOYOTA_MATRIX_RETROFIT:
|
||||
return []
|
||||
fw = firmware(CAR.TOYOTA_PRIUS if candidate == CAR.TOYOTA_PRIUS_RETROFIT else candidate)
|
||||
if candidate == CAR.TOYOTA_PRIUS_RETROFIT:
|
||||
for row in fw:
|
||||
if row.ecu == structs.CarParams.Ecu.eps:
|
||||
row.fwVersion = b'8965B47070' + bytes(6)
|
||||
return fw
|
||||
|
||||
|
||||
def fingerprint(candidate, address=0x343):
|
||||
pt = {0x260: 8, 0x262: 8 if candidate in dsu_bypass.EPS8_CARS or candidate == CAR.TOYOTA_PRIUS else 5, 0x224: 8, 0x226: 8, 0x1D2: 8, 0x1D3: 8}
|
||||
return {0: pt, 1: {}, 2: {address: 8}}
|
||||
|
||||
|
||||
def factory(candidate, address=0x343):
|
||||
return CarInterface.get_params(candidate, fingerprint(candidate, address), acquired(candidate), False, False, False)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('candidate', sorted(dsu_bypass.PROFILES))
|
||||
@pytest.mark.parametrize('address', (0x343, 0x4CB))
|
||||
@pytest.mark.parametrize('stock', (False, True))
|
||||
def test_exact_identity_current_tunes_and_stock_pair(candidate, address, stock):
|
||||
fp = fingerprint(candidate, address)
|
||||
cp = factory(candidate, address)
|
||||
baseline = CarInterface.get_params(candidate, {**fp, 2: {}}, acquired(candidate), False, False, False)
|
||||
assert dsu_bypass.configured(cp) and qualified(cp) and not cp.dashcamOnly and cp.pcmCruise
|
||||
assert cp.flags & ToyotaFlags.DSU_BYPASS and not cp.flags & ToyotaFlags.LONG_FILTER
|
||||
assert cp.safetyConfigs[0].safetyParam == dsu_bypass.PROFILES[candidate]
|
||||
for field in (
|
||||
'lateralTuning',
|
||||
'longitudinalTuning',
|
||||
'steerActuatorDelay',
|
||||
'steerLimitTimer',
|
||||
'longitudinalActuatorDelay',
|
||||
'minEnableSpeed',
|
||||
'minSteerSpeed',
|
||||
'wheelSpeedFactor',
|
||||
'mass',
|
||||
'wheelbase',
|
||||
'steerRatio',
|
||||
'centerToFront',
|
||||
):
|
||||
assert cp.to_dict()[field] == baseline.to_dict()[field], field
|
||||
if stock:
|
||||
assert dsu_bypass.prepare_stock(cp) and dsu_bypass.configured(cp) and qualified(cp)
|
||||
assert not cp.openpilotLongitudinalControl and cp.safetyConfigs[0].safetyParam == dsu_bypass.PROFILES[candidate] | 0x200
|
||||
|
||||
|
||||
@pytest.mark.parametrize('candidate', (CAR.TOYOTA_CAMRY, CAR.LEXUS_IS, CAR.TOYOTA_PRIUS, CAR.TOYOTA_PRIUS_RETROFIT))
|
||||
@pytest.mark.parametrize('address', (0x343, 0x4CB))
|
||||
def test_native_bus_mirror_is_not_adapter_identity(candidate, address):
|
||||
fp = fingerprint(candidate, address)
|
||||
fw = acquired(candidate)
|
||||
if candidate in (CAR.TOYOTA_PRIUS, CAR.TOYOTA_PRIUS_RETROFIT):
|
||||
for row in fw:
|
||||
if row.ecu == structs.CarParams.Ecu.fwdCamera:
|
||||
row.fwVersion = b'8646F47050'
|
||||
fp[0][address] = 8
|
||||
assert not dsu_bypass.hardware_supported(candidate, fp, fw)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('kind', ('foreign-pedal', 'filter', 'sdsu', 'camera-dlc', 'unknown-eps', 'logging', 'wrong-fw-bus'))
|
||||
def test_mixed_topology_or_unknown_firmware_does_not_enroll(kind):
|
||||
fp = fingerprint(CAR.TOYOTA_RAV4H)
|
||||
fw = acquired(CAR.TOYOTA_RAV4H)
|
||||
if kind in ('foreign-pedal', 'filter', 'sdsu'):
|
||||
fp[0][{'foreign-pedal': 0x201, 'filter': 0x2AA, 'sdsu': 0x2FF}[kind]] = 6 if kind == 'foreign-pedal' else 8
|
||||
elif kind == 'camera-dlc':
|
||||
fp[2][0x343] = 7
|
||||
else:
|
||||
row = next(f for f in fw if f.ecu == structs.CarParams.Ecu.eps)
|
||||
if kind == 'unknown-eps':
|
||||
row.fwVersion = b'unknown'
|
||||
elif kind == 'logging':
|
||||
row.logging = True
|
||||
else:
|
||||
row.bus = 2
|
||||
assert not dsu_bypass.hardware_supported(CAR.TOYOTA_RAV4H, fp, fw)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('candidate', sorted(dsu_bypass.PROFILES))
|
||||
def test_native_eps_and_brake_basis_matches_current_car(candidate):
|
||||
fp = fingerprint(candidate)
|
||||
baseline = CarInterface.get_params(candidate, {**fp, 2: {}}, acquired(candidate), False, False, False)
|
||||
cp = factory(candidate)
|
||||
assert cp.safetyConfigs[0].safetyParam & 0x1FF == baseline.safetyConfigs[0].safetyParam & 0x1FF
|
||||
|
||||
|
||||
@pytest.mark.parametrize('candidate', sorted(dsu_bypass.PROFILES))
|
||||
def test_dom_auto_resume_and_stop_timer_are_model_specific(candidate):
|
||||
from opendbc.car.toyota import legacy_stop_timer
|
||||
cp = factory(candidate)
|
||||
assert cp.autoResumeSng == (candidate in dsu_bypass.AUTO_RESUME_CARS)
|
||||
assert legacy_stop_timer.enabled(cp) == (candidate not in dsu_bypass.AUTO_RESUME_CARS)
|
||||
assert dsu_bypass.prepare_stock(cp)
|
||||
assert not cp.autoResumeSng and not legacy_stop_timer.enabled(cp)
|
||||
@@ -0,0 +1,63 @@
|
||||
"""Factory, Card, SelfdriveD, Controls, CI, C++ heartbeat and native bypass."""
|
||||
|
||||
import pytest
|
||||
from opendbc.car.toyota import dsu_bypass
|
||||
from opendbc.car.toyota.values import CAR
|
||||
from openpilot.starpilot.car.toyota.tests import test_rav4h_caller_native as helpers
|
||||
from openpilot.starpilot.car.toyota.tests.test_dsu_bypass import acquired, fingerprint
|
||||
from openpilot.starpilot.car.toyota.tests.test_toyota_cpp_transport import host_heartbeat_bridge as host_heartbeat_bridge
|
||||
|
||||
source_matched_native = helpers.source_matched_native
|
||||
daemon_gc_scope = helpers.daemon_gc_scope
|
||||
REPRESENTATIVES = (CAR.TOYOTA_RAV4H, CAR.LEXUS_ES, CAR.TOYOTA_CAMRY, CAR.TOYOTA_PRIUS, CAR.TOYOTA_COROLLA, CAR.TOYOTA_PRIUS_V, CAR.LEXUS_IS, CAR.LEXUS_GS_F)
|
||||
|
||||
|
||||
def run(candidate, stock, bridge, scenario='nominal', aol=True):
|
||||
def physical(packer, **fields):
|
||||
fields['sdsu'] = None
|
||||
frames = helpers.physical(packer, **fields)
|
||||
if candidate in dsu_bypass.ALT_MAIN_CARS:
|
||||
frames += [
|
||||
packer.make_can_msg('DSU_CRUISE', 0, {'MAIN_ON': fields.get('main', True), 'SET_SPEED': 90}),
|
||||
packer.make_can_msg('PCM_CRUISE_ALT', 0, {'UI_SET_SPEED': 90}),
|
||||
]
|
||||
frames += [packer.make_can_msg('ACC_CONTROL', 2, {'ACC_TYPE': 1}), packer.make_can_msg('PRE_COLLISION', 2, {}), packer.make_can_msg('PCS_HUD', 2, {})]
|
||||
return frames
|
||||
|
||||
def observe(tick, host, cs, cc, safety, native):
|
||||
del tick, cs, cc, native
|
||||
assert dsu_bypass.configured(host.CP)
|
||||
assert safety.safety_fwd_hook(2, 0x343) == (0 if stock else -1)
|
||||
assert safety.safety_fwd_hook(2, 0x283) == 0
|
||||
|
||||
fp = [(a, bytes(length), bus) for bus, messages in fingerprint(candidate).items() for a, length in messages.items()]
|
||||
manual = candidate in (CAR.TOYOTA_MATRIX_RETROFIT, CAR.TOYOTA_PRIUS_RETROFIT)
|
||||
helpers.run_case(
|
||||
stock,
|
||||
scenario,
|
||||
candidate=candidate,
|
||||
bridge=bridge,
|
||||
input_clock=True,
|
||||
sdsu_words=(dsu_bypass.PROFILES[candidate], dsu_bypass.PROFILES[candidate] | 0x200),
|
||||
physical_frames=physical,
|
||||
on_sample=observe,
|
||||
firmware_override=acquired(candidate),
|
||||
fingerprint_frames=fp,
|
||||
manual_selection=manual,
|
||||
manual_bypass=manual,
|
||||
bypass_owner=True,
|
||||
aol=aol,
|
||||
brake_stop_check_start=355,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('candidate', sorted(dsu_bypass.PROFILES))
|
||||
@pytest.mark.parametrize('stock', (False, True))
|
||||
def test_each_bypass_identity_full_caller(candidate, stock, host_heartbeat_bridge):
|
||||
run(candidate, stock, host_heartbeat_bridge)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('candidate', REPRESENTATIVES)
|
||||
@pytest.mark.parametrize('scenario', ('physical', 'off', 'ordinary'))
|
||||
def test_profile_physical_saved_off_and_ordinary_paths(candidate, scenario, host_heartbeat_bridge):
|
||||
run(candidate, False, host_heartbeat_bridge, 'nominal' if scenario == 'ordinary' else scenario, aol=scenario != 'ordinary')
|
||||
@@ -232,7 +232,7 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H,
|
||||
sdsu_words=(0x9049, 0x9249), alpha_long=False, disable_setting=None, physical_frames=None, angle=False,
|
||||
firmware_override=None, assert_hybrid_release=False, sdsu_mirror=False, on_sample=None, camera_messages=False, filter_advert=False,
|
||||
brake_pause_mps=None, native_rx_expected=None, on_state=None, fingerprint_frames=None, manual_selection=False, native_tx_expected=None,
|
||||
manual_filter_length=None):
|
||||
manual_filter_length=None, manual_bypass=False, bypass_owner=False):
|
||||
SYNTHETIC_LAST.clear()
|
||||
NATIVE_LAST.clear()
|
||||
safety = libsafety_py.libsafety
|
||||
@@ -252,7 +252,16 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H,
|
||||
params.put('AolBrakePauseSpeedMps', float(brake_pause_mps), block=True)
|
||||
fw = firmware(candidate) if firmware_override is None else firmware_override
|
||||
if manual_selection:
|
||||
if manual_filter_length is not None:
|
||||
if manual_bypass:
|
||||
assert fingerprint_frames is not None
|
||||
assert candidate in (CAR.TOYOTA_MATRIX_RETROFIT, CAR.TOYOTA_PRIUS_RETROFIT) and bypass_owner
|
||||
assert any(bus == 2 and address in (0x343, 0x4CB) and len(data) == 8 for address, data, bus in fingerprint_frames)
|
||||
assert not any(address in (0x201, 0x2FF, 0x2AA) for address, _, _ in fingerprint_frames)
|
||||
if candidate == CAR.TOYOTA_MATRIX_RETROFIT:
|
||||
assert not fw and firmware_override == []
|
||||
else:
|
||||
assert any(f.ecu == structs.CarParams.Ecu.eps and f.address == 0x7A1 and f.bus == 0 and bytes(f.fwVersion) == b'8965B47070' + bytes(6) for f in fw)
|
||||
elif manual_filter_length is not None:
|
||||
if candidate == CAR.TOYOTA_MATRIX_RETROFIT:
|
||||
assert manual_filter_length in (4, 8) and not fw and firmware_override == []
|
||||
else:
|
||||
@@ -327,7 +336,7 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H,
|
||||
)
|
||||
)
|
||||
rows = {r.key: r for r in wheel.rows()}
|
||||
if candidate == CAR.TOYOTA_RAV4H:
|
||||
if candidate == CAR.TOYOTA_RAV4H and not bypass_owner:
|
||||
assert 'Bookmark' in rows['wheel:LKASButtonControl'].choices
|
||||
assert 'Toggle AOL' not in rows['wheel:LKASButtonControl'].choices
|
||||
assert not any('Cancel' in k or 'MainCruise' in k for k in rows)
|
||||
@@ -574,7 +583,7 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H,
|
||||
assert not host.CP.openpilotLongitudinalControl and not cc.longActive
|
||||
assert host.CP.safetyConfigs[0].safetyParam == sdsu_words[1]
|
||||
else:
|
||||
preference = host.CI.CC.prius_filter_input if candidate == CAR.TOYOTA_PRIUS else (
|
||||
preference = host.CI.CC.bypass_input if bypass_owner else host.CI.CC.prius_filter_input if candidate == CAR.TOYOTA_PRIUS else (
|
||||
host.CI.CC.advert_filter_input if filter_advert or fingerprint_frames is not None and any(
|
||||
address == 0x2AA for address, _, _ in fingerprint_frames) else host.CI.CC.rav4h_filter_input)
|
||||
assert preference is not None and not preference.update(time.monotonic_ns())
|
||||
|
||||
@@ -175,6 +175,14 @@ def configure_controller(CI, params):
|
||||
prepare_rav4h_stock(cp)
|
||||
elif controller is not None:
|
||||
controller.rav4h_filter_input = Rav4hFilterPreference(cp, params)
|
||||
from opendbc.car.toyota import dsu_bypass
|
||||
if dsu_bypass.enabled(cp):
|
||||
from openpilot.starpilot.car.toyota.bypass_preferences import BypassPreference
|
||||
from openpilot.starpilot.car.toyota.prius_preferences import filter_preference_enabled
|
||||
if not filter_preference_enabled(params):
|
||||
dsu_bypass.prepare_stock(cp)
|
||||
elif controller is not None:
|
||||
controller.bypass_input = BypassPreference(cp, params)
|
||||
from opendbc.car.toyota import advert_filter
|
||||
if advert_filter.enabled(cp):
|
||||
from openpilot.starpilot.car.toyota.advert_preferences import AdvertFilterPreference
|
||||
|
||||
@@ -206,6 +206,8 @@ class VehicleStartupPreferences:
|
||||
prepare_advert_filter_stock(cp)
|
||||
from opendbc.car.toyota.angle_control import prepare_stock as prepare_angle_stock
|
||||
prepare_angle_stock(cp)
|
||||
from opendbc.car.toyota.dsu_bypass import prepare_stock as prepare_bypass_stock
|
||||
prepare_bypass_stock(cp)
|
||||
self._prepare_bolt(cp, fingerprints)
|
||||
prepare_disable_longitudinal(cp, self.disable_bolt_long)
|
||||
self._prepare_camera_pedal(cp)
|
||||
@@ -247,6 +249,8 @@ class VehicleStartupPreferences:
|
||||
prepare_advert_filter_stock(cp)
|
||||
from opendbc.car.toyota.angle_control import prepare_stock as prepare_angle_stock
|
||||
prepare_angle_stock(cp)
|
||||
from opendbc.car.toyota.dsu_bypass import prepare_stock as prepare_bypass_stock
|
||||
prepare_bypass_stock(cp)
|
||||
self._prepare_bolt(cp)
|
||||
prepare_disable_longitudinal(cp, self.disable_bolt_long)
|
||||
self._prepare_camera_pedal(cp)
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"protected_inventory_sha256": "de3ffa5eadfc93f3696ceba58a0260f2578fdc8f99862f6004354df661a83ba4", "schema_version": 1}
|
||||
{"protected_inventory_sha256": "b9097bfbbea2a3eae03349fb84e39dda591f5f60678075d491ef6e4cf1aa3f97", "schema_version": 1}
|
||||
|
||||
@@ -40,6 +40,9 @@ AOL_LIFECYCLE_TARGETS = (
|
||||
'openpilot/starpilot/car/toyota/tests/test_rav4h_pedal_composite_callers.py',
|
||||
'opendbc_repo/opendbc/safety/tests/test_toyota_rav4h_pedal_composite.py',
|
||||
'opendbc_repo/opendbc/safety/tests/test_toyota_rav4h_pedal_order.py',
|
||||
'openpilot/starpilot/car/toyota/tests/test_dsu_bypass.py',
|
||||
'openpilot/starpilot/car/toyota/tests/test_dsu_bypass_callers.py',
|
||||
'opendbc_repo/opendbc/safety/tests/test_toyota_dsu_bypass.py',
|
||||
'opendbc_repo/opendbc/safety/tests/test_toyota_radar_lta_pedal.py',
|
||||
'opendbc_repo/opendbc/safety/tests/test_toyota_prius_retrofit_advert.py',
|
||||
'openpilot/starpilot/aol/tests/test_crossmake_native_admission.py',
|
||||
@@ -242,6 +245,9 @@ RELEASE_TARGETS = (
|
||||
'openpilot/starpilot/car/toyota/tests/test_rav4h_pedal_composite_callers.py',
|
||||
'opendbc_repo/opendbc/safety/tests/test_toyota_rav4h_pedal_composite.py',
|
||||
'opendbc_repo/opendbc/safety/tests/test_toyota_rav4h_pedal_order.py',
|
||||
'openpilot/starpilot/car/toyota/tests/test_dsu_bypass.py',
|
||||
'openpilot/starpilot/car/toyota/tests/test_dsu_bypass_callers.py',
|
||||
'opendbc_repo/opendbc/safety/tests/test_toyota_dsu_bypass.py',
|
||||
'opendbc_repo/opendbc/safety/tests/test_toyota_radar_lta_pedal.py',
|
||||
'opendbc_repo/opendbc/safety/tests/test_toyota_prius_retrofit_advert.py',
|
||||
'opendbc_repo/opendbc/car/hyundai/tests/test_long_cp_copy.py',
|
||||
|
||||
Reference in New Issue
Block a user