diff --git a/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py index 8f580c9b90..3f303912ad 100644 --- a/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py +++ b/opendbc_repo/opendbc/car/hyundai/hyundaicanfd.py @@ -1,10 +1,10 @@ import math +from binascii import crc_hqx from typing import cast import numpy as np from opendbc.car import CanBusBase, CanData from opendbc.car.common.conversions import Conversions as CV -from opendbc.car.crc import CRC16_XMODEM from opendbc.car.hyundai.ioniq6_bsm import BlindspotStatus, FRONT_NEUTRAL_BODY, rear_body from opendbc.car.hyundai.values import CAR, HyundaiFlags @@ -437,11 +437,7 @@ def create_adrv_messages(packer, CAN, frame, *, template=None, drive_gear=False, def hkg_can_fd_checksum(address: int, sig, d: bytearray) -> int: - crc = 0 - for i in range(2, len(d)): - crc = ((crc << 8) ^ CRC16_XMODEM[(crc >> 8) ^ d[i]]) & 0xFFFF - crc = ((crc << 8) ^ CRC16_XMODEM[(crc >> 8) ^ ((address >> 0) & 0xFF)]) & 0xFFFF - crc = ((crc << 8) ^ CRC16_XMODEM[(crc >> 8) ^ ((address >> 8) & 0xFF)]) & 0xFFFF + crc = crc_hqx(d[2:] + (address & 0xFFFF).to_bytes(2, "little"), 0) if len(d) == 8: crc ^= 0x5F29 elif len(d) == 16: diff --git a/opendbc_repo/opendbc/car/hyundai/tests/test_canfd_checksum.py b/opendbc_repo/opendbc/car/hyundai/tests/test_canfd_checksum.py new file mode 100644 index 0000000000..0446ef085e --- /dev/null +++ b/opendbc_repo/opendbc/car/hyundai/tests/test_canfd_checksum.py @@ -0,0 +1,63 @@ +import unittest + +from opendbc.car.hyundai.hyundaicanfd import hkg_can_fd_checksum + + +def reference_checksum(address, data): + crc = 0 + for byte in (*data[2:], address & 0xFF, (address >> 8) & 0xFF): + for bit in range(7, -1, -1): + feedback = (crc >> 15) ^ ((byte >> bit) & 1) + crc = (crc << 1) & 0xFFFF + if feedback: + crc ^= 0x1021 + return crc ^ {8: 0x5F29, 16: 0x041D, 24: 0x819D, 32: 0x9F5B}.get(len(data), 0) + + +class TestCanfdChecksum(unittest.TestCase): + def test_matches_bitwise_reference_and_preserves_input(self): + addresses = (0, 1, 0x1234, 0x7FE, 0x7FF, 0x800, 0x801, + 0xFFFE, 0xFFFF, 0x10000, 0x10001, + 0x1FFFFFFE, 0x1FFFFFFF, 0x20000000, + -1, -0x10001, (1 << 160) | 0x1234) + for length in range(65): + payloads = (bytes(length), b"\xff" * length, + bytes((i * 37 + length * 13) & 0xFF for i in range(length))) + for pattern, payload in enumerate(payloads): + for address in addresses: + expected = reference_checksum(address, payload) + for container in (bytes, bytearray): + with self.subTest(length=length, pattern=pattern, address=address, container=container.__name__): + data = container(payload) + self.assertEqual(hkg_can_fd_checksum(address, None, data), expected) + self.assertEqual(data, payload) + + def test_first_two_bytes_are_ignored(self): + for length in range(65): + payload = bytes((i * 29 + 17) & 0xFF for i in range(length)) + expected = reference_checksum(0x1234, payload) + for prefix in (b"\x00\x00", b"\xff\xff", b"\x5a\xa5"): + for container in (bytes, bytearray): + with self.subTest(length=length, prefix=prefix, container=container.__name__): + data = container(prefix[:min(2, length)] + payload[2:]) + self.assertEqual(hkg_can_fd_checksum(0x1234, None, data), expected) + + def test_only_low_sixteen_address_bits_are_used(self): + for length in range(65): + payload = bytes((i * 19 + 3) & 0xFF for i in range(length)) + for low_address in (0, 0x7FF, 0x800, 0x1234, 0xFFFF): + expected = reference_checksum(low_address, payload) + for address in (low_address - (1 << 80), low_address | (1 << 160)): + for container in (bytes, bytearray): + with self.subTest(length=length, address=address, container=container.__name__): + self.assertEqual(hkg_can_fd_checksum(address, None, container(payload)), expected) + + def test_zero_payload_length_adjustments(self): + for length, expected in ((0, 0), (1, 0), (2, 0), (8, 0x5F29), + (16, 0x041D), (24, 0x819D), (32, 0x9F5B), (64, 0)): + with self.subTest(length=length): + self.assertEqual(hkg_can_fd_checksum(0, None, bytes(length)), expected) + + +if __name__ == "__main__": + unittest.main() diff --git a/prebuilt.json b/prebuilt.json index cbd114bc53..b89086b43e 100644 --- a/prebuilt.json +++ b/prebuilt.json @@ -1 +1 @@ -{"protected_inventory_sha256": "ec474989597c90246eef09acaacab24b8bbf68c04b1271dbac521e005b84082a", "schema_version": 1} +{"protected_inventory_sha256": "13836c06f15783e9b64f424907c835e5acde61997c1c6a106f8037ee6560fded", "schema_version": 1}