mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-07-21 21:02:09 +08:00
FPv2: fingerprint on all FW combinations (#25204)
* Try to fingerprint on all possible combinations * build_fw_dict creates set dict, tries each fw version for addr, subaddr * clean up * static analysis * comment * fix comment * revert changes to test_fw_query_on_routes * remove comment
This commit is contained in:
@@ -228,13 +228,13 @@ def chunks(l, n=128):
|
||||
|
||||
|
||||
def build_fw_dict(fw_versions, filter_brand=None):
|
||||
fw_versions_dict = {}
|
||||
fw_versions_dict = defaultdict(set)
|
||||
for fw in fw_versions:
|
||||
if filter_brand is None or fw.brand == filter_brand:
|
||||
addr = fw.address
|
||||
sub_addr = fw.subAddress if fw.subAddress != 0 else None
|
||||
fw_versions_dict[(addr, sub_addr)] = fw.fwVersion
|
||||
return fw_versions_dict
|
||||
fw_versions_dict[(addr, sub_addr)].add(fw.fwVersion)
|
||||
return dict(fw_versions_dict)
|
||||
|
||||
|
||||
def get_brand_addrs():
|
||||
@@ -271,17 +271,18 @@ def match_fw_to_car_fuzzy(fw_versions_dict, log=True, exclude=None):
|
||||
|
||||
match_count = 0
|
||||
candidate = None
|
||||
for addr, version in fw_versions_dict.items():
|
||||
# All cars that have this FW response on the specified address
|
||||
candidates = all_fw_versions[(addr[0], addr[1], version)]
|
||||
for addr, versions in fw_versions_dict.items():
|
||||
for version in versions:
|
||||
# All cars that have this FW response on the specified address
|
||||
candidates = all_fw_versions[(addr[0], addr[1], version)]
|
||||
|
||||
if len(candidates) == 1:
|
||||
match_count += 1
|
||||
if candidate is None:
|
||||
candidate = candidates[0]
|
||||
# We uniquely matched two different cars. No fuzzy match possible
|
||||
elif candidate != candidates[0]:
|
||||
return set()
|
||||
if len(candidates) == 1:
|
||||
match_count += 1
|
||||
if candidate is None:
|
||||
candidate = candidates[0]
|
||||
# We uniquely matched two different cars. No fuzzy match possible
|
||||
elif candidate != candidates[0]:
|
||||
return set()
|
||||
|
||||
if match_count >= 2:
|
||||
if log:
|
||||
@@ -303,23 +304,23 @@ def match_fw_to_car_exact(fw_versions_dict):
|
||||
for ecu, expected_versions in fws.items():
|
||||
ecu_type = ecu[0]
|
||||
addr = ecu[1:]
|
||||
found_version = fw_versions_dict.get(addr, None)
|
||||
if ecu_type == Ecu.esp and candidate in (TOYOTA.RAV4, TOYOTA.COROLLA, TOYOTA.HIGHLANDER, TOYOTA.SIENNA, TOYOTA.LEXUS_IS) and found_version is None:
|
||||
found_versions = fw_versions_dict.get(addr, set())
|
||||
if ecu_type == Ecu.esp and candidate in (TOYOTA.RAV4, TOYOTA.COROLLA, TOYOTA.HIGHLANDER, TOYOTA.SIENNA, TOYOTA.LEXUS_IS) and not len(found_versions):
|
||||
continue
|
||||
|
||||
# On some Toyota models, the engine can show on two different addresses
|
||||
if ecu_type == Ecu.engine and candidate in (TOYOTA.CAMRY, TOYOTA.COROLLA_TSS2, TOYOTA.CHR, TOYOTA.LEXUS_IS) and found_version is None:
|
||||
if ecu_type == Ecu.engine and candidate in (TOYOTA.CAMRY, TOYOTA.COROLLA_TSS2, TOYOTA.CHR, TOYOTA.LEXUS_IS) and not len(found_versions):
|
||||
continue
|
||||
|
||||
# Ignore non essential ecus
|
||||
if ecu_type not in ESSENTIAL_ECUS and found_version is None:
|
||||
if ecu_type not in ESSENTIAL_ECUS and not len(found_versions):
|
||||
continue
|
||||
|
||||
# Virtual debug ecu doesn't need to match the database
|
||||
if ecu_type == Ecu.debug:
|
||||
continue
|
||||
|
||||
if found_version not in expected_versions:
|
||||
if not any([found_version in expected_versions for found_version in found_versions]):
|
||||
invalid.append(candidate)
|
||||
break
|
||||
|
||||
@@ -327,19 +328,16 @@ def match_fw_to_car_exact(fw_versions_dict):
|
||||
|
||||
|
||||
def match_fw_to_car(fw_versions, allow_fuzzy=True):
|
||||
versions = get_interface_attr('FW_VERSIONS', ignore_none=True)
|
||||
|
||||
# Try exact matching first
|
||||
exact_matches = [(True, match_fw_to_car_exact)]
|
||||
if allow_fuzzy:
|
||||
exact_matches.append((False, match_fw_to_car_fuzzy))
|
||||
|
||||
for exact_match, match_func in exact_matches:
|
||||
# For each brand, attempt to fingerprint using FW returned from its queries
|
||||
# TODO: For each brand, attempt to fingerprint using only FW returned from its queries
|
||||
matches = set()
|
||||
for brand in versions.keys():
|
||||
fw_versions_dict = build_fw_dict(fw_versions, filter_brand=brand)
|
||||
matches |= match_func(fw_versions_dict)
|
||||
fw_versions_dict = build_fw_dict(fw_versions, filter_brand=None)
|
||||
matches |= match_func(fw_versions_dict)
|
||||
|
||||
if len(matches):
|
||||
return exact_match, matches
|
||||
@@ -408,7 +406,9 @@ def get_fw_versions_ordered(logcan, sendcan, ecu_rx_addrs, timeout=0.1, debug=Fa
|
||||
for brand in sorted(brand_matches, key=lambda b: len(brand_matches[b]), reverse=True):
|
||||
car_fw = get_fw_versions(logcan, sendcan, query_brand=brand, timeout=timeout, debug=debug, progress=progress)
|
||||
all_car_fw.extend(car_fw)
|
||||
matches = match_fw_to_car_exact(build_fw_dict(car_fw))
|
||||
|
||||
# TODO: Until erroneous FW versions are removed, try to fingerprint on all possible combinations so far
|
||||
_, matches = match_fw_to_car(all_car_fw, allow_fuzzy=False)
|
||||
if len(matches) == 1:
|
||||
break
|
||||
|
||||
|
||||
@@ -89,24 +89,9 @@ if __name__ == "__main__":
|
||||
print("not in supported cars")
|
||||
break
|
||||
|
||||
# Older routes only have carFw from their brand
|
||||
old_route = not any([len(fw.brand) for fw in car_fw])
|
||||
brands = SUPPORTED_BRANDS if not old_route else [None]
|
||||
|
||||
# Exact match
|
||||
exact_matches, fuzzy_matches = [], []
|
||||
for brand in brands:
|
||||
fw_versions_dict = build_fw_dict(car_fw, filter_brand=brand)
|
||||
exact_matches = match_fw_to_car_exact(fw_versions_dict)
|
||||
if len(exact_matches) == 1:
|
||||
break
|
||||
|
||||
# Fuzzy match
|
||||
for brand in brands:
|
||||
fw_versions_dict = build_fw_dict(car_fw, filter_brand=brand)
|
||||
fuzzy_matches = match_fw_to_car_fuzzy(fw_versions_dict)
|
||||
if len(fuzzy_matches) == 1:
|
||||
break
|
||||
fw_versions_dict = build_fw_dict(car_fw)
|
||||
exact_matches = match_fw_to_car_exact(fw_versions_dict)
|
||||
fuzzy_matches = match_fw_to_car_fuzzy(fw_versions_dict)
|
||||
|
||||
if (len(exact_matches) == 1) and (list(exact_matches)[0] == live_fingerprint):
|
||||
good_exact += 1
|
||||
|
||||
Reference in New Issue
Block a user