diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py index bc94ae54d3..eeabbd9c06 100644 --- a/selfdrive/car/toyota/values.py +++ b/selfdrive/car/toyota/values.py @@ -239,24 +239,52 @@ SHORT_FW_PATTERN = re.compile(b'(?P[A-Z0-9]{4})(?P[A-Z0-9]{4} MED_PATTERN = re.compile(b'TODO') FW_PATTERN = re.compile(b'(?P[0-9A-Z]{4})[0-9A-Z](?P[A-Z0-9]{2})(?P[A-Z0-9]{2})(?P[A-Z0-9]{3})') + def get_platform_codes(fw_versions: List[bytes]) -> Set[Tuple[bytes, Optional[bytes]]]: # Returns unique, platform-specific identification codes for a set of versions codes = set() # (code-Optional[part], date) for fw in fw_versions: - has_length = fw[0] < 0xf - length = 1 - if has_length: - length = fw[0] + # FW versions returned from UDS queries can return multiple fields/chunks of data (different ECU calibrations, different data?) + # and are prefixed with a byte that describes how many chunks of data there are. + # But FW returned from KWP requires querying of each sub-data id and does not have a length prefix. + has_n_chunks = fw[0] < 0xf # max seen is 3 chunks, 16 bytes each + n_chunks = 1 + print(f'{has_n_chunks=}') + if has_n_chunks: + n_chunks = fw[0] fw = fw[1:] - assert length * 16 == len(fw) + assert n_chunks * 16 == len(fw) - chunks = [fw[16 * i:16 * i + 16] for i in range(length)] - print(fw, chunks) + chunks = [fw[16 * i:16 * i + 16] for i in range(n_chunks)] + # chunks = [s for s in fw.split(b'\x00') if len(s)] + chunks = [c.strip(b'\x00 ') for c in chunks] + a = list(map(len, chunks)) + print(fw, chunks, a) + # assert len(set(a)) == 1 # only first is considered for now since second is commonly shared (TODO: understand that) first_chunk = chunks[0] # doesn't have a part encoded in version (OBD query?) - short_version = sum(b > 0xf for b in first_chunk) == 8 + # short_version = sum(b > 0xf for b in first_chunk) == 8 + short_version = len(first_chunk) == 8 + if short_version: + print('short version') + code_match = SHORT_FW_PATTERN.search(first_chunk) + if code_match is not None: + code, version = code_match.groups() + print('platform code, version', code, version) + elif len(first_chunk) == 10: + # not done + pass + elif len(first_chunk) == 12: + print(FW_PATTERN) + code_match = FW_PATTERN.search(first_chunk) + if code_match is not None: + print('got long match!') + print(first_chunk, code_match, code_match.groups()) + + else: + assert False, f'invalid length: {len(first_chunk)}' continue @@ -266,8 +294,8 @@ def get_platform_codes(fw_versions: List[bytes]) -> Set[Tuple[bytes, Optional[by assert len(sections) > 0 assert len(sections[0]) > 0 - has_length = sections[0][0] < 0xf - if has_length: + has_n_chunks = sections[0][0] < 0xf + if has_n_chunks: assert len(sections) == sections[0][0] sections[0] = sections[0][1:] @@ -375,8 +403,8 @@ FW_QUERY_CONFIG = FwQueryConfig( ], ) -FW_PATTERN = re.compile(b'[0-9]{4}[0-9A-Z][0-9A-Z]') -FW_PATTERN2 = re.compile(br'(?<=\\x[0-9]{2})[0-9A-Z]{5}|^[0-9A-Z]{5}') +# FW_PATTERN = re.compile(b'[0-9]{4}[0-9A-Z][0-9A-Z]') +# FW_PATTERN2 = re.compile(br'(?<=\\x[0-9]{2})[0-9A-Z]{5}|^[0-9A-Z]{5}') FW_LEN_CODE = re.compile(b'^[\x00-\x0F]') FW_PATTERN_V3 = re.compile(b'(?P^[\x00-\x0F])?(?P[0-9A-Z]{4})')