Ignore Toyota transmit receipts when checking adapter identity

This commit is contained in:
firestar5683
2026-10-26 21:54:11 -05:00
parent c604521745
commit 9c0cbcd5f4
7 changed files with 66 additions and 0 deletions
@@ -98,6 +98,10 @@ class CameraTwoAACANParser(AdvertFilterCANParser):
for stamp, frames in strings:
accepted = []
for address, data, bus in frames:
# pandad marks TX confirmations/rejections with bus >= 128; they
# are not received hardware (see panda.h CAN_*_BUS_OFFSET).
if bus >= 128:
continue
if address in (0x201, 0x2FF):
self.hardware_ambiguous = True
continue
@@ -139,6 +139,10 @@ class BypassCANParser(CANParser):
for stamp, frames in strings:
accepted = []
for address, data, bus in frames:
# pandad marks TX confirmations/rejections with bus >= 128; they
# are not received hardware (see panda.h CAN_*_BUS_OFFSET).
if bus >= 128:
continue
if address in (0x201, 0x2FF, 0x2AA):
self.ambiguous = True
if bus == self.bus:
@@ -82,6 +82,10 @@ class PriusAdvertCANParser(AdvertFilterCANParser):
for stamp, frames in strings:
frames = list(frames)
for address, data, bus in frames:
# pandad marks TX confirmations/rejections with bus >= 128; they
# are not received hardware (see panda.h CAN_*_BUS_OFFSET).
if bus >= 128:
continue
if address in (0x201, 0x2AA) or address == 0x2FF and (bus not in (0, 2) or len(data) != 4):
self.hardware_ambiguous = True
batches.append((stamp, frames))
@@ -85,6 +85,10 @@ class PriusSDSUCANParser(Rav4hCANParser):
for stamp, frames in strings:
accepted = []
for address, data, bus in frames:
# pandad marks TX confirmations/rejections with bus >= 128; they
# are not received hardware (see panda.h CAN_*_BUS_OFFSET).
if bus >= 128:
continue
if address in (0x201, 0x2AA) or address == 0x2FF and (bus not in (0, 2) or len(data) == 4):
self.hardware_ambiguous = True
if bus == self.bus and address in (0x1D3, 0x262):
@@ -0,0 +1,44 @@
"""Transport receipts must neither revoke hardware identity nor refresh RX leases."""
import pytest
from opendbc.can import CANPacker
from opendbc.car import Bus
from opendbc.car.toyota import camera_2aa_filter, dsu_bypass, prius_advert_filter, prius_sdsu
from opendbc.car.toyota.values import CAR, DBC
PARSERS = (prius_advert_filter.PriusAdvertCANParser, prius_sdsu.PriusSDSUCANParser,
camera_2aa_filter.CameraTwoAACANParser, dsu_bypass.BypassCANParser)
def ambiguous(parser):
return getattr(parser, 'hardware_ambiguous', getattr(parser, 'ambiguous', False))
@pytest.mark.parametrize('parser_type', PARSERS)
@pytest.mark.parametrize('bus', (128, 130, 132, 192, 194, 196))
def test_receipts_do_not_change_identity_or_supply_main_eps(parser_type, bus):
dbc = DBC[CAR.TOYOTA_PRIUS][Bus.pt]
packer = CANPacker(dbc)
parser = parser_type(dbc, [('PCM_CRUISE_2', 10), ('EPS_STATUS', 25)], 0)
main = packer.make_can_msg('PCM_CRUISE_2', 0, {'MAIN_ON': 1})
eps = packer.make_can_msg('EPS_STATUS', 0, {'LKA_STATE': 1})
receipts = [(a, data, bus) for a, data, _ in (main, eps)]
receipts += [(a, bytes(n), bus) for a, n in ((0x201, 6), (0x2AA, 8), (0x2FF, 4), (0x2FF, 8))]
parser.update([(2_000_000_000, receipts)])
assert not ambiguous(parser) and not parser.main_valid and not parser.eps_valid
parser.update([(2_010_000_000, [main, eps])])
stamp = parser.ts_nanos['PCM_CRUISE_2']['MAIN_ON']
assert not ambiguous(parser) and parser.main_valid and parser.eps_valid
parser.update([(2_020_000_000, receipts)])
assert not ambiguous(parser) and parser.main_valid and parser.eps_valid
assert parser.ts_nanos['PCM_CRUISE_2']['MAIN_ON'] == stamp
@pytest.mark.parametrize('parser_type', PARSERS)
@pytest.mark.parametrize('bus', (0, 1, 2, 4))
def test_real_conflicting_hardware_stays_latched(parser_type, bus):
dbc = DBC[CAR.TOYOTA_PRIUS][Bus.pt]
parser = parser_type(dbc, [('PCM_CRUISE_2', 10), ('EPS_STATUS', 25)], 0)
parser.update([(2_000_000_000, [(0x201, bytes(6), bus)])])
assert ambiguous(parser)
parser.update([(2_010_000_000, [])])
assert ambiguous(parser)
@@ -19,6 +19,9 @@ def test_eps73_advert_actual_cold_callers(candidate,stock,host_heartbeat_bridge)
frames=helpers.physical(packer,**fields)
assert len(next(data for address,data,bus in frames if address==0x262 and bus==0))==8
frames.extend(((0x2FF,bytes.fromhex('80007409'),0),(0x2FF,bytes.fromhex('80007409'),2)))
# Route 16c1c1b1b2152da0/00000001--a0679e3a1b: after the
# safety handoff, forwarded four-byte advertisements return on bus 130.
frames.extend((address,data,bus+128) for address,data,bus in list(frames) if bus == 2 or address == 0x2FF)
return frames
def observe(tick,host,cs,cc,safety,native):
@@ -419,6 +419,9 @@ def run_case(stock, scenario='nominal', *, aol=True, candidate=CAR.TOYOTA_RAV4H,
malformed = packer.make_can_msg('SDSU', 0, {'STATE': 0})
frames.append((malformed[0], malformed[1][:7], malformed[2]))
for a, d, bus in frames:
# USB TX receipts are delivered to host parsers, never native RX.
if bus >= 128:
continue
accepted = bool(safety.safety_rx_hook(libsafety_py.make_CANPacket(a, bus, d)))
expected = not (a == 0x2FF and bus == 0 and 0 < (d[2] >> 4) < 7)
if native_rx_expected is not None: