Files
panda-meb/python/__init__.py

810 lines
26 KiB
Python
Raw Normal View History

2017-04-06 18:11:36 -07:00
# python library to interface with panda
2017-07-17 15:29:31 -07:00
import os
import sys
2017-07-17 15:29:31 -07:00
import time
import usb1
import struct
import hashlib
import binascii
from functools import wraps, partial
from itertools import accumulate
from opendbc.car.structs import CarParams
from .base import BaseHandle
from .constants import FW_PATH, McuType
from .dfu import PandaDFU
from .spi import PandaSpiHandle, PandaSpiException, PandaProtocolMismatch
from .usb import PandaUsbHandle
from .utils import logger
2017-04-06 18:11:36 -07:00
CAN_FIFOMailBox to CANPacket struct + USB dynamic packet size (#739) * Squashed commits, no cleanup * Few fixes * No init = garbage * Only receive with new canpacket * Add send with canpacket * Revert "Add send with canpacket" This reverts commit 7d06686ddd6d447c714b5289d31af24403d36931. * Packet must be aligned to word, or bad performance * Cleaner * Fix tests * Tests... * MISRA 10.4 * More MISRA * libpandasafety_py * cffi * even more tests... * typo * ... * ... * ... * Slight cleanup * MISRA 6.1 * MISRA 17.7 * Bug in bxcan + even style * MISRA 10.1 * Revert "MISRA 10.1" This reverts commit 404ae7fcc39556f80f528de9015702e69f4ea0a5. * ... * MISRA 10.1 and 10.4 suppress until next PR * MISRA 20.1 * ... * test_honda * ... * ... * test_toyota * test_volkswagen_mqb * test_volkswagen_pq * Sketchy thing... * Revert "Sketchy thing..." This reverts commit 3b2e5715bdc1954f7b7b3b7469ba3d0eaa06bdf9. * remove comment * bxcan extended address bug * Concept, experimental dynamic usb packet size * increase each buffer to 10240 bytes * raise python bulk read/write limits * ... * Move packet size to start * Experimental send, stream-like * New receive test, stream-like * cleanup * cleanup + rebase fixes * MISRA * Extra receive method, stream-like, commented out * type change * Revert back to buffer for send, stream commented * forgot ZLP * lower buffer, add rx failsafe * ... remove ZLP * return ZLP back * Add tx checks to panda fw * TX stream with counter * fix counter overflow * 13 free slots should be enough * limit tx usb packet * ... * Revert max_bulk_msg doubling * python lib improve speed * Stream with counter for RX, dirty, needs cleanup * Increase chunk length to 4096 bytes * cleanup fdcan.h * cleanup __init__.py * MISRA 12.1 * MISRA 10.8 * remove non-streaming usb functions * more main.c cleanup * MISRA 15.6 * MISRA 15.5 * MISRA 18.4 and suppress objectIndex * handling usb pakcets > 63bytes, naming and cleanup * Cleanup old from tests and update CANPacket_t struct * Switch to 4 bit DLC instead of 6 bit length * ops) * ... * pylint * receive python buffer increase * USB increase receive packet len * tweak buffers * No need for so high limits * MISRA 20.1 workaround * performance tweaks * cleanup, dlc to data_len_code naming * main.c naming * comments and cleanup for main.c usb * clean py lib * pylint * do not discard good rx messages on stream fail * cleanups * naming * remove bitstruct lib and lower tx limit * bitstruct lefovers * fix bug in VW test * remove adjusting data size and assert on wrong len * ... * test new memcpy before merging * Revert "test new memcpy before merging" This reverts commit 399465a264835061adabdd785718c4b6fc18c267. * macros for to/fromuint8_t array * MISRA hates me! * tests.c include macros instead * move CANPacket to can_definitions.h * vw_pq python test fix * new memcpy test, REMOVE * check without alignment * revert macros for uint8 arrays * Revert "revert macros for uint8 arrays" This reverts commit 581a9db735a42d0d68200bd270d87a8fd34e43fe. * check assert * Revert "check assert" This reverts commit 9e970d029a50597a1718b2bb0260196c050fd77f. * one more variation * Revert "one more variation" This reverts commit f6c0528b7ac7e125750dc0d9445c7ce97f6954b5. * what about read performance * Revert "what about read performance" This reverts commit d2610f90958a816fe7f1822157a84f85e97d9249. * check struct alignment to word * check for aligned memcpy again * cleanup * add CANPacket structure diagram * update CANPacket and add USB packet struct * bugfix + refactoring of EP1 * move dlc_to_len to header * missed include * typo... * MISRA * fk * lower MAX_CAN_MSGS_PER_BULK_TRANSFER * bump CAN_PACKET_VERSION to 2 * bump python lib CAN_PACKET_VERSION to 2 * rename parse_can_buffer to unpack_can_buffer * CANPacket_t const fields * Revert "CANPacket_t const fields" This reverts commit cf91c035b7706a14e317550c5f0501ae3fce7c70. * test.c relative path * cleanup * move macros to safety_declarations * Refactor pack/unpack funcs and add unittest * usb_protocol.h * oops * Update .github/workflows/test.yaml Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> * remove print from unittest Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2021-11-12 16:36:34 -08:00
__version__ = '0.0.10'
CANPACKET_HEAD_SIZE = 0x6
CAN_FIFOMailBox to CANPacket struct + USB dynamic packet size (#739) * Squashed commits, no cleanup * Few fixes * No init = garbage * Only receive with new canpacket * Add send with canpacket * Revert "Add send with canpacket" This reverts commit 7d06686ddd6d447c714b5289d31af24403d36931. * Packet must be aligned to word, or bad performance * Cleaner * Fix tests * Tests... * MISRA 10.4 * More MISRA * libpandasafety_py * cffi * even more tests... * typo * ... * ... * ... * Slight cleanup * MISRA 6.1 * MISRA 17.7 * Bug in bxcan + even style * MISRA 10.1 * Revert "MISRA 10.1" This reverts commit 404ae7fcc39556f80f528de9015702e69f4ea0a5. * ... * MISRA 10.1 and 10.4 suppress until next PR * MISRA 20.1 * ... * test_honda * ... * ... * test_toyota * test_volkswagen_mqb * test_volkswagen_pq * Sketchy thing... * Revert "Sketchy thing..." This reverts commit 3b2e5715bdc1954f7b7b3b7469ba3d0eaa06bdf9. * remove comment * bxcan extended address bug * Concept, experimental dynamic usb packet size * increase each buffer to 10240 bytes * raise python bulk read/write limits * ... * Move packet size to start * Experimental send, stream-like * New receive test, stream-like * cleanup * cleanup + rebase fixes * MISRA * Extra receive method, stream-like, commented out * type change * Revert back to buffer for send, stream commented * forgot ZLP * lower buffer, add rx failsafe * ... remove ZLP * return ZLP back * Add tx checks to panda fw * TX stream with counter * fix counter overflow * 13 free slots should be enough * limit tx usb packet * ... * Revert max_bulk_msg doubling * python lib improve speed * Stream with counter for RX, dirty, needs cleanup * Increase chunk length to 4096 bytes * cleanup fdcan.h * cleanup __init__.py * MISRA 12.1 * MISRA 10.8 * remove non-streaming usb functions * more main.c cleanup * MISRA 15.6 * MISRA 15.5 * MISRA 18.4 and suppress objectIndex * handling usb pakcets > 63bytes, naming and cleanup * Cleanup old from tests and update CANPacket_t struct * Switch to 4 bit DLC instead of 6 bit length * ops) * ... * pylint * receive python buffer increase * USB increase receive packet len * tweak buffers * No need for so high limits * MISRA 20.1 workaround * performance tweaks * cleanup, dlc to data_len_code naming * main.c naming * comments and cleanup for main.c usb * clean py lib * pylint * do not discard good rx messages on stream fail * cleanups * naming * remove bitstruct lib and lower tx limit * bitstruct lefovers * fix bug in VW test * remove adjusting data size and assert on wrong len * ... * test new memcpy before merging * Revert "test new memcpy before merging" This reverts commit 399465a264835061adabdd785718c4b6fc18c267. * macros for to/fromuint8_t array * MISRA hates me! * tests.c include macros instead * move CANPacket to can_definitions.h * vw_pq python test fix * new memcpy test, REMOVE * check without alignment * revert macros for uint8 arrays * Revert "revert macros for uint8 arrays" This reverts commit 581a9db735a42d0d68200bd270d87a8fd34e43fe. * check assert * Revert "check assert" This reverts commit 9e970d029a50597a1718b2bb0260196c050fd77f. * one more variation * Revert "one more variation" This reverts commit f6c0528b7ac7e125750dc0d9445c7ce97f6954b5. * what about read performance * Revert "what about read performance" This reverts commit d2610f90958a816fe7f1822157a84f85e97d9249. * check struct alignment to word * check for aligned memcpy again * cleanup * add CANPacket structure diagram * update CANPacket and add USB packet struct * bugfix + refactoring of EP1 * move dlc_to_len to header * missed include * typo... * MISRA * fk * lower MAX_CAN_MSGS_PER_BULK_TRANSFER * bump CAN_PACKET_VERSION to 2 * bump python lib CAN_PACKET_VERSION to 2 * rename parse_can_buffer to unpack_can_buffer * CANPacket_t const fields * Revert "CANPacket_t const fields" This reverts commit cf91c035b7706a14e317550c5f0501ae3fce7c70. * test.c relative path * cleanup * move macros to safety_declarations * Refactor pack/unpack funcs and add unittest * usb_protocol.h * oops * Update .github/workflows/test.yaml Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> * remove print from unittest Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2021-11-12 16:36:34 -08:00
DLC_TO_LEN = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64]
LEN_TO_DLC = {length: dlc for (dlc, length) in enumerate(DLC_TO_LEN)}
PANDA_CAN_CNT = 3
CAN_FIFOMailBox to CANPacket struct + USB dynamic packet size (#739) * Squashed commits, no cleanup * Few fixes * No init = garbage * Only receive with new canpacket * Add send with canpacket * Revert "Add send with canpacket" This reverts commit 7d06686ddd6d447c714b5289d31af24403d36931. * Packet must be aligned to word, or bad performance * Cleaner * Fix tests * Tests... * MISRA 10.4 * More MISRA * libpandasafety_py * cffi * even more tests... * typo * ... * ... * ... * Slight cleanup * MISRA 6.1 * MISRA 17.7 * Bug in bxcan + even style * MISRA 10.1 * Revert "MISRA 10.1" This reverts commit 404ae7fcc39556f80f528de9015702e69f4ea0a5. * ... * MISRA 10.1 and 10.4 suppress until next PR * MISRA 20.1 * ... * test_honda * ... * ... * test_toyota * test_volkswagen_mqb * test_volkswagen_pq * Sketchy thing... * Revert "Sketchy thing..." This reverts commit 3b2e5715bdc1954f7b7b3b7469ba3d0eaa06bdf9. * remove comment * bxcan extended address bug * Concept, experimental dynamic usb packet size * increase each buffer to 10240 bytes * raise python bulk read/write limits * ... * Move packet size to start * Experimental send, stream-like * New receive test, stream-like * cleanup * cleanup + rebase fixes * MISRA * Extra receive method, stream-like, commented out * type change * Revert back to buffer for send, stream commented * forgot ZLP * lower buffer, add rx failsafe * ... remove ZLP * return ZLP back * Add tx checks to panda fw * TX stream with counter * fix counter overflow * 13 free slots should be enough * limit tx usb packet * ... * Revert max_bulk_msg doubling * python lib improve speed * Stream with counter for RX, dirty, needs cleanup * Increase chunk length to 4096 bytes * cleanup fdcan.h * cleanup __init__.py * MISRA 12.1 * MISRA 10.8 * remove non-streaming usb functions * more main.c cleanup * MISRA 15.6 * MISRA 15.5 * MISRA 18.4 and suppress objectIndex * handling usb pakcets > 63bytes, naming and cleanup * Cleanup old from tests and update CANPacket_t struct * Switch to 4 bit DLC instead of 6 bit length * ops) * ... * pylint * receive python buffer increase * USB increase receive packet len * tweak buffers * No need for so high limits * MISRA 20.1 workaround * performance tweaks * cleanup, dlc to data_len_code naming * main.c naming * comments and cleanup for main.c usb * clean py lib * pylint * do not discard good rx messages on stream fail * cleanups * naming * remove bitstruct lib and lower tx limit * bitstruct lefovers * fix bug in VW test * remove adjusting data size and assert on wrong len * ... * test new memcpy before merging * Revert "test new memcpy before merging" This reverts commit 399465a264835061adabdd785718c4b6fc18c267. * macros for to/fromuint8_t array * MISRA hates me! * tests.c include macros instead * move CANPacket to can_definitions.h * vw_pq python test fix * new memcpy test, REMOVE * check without alignment * revert macros for uint8 arrays * Revert "revert macros for uint8 arrays" This reverts commit 581a9db735a42d0d68200bd270d87a8fd34e43fe. * check assert * Revert "check assert" This reverts commit 9e970d029a50597a1718b2bb0260196c050fd77f. * one more variation * Revert "one more variation" This reverts commit f6c0528b7ac7e125750dc0d9445c7ce97f6954b5. * what about read performance * Revert "what about read performance" This reverts commit d2610f90958a816fe7f1822157a84f85e97d9249. * check struct alignment to word * check for aligned memcpy again * cleanup * add CANPacket structure diagram * update CANPacket and add USB packet struct * bugfix + refactoring of EP1 * move dlc_to_len to header * missed include * typo... * MISRA * fk * lower MAX_CAN_MSGS_PER_BULK_TRANSFER * bump CAN_PACKET_VERSION to 2 * bump python lib CAN_PACKET_VERSION to 2 * rename parse_can_buffer to unpack_can_buffer * CANPacket_t const fields * Revert "CANPacket_t const fields" This reverts commit cf91c035b7706a14e317550c5f0501ae3fce7c70. * test.c relative path * cleanup * move macros to safety_declarations * Refactor pack/unpack funcs and add unittest * usb_protocol.h * oops * Update .github/workflows/test.yaml Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> * remove print from unittest Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2021-11-12 16:36:34 -08:00
def calculate_checksum(data):
res = 0
for b in data:
res ^= b
return res
def pack_can_buffer(arr, chunk=False, fd=False):
snds = [bytearray(), ]
for address, dat, bus in arr:
CAN_FIFOMailBox to CANPacket struct + USB dynamic packet size (#739) * Squashed commits, no cleanup * Few fixes * No init = garbage * Only receive with new canpacket * Add send with canpacket * Revert "Add send with canpacket" This reverts commit 7d06686ddd6d447c714b5289d31af24403d36931. * Packet must be aligned to word, or bad performance * Cleaner * Fix tests * Tests... * MISRA 10.4 * More MISRA * libpandasafety_py * cffi * even more tests... * typo * ... * ... * ... * Slight cleanup * MISRA 6.1 * MISRA 17.7 * Bug in bxcan + even style * MISRA 10.1 * Revert "MISRA 10.1" This reverts commit 404ae7fcc39556f80f528de9015702e69f4ea0a5. * ... * MISRA 10.1 and 10.4 suppress until next PR * MISRA 20.1 * ... * test_honda * ... * ... * test_toyota * test_volkswagen_mqb * test_volkswagen_pq * Sketchy thing... * Revert "Sketchy thing..." This reverts commit 3b2e5715bdc1954f7b7b3b7469ba3d0eaa06bdf9. * remove comment * bxcan extended address bug * Concept, experimental dynamic usb packet size * increase each buffer to 10240 bytes * raise python bulk read/write limits * ... * Move packet size to start * Experimental send, stream-like * New receive test, stream-like * cleanup * cleanup + rebase fixes * MISRA * Extra receive method, stream-like, commented out * type change * Revert back to buffer for send, stream commented * forgot ZLP * lower buffer, add rx failsafe * ... remove ZLP * return ZLP back * Add tx checks to panda fw * TX stream with counter * fix counter overflow * 13 free slots should be enough * limit tx usb packet * ... * Revert max_bulk_msg doubling * python lib improve speed * Stream with counter for RX, dirty, needs cleanup * Increase chunk length to 4096 bytes * cleanup fdcan.h * cleanup __init__.py * MISRA 12.1 * MISRA 10.8 * remove non-streaming usb functions * more main.c cleanup * MISRA 15.6 * MISRA 15.5 * MISRA 18.4 and suppress objectIndex * handling usb pakcets > 63bytes, naming and cleanup * Cleanup old from tests and update CANPacket_t struct * Switch to 4 bit DLC instead of 6 bit length * ops) * ... * pylint * receive python buffer increase * USB increase receive packet len * tweak buffers * No need for so high limits * MISRA 20.1 workaround * performance tweaks * cleanup, dlc to data_len_code naming * main.c naming * comments and cleanup for main.c usb * clean py lib * pylint * do not discard good rx messages on stream fail * cleanups * naming * remove bitstruct lib and lower tx limit * bitstruct lefovers * fix bug in VW test * remove adjusting data size and assert on wrong len * ... * test new memcpy before merging * Revert "test new memcpy before merging" This reverts commit 399465a264835061adabdd785718c4b6fc18c267. * macros for to/fromuint8_t array * MISRA hates me! * tests.c include macros instead * move CANPacket to can_definitions.h * vw_pq python test fix * new memcpy test, REMOVE * check without alignment * revert macros for uint8 arrays * Revert "revert macros for uint8 arrays" This reverts commit 581a9db735a42d0d68200bd270d87a8fd34e43fe. * check assert * Revert "check assert" This reverts commit 9e970d029a50597a1718b2bb0260196c050fd77f. * one more variation * Revert "one more variation" This reverts commit f6c0528b7ac7e125750dc0d9445c7ce97f6954b5. * what about read performance * Revert "what about read performance" This reverts commit d2610f90958a816fe7f1822157a84f85e97d9249. * check struct alignment to word * check for aligned memcpy again * cleanup * add CANPacket structure diagram * update CANPacket and add USB packet struct * bugfix + refactoring of EP1 * move dlc_to_len to header * missed include * typo... * MISRA * fk * lower MAX_CAN_MSGS_PER_BULK_TRANSFER * bump CAN_PACKET_VERSION to 2 * bump python lib CAN_PACKET_VERSION to 2 * rename parse_can_buffer to unpack_can_buffer * CANPacket_t const fields * Revert "CANPacket_t const fields" This reverts commit cf91c035b7706a14e317550c5f0501ae3fce7c70. * test.c relative path * cleanup * move macros to safety_declarations * Refactor pack/unpack funcs and add unittest * usb_protocol.h * oops * Update .github/workflows/test.yaml Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> * remove print from unittest Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2021-11-12 16:36:34 -08:00
extended = 1 if address >= 0x800 else 0
data_len_code = LEN_TO_DLC[len(dat)]
header = bytearray(CANPACKET_HEAD_SIZE)
word_4b = (address << 3) | (extended << 2)
header[0] = (data_len_code << 4) | (bus << 1) | int(fd)
CAN_FIFOMailBox to CANPacket struct + USB dynamic packet size (#739) * Squashed commits, no cleanup * Few fixes * No init = garbage * Only receive with new canpacket * Add send with canpacket * Revert "Add send with canpacket" This reverts commit 7d06686ddd6d447c714b5289d31af24403d36931. * Packet must be aligned to word, or bad performance * Cleaner * Fix tests * Tests... * MISRA 10.4 * More MISRA * libpandasafety_py * cffi * even more tests... * typo * ... * ... * ... * Slight cleanup * MISRA 6.1 * MISRA 17.7 * Bug in bxcan + even style * MISRA 10.1 * Revert "MISRA 10.1" This reverts commit 404ae7fcc39556f80f528de9015702e69f4ea0a5. * ... * MISRA 10.1 and 10.4 suppress until next PR * MISRA 20.1 * ... * test_honda * ... * ... * test_toyota * test_volkswagen_mqb * test_volkswagen_pq * Sketchy thing... * Revert "Sketchy thing..." This reverts commit 3b2e5715bdc1954f7b7b3b7469ba3d0eaa06bdf9. * remove comment * bxcan extended address bug * Concept, experimental dynamic usb packet size * increase each buffer to 10240 bytes * raise python bulk read/write limits * ... * Move packet size to start * Experimental send, stream-like * New receive test, stream-like * cleanup * cleanup + rebase fixes * MISRA * Extra receive method, stream-like, commented out * type change * Revert back to buffer for send, stream commented * forgot ZLP * lower buffer, add rx failsafe * ... remove ZLP * return ZLP back * Add tx checks to panda fw * TX stream with counter * fix counter overflow * 13 free slots should be enough * limit tx usb packet * ... * Revert max_bulk_msg doubling * python lib improve speed * Stream with counter for RX, dirty, needs cleanup * Increase chunk length to 4096 bytes * cleanup fdcan.h * cleanup __init__.py * MISRA 12.1 * MISRA 10.8 * remove non-streaming usb functions * more main.c cleanup * MISRA 15.6 * MISRA 15.5 * MISRA 18.4 and suppress objectIndex * handling usb pakcets > 63bytes, naming and cleanup * Cleanup old from tests and update CANPacket_t struct * Switch to 4 bit DLC instead of 6 bit length * ops) * ... * pylint * receive python buffer increase * USB increase receive packet len * tweak buffers * No need for so high limits * MISRA 20.1 workaround * performance tweaks * cleanup, dlc to data_len_code naming * main.c naming * comments and cleanup for main.c usb * clean py lib * pylint * do not discard good rx messages on stream fail * cleanups * naming * remove bitstruct lib and lower tx limit * bitstruct lefovers * fix bug in VW test * remove adjusting data size and assert on wrong len * ... * test new memcpy before merging * Revert "test new memcpy before merging" This reverts commit 399465a264835061adabdd785718c4b6fc18c267. * macros for to/fromuint8_t array * MISRA hates me! * tests.c include macros instead * move CANPacket to can_definitions.h * vw_pq python test fix * new memcpy test, REMOVE * check without alignment * revert macros for uint8 arrays * Revert "revert macros for uint8 arrays" This reverts commit 581a9db735a42d0d68200bd270d87a8fd34e43fe. * check assert * Revert "check assert" This reverts commit 9e970d029a50597a1718b2bb0260196c050fd77f. * one more variation * Revert "one more variation" This reverts commit f6c0528b7ac7e125750dc0d9445c7ce97f6954b5. * what about read performance * Revert "what about read performance" This reverts commit d2610f90958a816fe7f1822157a84f85e97d9249. * check struct alignment to word * check for aligned memcpy again * cleanup * add CANPacket structure diagram * update CANPacket and add USB packet struct * bugfix + refactoring of EP1 * move dlc_to_len to header * missed include * typo... * MISRA * fk * lower MAX_CAN_MSGS_PER_BULK_TRANSFER * bump CAN_PACKET_VERSION to 2 * bump python lib CAN_PACKET_VERSION to 2 * rename parse_can_buffer to unpack_can_buffer * CANPacket_t const fields * Revert "CANPacket_t const fields" This reverts commit cf91c035b7706a14e317550c5f0501ae3fce7c70. * test.c relative path * cleanup * move macros to safety_declarations * Refactor pack/unpack funcs and add unittest * usb_protocol.h * oops * Update .github/workflows/test.yaml Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> * remove print from unittest Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2021-11-12 16:36:34 -08:00
header[1] = word_4b & 0xFF
header[2] = (word_4b >> 8) & 0xFF
header[3] = (word_4b >> 16) & 0xFF
header[4] = (word_4b >> 24) & 0xFF
header[5] = calculate_checksum(header[:5] + dat)
snds[-1].extend(header)
snds[-1].extend(dat)
if chunk and len(snds[-1]) > 256:
snds.append(bytearray())
CAN_FIFOMailBox to CANPacket struct + USB dynamic packet size (#739) * Squashed commits, no cleanup * Few fixes * No init = garbage * Only receive with new canpacket * Add send with canpacket * Revert "Add send with canpacket" This reverts commit 7d06686ddd6d447c714b5289d31af24403d36931. * Packet must be aligned to word, or bad performance * Cleaner * Fix tests * Tests... * MISRA 10.4 * More MISRA * libpandasafety_py * cffi * even more tests... * typo * ... * ... * ... * Slight cleanup * MISRA 6.1 * MISRA 17.7 * Bug in bxcan + even style * MISRA 10.1 * Revert "MISRA 10.1" This reverts commit 404ae7fcc39556f80f528de9015702e69f4ea0a5. * ... * MISRA 10.1 and 10.4 suppress until next PR * MISRA 20.1 * ... * test_honda * ... * ... * test_toyota * test_volkswagen_mqb * test_volkswagen_pq * Sketchy thing... * Revert "Sketchy thing..." This reverts commit 3b2e5715bdc1954f7b7b3b7469ba3d0eaa06bdf9. * remove comment * bxcan extended address bug * Concept, experimental dynamic usb packet size * increase each buffer to 10240 bytes * raise python bulk read/write limits * ... * Move packet size to start * Experimental send, stream-like * New receive test, stream-like * cleanup * cleanup + rebase fixes * MISRA * Extra receive method, stream-like, commented out * type change * Revert back to buffer for send, stream commented * forgot ZLP * lower buffer, add rx failsafe * ... remove ZLP * return ZLP back * Add tx checks to panda fw * TX stream with counter * fix counter overflow * 13 free slots should be enough * limit tx usb packet * ... * Revert max_bulk_msg doubling * python lib improve speed * Stream with counter for RX, dirty, needs cleanup * Increase chunk length to 4096 bytes * cleanup fdcan.h * cleanup __init__.py * MISRA 12.1 * MISRA 10.8 * remove non-streaming usb functions * more main.c cleanup * MISRA 15.6 * MISRA 15.5 * MISRA 18.4 and suppress objectIndex * handling usb pakcets > 63bytes, naming and cleanup * Cleanup old from tests and update CANPacket_t struct * Switch to 4 bit DLC instead of 6 bit length * ops) * ... * pylint * receive python buffer increase * USB increase receive packet len * tweak buffers * No need for so high limits * MISRA 20.1 workaround * performance tweaks * cleanup, dlc to data_len_code naming * main.c naming * comments and cleanup for main.c usb * clean py lib * pylint * do not discard good rx messages on stream fail * cleanups * naming * remove bitstruct lib and lower tx limit * bitstruct lefovers * fix bug in VW test * remove adjusting data size and assert on wrong len * ... * test new memcpy before merging * Revert "test new memcpy before merging" This reverts commit 399465a264835061adabdd785718c4b6fc18c267. * macros for to/fromuint8_t array * MISRA hates me! * tests.c include macros instead * move CANPacket to can_definitions.h * vw_pq python test fix * new memcpy test, REMOVE * check without alignment * revert macros for uint8 arrays * Revert "revert macros for uint8 arrays" This reverts commit 581a9db735a42d0d68200bd270d87a8fd34e43fe. * check assert * Revert "check assert" This reverts commit 9e970d029a50597a1718b2bb0260196c050fd77f. * one more variation * Revert "one more variation" This reverts commit f6c0528b7ac7e125750dc0d9445c7ce97f6954b5. * what about read performance * Revert "what about read performance" This reverts commit d2610f90958a816fe7f1822157a84f85e97d9249. * check struct alignment to word * check for aligned memcpy again * cleanup * add CANPacket structure diagram * update CANPacket and add USB packet struct * bugfix + refactoring of EP1 * move dlc_to_len to header * missed include * typo... * MISRA * fk * lower MAX_CAN_MSGS_PER_BULK_TRANSFER * bump CAN_PACKET_VERSION to 2 * bump python lib CAN_PACKET_VERSION to 2 * rename parse_can_buffer to unpack_can_buffer * CANPacket_t const fields * Revert "CANPacket_t const fields" This reverts commit cf91c035b7706a14e317550c5f0501ae3fce7c70. * test.c relative path * cleanup * move macros to safety_declarations * Refactor pack/unpack funcs and add unittest * usb_protocol.h * oops * Update .github/workflows/test.yaml Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> * remove print from unittest Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2021-11-12 16:36:34 -08:00
return snds
def unpack_can_buffer(dat):
ret = []
while len(dat) >= CANPACKET_HEAD_SIZE:
data_len = DLC_TO_LEN[(dat[0]>>4)]
header = dat[:CANPACKET_HEAD_SIZE]
bus = (header[0] >> 1) & 0x7
address = (header[4] << 24 | header[3] << 16 | header[2] << 8 | header[1]) >> 3
if (header[1] >> 1) & 0x1:
# returned
bus += 128
if header[1] & 0x1:
# rejected
bus += 192
# we need more from the next transfer
if data_len > len(dat) - CANPACKET_HEAD_SIZE:
break
assert calculate_checksum(dat[:(CANPACKET_HEAD_SIZE+data_len)]) == 0, "CAN packet checksum incorrect"
data = dat[CANPACKET_HEAD_SIZE:(CANPACKET_HEAD_SIZE+data_len)]
dat = dat[(CANPACKET_HEAD_SIZE+data_len):]
ret.append((address, data, bus))
return (ret, dat)
def ensure_version(desc, lib_field, panda_field, fn):
@wraps(fn)
def wrapper(self, *args, **kwargs):
lib_version = getattr(self, lib_field)
panda_version = getattr(self, panda_field)
if lib_version != panda_version:
raise RuntimeError(f"{desc} packet version mismatch: panda's firmware v{panda_version}, library v{lib_version}. Reflash panda.")
return fn(self, *args, **kwargs)
return wrapper
ensure_can_packet_version = partial(ensure_version, "CAN", "CAN_PACKET_VERSION", "can_version")
ensure_can_health_packet_version = partial(ensure_version, "CAN health", "CAN_HEALTH_PACKET_VERSION", "can_health_version")
ensure_health_packet_version = partial(ensure_version, "health", "HEALTH_PACKET_VERSION", "health_version")
2022-05-12 14:22:58 +02:00
class Panda:
2017-07-18 12:15:19 -07:00
SERIAL_DEBUG = 0
SERIAL_SOM_DEBUG = 4
2017-07-18 12:15:19 -07:00
USB_VIDS = (0xbbaa, 0x3801) # 0x3801 is comma's registered VID
USB_PIDS = (0xddee, 0xddcc)
2017-07-17 18:59:16 -07:00
REQUEST_IN = usb1.ENDPOINT_IN | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE
REQUEST_OUT = usb1.ENDPOINT_OUT | usb1.TYPE_VENDOR | usb1.RECIPIENT_DEVICE
# from https://github.com/commaai/openpilot/blob/103b4df18cbc38f4129555ab8b15824d1a672bdf/cereal/log.capnp#L648
HW_TYPE_UNKNOWN = b'\x00'
HW_TYPE_WHITE = b'\x01'
HW_TYPE_BLACK = b'\x03'
HW_TYPE_RED_PANDA = b'\x07'
HW_TYPE_TRES = b'\x09'
2024-01-24 13:07:47 -08:00
HW_TYPE_CUATRO = b'\x0a'
HW_TYPE_BODY = b'\xb1'
CAN_PACKET_VERSION = 4
HEALTH_PACKET_VERSION = 17
CAN_HEALTH_PACKET_VERSION = 5
HEALTH_STRUCT = struct.Struct("<IIIIIIIIBBBBBHBBBHfBBHHHB")
CAN_HEALTH_STRUCT = struct.Struct("<BIBBBBBBBBIIIIIIIHHBBBIIII")
F4_DEVICES = [HW_TYPE_WHITE, HW_TYPE_BLACK]
H7_DEVICES = [HW_TYPE_RED_PANDA, HW_TYPE_TRES, HW_TYPE_CUATRO, HW_TYPE_BODY]
SUPPORTED_DEVICES = H7_DEVICES
INTERNAL_DEVICES = (HW_TYPE_TRES, HW_TYPE_CUATRO)
MAX_FAN_RPMs = {
HW_TYPE_TRES: 6600,
HW_TYPE_CUATRO: 5000,
}
HARNESS_STATUS_NC = 0
HARNESS_STATUS_NORMAL = 1
HARNESS_STATUS_FLIPPED = 2
def __init__(self, serial: str | None = None, claim: bool = True, disable_checks: bool = True, can_speed_kbps: int = 500, cli: bool = True):
self._disable_checks = disable_checks
self._handle: BaseHandle
self._handle_open = False
self.can_rx_overflow_buffer = b''
self._can_speed_kbps = can_speed_kbps
if cli and serial is None:
self._connect_serial = self._cli_select_panda()
else:
self._connect_serial = serial
# connect and set mcu type
2017-07-24 15:16:22 -07:00
self.connect(claim)
def _cli_select_panda(self):
dfu_pandas = PandaDFU.list()
if len(dfu_pandas) > 0:
print("INFO: some attached pandas are in DFU mode.")
pandas = self.list()
if len(pandas) == 0:
print("INFO: panda not available")
return None
if len(pandas) == 1:
print(f"INFO: connecting to panda {pandas[0]}")
return pandas[0]
while True:
print("Multiple pandas available:")
pandas.sort()
for idx, serial in enumerate(pandas):
print(f"{[idx]}: {serial}")
try:
choice = int(input("Choose serial [0]:") or "0")
return pandas[choice]
except (ValueError, IndexError):
print("Enter a valid index.")
def __enter__(self):
return self
def __exit__(self, *args):
self.close()
2017-07-24 15:16:22 -07:00
def close(self):
if self._handle_open:
self._handle.close()
self._handle_open = False
if self._context is not None:
self._context.close()
2017-07-24 15:16:22 -07:00
2017-07-29 17:21:22 -07:00
def connect(self, claim=True, wait=False):
self.close()
2017-04-06 18:11:36 -07:00
self._handle = None
while self._handle is None:
# try USB first, then SPI
self._context, self._handle, serial, self.bootstub = self.usb_connect(self._connect_serial, claim=claim, no_error=wait)
if self._handle is None:
self._context, self._handle, serial, self.bootstub = self.spi_connect(self._connect_serial)
if not wait:
break
if self._handle is None:
raise Exception("failed to connect to panda")
self._serial = serial
self._connect_serial = serial
self._handle_open = True
self._mcu_type = self.get_mcu_type()
self.health_version, self.can_version, self.can_health_version = self.get_packets_versions()
logger.debug("connected")
hw_type = self.get_type()
if hw_type not in self.SUPPORTED_DEVICES:
print("WARNING: Using deprecated HW")
# disable openpilot's heartbeat checks
if self._disable_checks:
self.set_heartbeat_disabled()
self.set_power_save(0)
# reset comms
self.can_reset_communications()
# disable automatic CAN-FD switching
for bus in range(PANDA_CAN_CNT):
self.set_canfd_auto(bus, False)
# set CAN speed
for bus in range(PANDA_CAN_CNT):
self.set_can_speed_kbps(bus, self._can_speed_kbps)
@property
def spi(self) -> bool:
return isinstance(self._handle, PandaSpiHandle)
@classmethod
def spi_connect(cls, serial, ignore_version=False):
try:
handle = PandaSpiHandle()
dat = handle.get_protocol_version()
except PandaSpiException:
return None, None, None, False
spi_serial = binascii.hexlify(dat[:12]).decode()
pid = dat[13]
if pid not in (0xcc, 0xee):
raise PandaProtocolMismatch(f"invalid bootstub status ({pid=}). reflash panda")
bootstub = pid == 0xee
spi_version = dat[14]
# did we get the right panda?
if serial is not None and spi_serial != serial:
return None, None, None, False
# ensure our protocol version matches the panda
if (not ignore_version) and spi_version != handle.PROTOCOL_VERSION:
raise PandaProtocolMismatch(f"panda protocol mismatch: expected {handle.PROTOCOL_VERSION}, got {spi_version}. reflash panda")
# got a device and all good
return None, handle, spi_serial, bootstub
@classmethod
def usb_connect(cls, serial, claim=True, no_error=False):
handle, usb_serial, bootstub = None, None, None
context = usb1.USBContext()
context.open()
try:
for device in context.getDeviceList(skip_on_error=True):
if device.getVendorID() in cls.USB_VIDS and device.getProductID() in cls.USB_PIDS:
try:
this_serial = device.getSerialNumber()
except Exception:
# Allow to ignore errors on reconnect. USB hubs need some time to initialize after panda reset
if not no_error:
logger.exception("failed to get serial number of panda")
continue
if serial is None or this_serial == serial:
logger.debug("opening device %s %s", this_serial, hex(device.getProductID()))
usb_serial = this_serial
bootstub = (device.getProductID() & 0xF0) == 0xe0
handle = device.open()
if sys.platform not in ("win32", "cygwin", "msys", "darwin"):
handle.setAutoDetachKernelDriver(True)
if claim:
handle.claimInterface(0)
# handle.setInterfaceAltSetting(0, 0) # Issue in USB stack
break
except Exception:
logger.exception("USB connect error")
usb_handle = None
if handle is not None:
usb_handle = PandaUsbHandle(handle)
else:
context.close()
return context, usb_handle, usb_serial, bootstub
def is_connected_spi(self):
return isinstance(self._handle, PandaSpiHandle)
def is_connected_usb(self):
return isinstance(self._handle, PandaUsbHandle)
@classmethod
def list(cls, usb_only: bool = False):
ret = cls.usb_list()
if not usb_only:
ret += cls.spi_list()
return list(set(ret))
@classmethod
def usb_list(cls):
ret = []
try:
with usb1.USBContext() as context:
for device in context.getDeviceList(skip_on_error=True):
if device.getVendorID() in cls.USB_VIDS and device.getProductID() in cls.USB_PIDS:
try:
serial = device.getSerialNumber()
if len(serial) == 24:
ret.append(serial)
else:
logger.warning(f"found device with panda descriptors but invalid serial: {serial}", RuntimeWarning)
except Exception:
logger.exception("error connecting to panda")
except Exception:
logger.exception("exception while listing pandas")
return ret
@classmethod
def spi_list(cls):
_, _, serial, _ = cls.spi_connect(None, ignore_version=True)
if serial is not None:
return [serial, ]
return []
def reset(self, enter_bootstub=False, enter_bootloader=False, reconnect=True):
# no response is expected since it resets right away
timeout = 5000 if isinstance(self._handle, PandaSpiHandle) else 15000
2017-07-24 15:16:22 -07:00
try:
2017-07-27 14:29:07 -07:00
if enter_bootloader:
self._handle.controlWrite(Panda.REQUEST_IN, 0xd1, 0, 0, b'', timeout=timeout, expect_disconnect=True)
2017-07-24 15:16:22 -07:00
else:
2017-07-27 14:29:07 -07:00
if enter_bootstub:
self._handle.controlWrite(Panda.REQUEST_IN, 0xd1, 1, 0, b'', timeout=timeout, expect_disconnect=True)
2017-07-27 14:29:07 -07:00
else:
self._handle.controlWrite(Panda.REQUEST_IN, 0xd8, 0, 0, b'', timeout=timeout, expect_disconnect=True)
2017-07-24 15:16:22 -07:00
except Exception:
pass
self.close()
if not enter_bootloader and reconnect:
2018-03-10 11:22:22 -08:00
self.reconnect()
@property
def connected(self) -> bool:
return self._handle_open
2018-03-10 11:22:22 -08:00
def reconnect(self):
if self._handle_open:
self.close()
2018-03-10 11:22:22 -08:00
success = False
# wait up to 15 seconds
for _ in range(15*10):
2018-03-10 11:22:22 -08:00
try:
self.connect(claim=False, wait=True)
2018-03-10 11:22:22 -08:00
success = True
break
except Exception:
pass
2023-08-04 23:52:18 -07:00
time.sleep(0.1)
2018-03-10 11:22:22 -08:00
if not success:
raise Exception("reconnect failed")
@staticmethod
def flasher_present(handle: BaseHandle) -> bool:
fr = handle.controlRead(Panda.REQUEST_IN, 0xb0, 0, 0, 0xc)
return fr[4:8] == b"\xde\xad\xd0\x0d"
2018-03-10 11:22:22 -08:00
@staticmethod
def flash_static(handle, code, mcu_type):
assert mcu_type is not None, "must set valid mcu_type to flash"
2018-03-10 11:22:22 -08:00
# confirm flasher is present
assert Panda.flasher_present(handle)
2018-03-10 11:22:22 -08:00
# determine sectors to erase
apps_sectors_cumsum = accumulate(mcu_type.config.sector_sizes[1:])
last_sector = next((i + 1 for i, v in enumerate(apps_sectors_cumsum) if v > len(code)), -1)
assert last_sector >= 1, "Binary too small? No sector to erase."
assert last_sector < 7, "Binary too large! Risk of overwriting provisioning chunk."
2018-03-10 11:22:22 -08:00
# unlock flash
2024-10-02 17:05:15 -07:00
logger.info("flash: unlocking")
2018-03-10 11:22:22 -08:00
handle.controlWrite(Panda.REQUEST_IN, 0xb1, 0, 0, b'')
# erase sectors
2024-10-02 17:05:15 -07:00
logger.info(f"flash: erasing sectors 1 - {last_sector}")
for i in range(1, last_sector + 1):
Black (#254) * late usb * Added type support for black panda * Added harness presence and orientation detection * harness relay driving code * Added intercept support in black panda code. Switched around can0 and can2 * Disable ADCs after orientation detection. Ignition interrupts via harness * WIP: Hardware abstraction layer + black panda bringup * Fixed bootstub build * Fixed bootstub for pedal * Fixed infinite loops * Got CAN buses working on white again * Fixed pedal build and black can interfaces * Got CAN buses working on black panda * Finished loopback test for black panda * Erase all flash sectors on the panda. Increased binary limit. Added extra python functions. * Fixed python * Made new code MISRA compliant * Cleaned up ignition. Fixed build * Fixed health packet * Fixed CAN mode on black bug. Changed OBD to switch on ELM mode * Fixes from Github review * Fixed MISRA issue for pedal * Fixed failing gmlan tests * ELM327 safety: allow diagnostic on all buses * Cleaned up EON relay code * delete only 3 sectors instead of 11 to allow a new build to be flashed. Much faster to flash * Removed CAN only can0 output mode. Does not make sense on black panda due to reversibility issues. * Added heartbeat logic for EON code on panda. Go to NOOUTPUT if EON does not send a heartbeat for 5 seconds. * Remove all CAN buses live on EON startup. Shouldn't be necessary to have this separate case * Formatting * Added file I forgot to push * Added heartbeat to testing code to make sure EON tests don't fail. Should probably find a better way to do this though. Heartbeat thread didn't work, concurrent USB connection issues... * Safety: support black panda for Honda Bosch * Disable OBD2 if setting to NOOUTPUT mode * Run safety tests for all hw_types * Fail test if subtest fails * fix safety tests
2019-07-23 15:07:06 -07:00
handle.controlWrite(Panda.REQUEST_IN, 0xb2, i, 0, b'')
2018-03-10 11:22:22 -08:00
# flash over EP2
STEP = 0x200
2024-10-02 17:05:15 -07:00
logger.info("flash: flashing")
for i in range(0, len(code), STEP):
handle.bulkWrite(2, code[i:i + STEP])
2018-03-10 11:22:22 -08:00
# reset
2024-10-02 17:05:15 -07:00
logger.info("flash: resetting")
2018-03-10 11:22:22 -08:00
try:
handle.controlWrite(Panda.REQUEST_IN, 0xd8, 0, 0, b'', expect_disconnect=True)
2018-03-10 11:22:22 -08:00
except Exception:
pass
def flash(self, fn=None, code=None, reconnect=True):
if self.up_to_date(fn=fn):
2024-10-02 17:05:15 -07:00
logger.info("flash: already up to date")
return
hw_type = self.get_type()
if hw_type not in self.SUPPORTED_DEVICES:
raise RuntimeError(f"HW type {hw_type.hex()} is deprecated and can no longer be flashed.")
if not fn:
fn = os.path.join(FW_PATH, self._mcu_type.config.app_fn)
assert os.path.isfile(fn)
logger.debug("flash: main version is %s", self.get_version())
2017-07-24 15:16:22 -07:00
if not self.bootstub:
2017-07-27 14:29:07 -07:00
self.reset(enter_bootstub=True)
2017-07-24 15:16:22 -07:00
assert(self.bootstub)
2017-08-22 13:36:20 -07:00
if code is None:
2019-09-25 16:52:03 -07:00
with open(fn, "rb") as f:
2017-08-22 13:36:20 -07:00
code = f.read()
2017-07-24 15:16:22 -07:00
# get version
logger.debug("flash: bootstub version is %s", self.get_version())
2018-03-10 11:22:22 -08:00
# do flash
Panda.flash_static(self._handle, code, mcu_type=self._mcu_type)
2017-07-24 15:16:22 -07:00
2018-03-10 11:22:22 -08:00
# reconnect
if reconnect:
self.reconnect()
2017-04-06 18:11:36 -07:00
2024-02-24 21:56:28 +00:00
def recover(self, timeout: int | None = 60, reset: bool = True) -> bool:
dfu_serial = self.get_dfu_serial()
if reset:
self.reset(enter_bootstub=True)
self.reset(enter_bootloader=True)
if not self.wait_for_dfu(dfu_serial, timeout=timeout):
return False
2017-08-28 10:42:23 -07:00
dfu = PandaDFU(dfu_serial)
2017-08-28 10:42:23 -07:00
dfu.recover()
# reflash after recover
self.connect(True, True)
self.flash()
return True
2017-08-28 10:42:23 -07:00
@staticmethod
2024-02-24 21:56:28 +00:00
def wait_for_dfu(dfu_serial: str | None, timeout: int | None = None) -> bool:
t_start = time.monotonic()
2023-05-23 20:50:09 -07:00
dfu_list = PandaDFU.list()
while (dfu_serial is None and len(dfu_list) == 0) or (dfu_serial is not None and dfu_serial not in dfu_list):
logger.debug("waiting for DFU...")
time.sleep(0.1)
if timeout is not None and (time.monotonic() - t_start) > timeout:
return False
2023-05-23 20:50:09 -07:00
dfu_list = PandaDFU.list()
return True
@classmethod
def wait_for_panda(cls, serial: str | None, timeout: int) -> bool:
t_start = time.monotonic()
serials = cls.list()
while (serial is None and len(serials) == 0) or (serial is not None and serial not in serials):
logger.debug("waiting for panda...")
time.sleep(0.1)
if timeout is not None and (time.monotonic() - t_start) > timeout:
return False
serials = cls.list()
return True
def up_to_date(self, fn=None) -> bool:
current = self.get_signature()
if fn is None:
fn = os.path.join(FW_PATH, self.get_mcu_type().config.app_fn)
expected = Panda.get_signature_from_firmware(fn)
return (current == expected)
2017-07-18 12:29:16 -07:00
def call_control_api(self, msg):
self._handle.controlWrite(Panda.REQUEST_OUT, msg, 0, 0, b'')
2017-04-06 18:11:36 -07:00
# ******************* health *******************
@ensure_health_packet_version
2017-04-06 18:11:36 -07:00
def health(self):
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xd2, 0, 0, self.HEALTH_STRUCT.size)
a = self.HEALTH_STRUCT.unpack(dat)
Black (#254) * late usb * Added type support for black panda * Added harness presence and orientation detection * harness relay driving code * Added intercept support in black panda code. Switched around can0 and can2 * Disable ADCs after orientation detection. Ignition interrupts via harness * WIP: Hardware abstraction layer + black panda bringup * Fixed bootstub build * Fixed bootstub for pedal * Fixed infinite loops * Got CAN buses working on white again * Fixed pedal build and black can interfaces * Got CAN buses working on black panda * Finished loopback test for black panda * Erase all flash sectors on the panda. Increased binary limit. Added extra python functions. * Fixed python * Made new code MISRA compliant * Cleaned up ignition. Fixed build * Fixed health packet * Fixed CAN mode on black bug. Changed OBD to switch on ELM mode * Fixes from Github review * Fixed MISRA issue for pedal * Fixed failing gmlan tests * ELM327 safety: allow diagnostic on all buses * Cleaned up EON relay code * delete only 3 sectors instead of 11 to allow a new build to be flashed. Much faster to flash * Removed CAN only can0 output mode. Does not make sense on black panda due to reversibility issues. * Added heartbeat logic for EON code on panda. Go to NOOUTPUT if EON does not send a heartbeat for 5 seconds. * Remove all CAN buses live on EON startup. Shouldn't be necessary to have this separate case * Formatting * Added file I forgot to push * Added heartbeat to testing code to make sure EON tests don't fail. Should probably find a better way to do this though. Heartbeat thread didn't work, concurrent USB connection issues... * Safety: support black panda for Honda Bosch * Disable OBD2 if setting to NOOUTPUT mode * Run safety tests for all hw_types * Fail test if subtest fails * fix safety tests
2019-07-23 15:07:06 -07:00
return {
"uptime": a[0],
"voltage": a[1],
"current": a[2],
"safety_tx_blocked": a[3],
"safety_rx_invalid": a[4],
"tx_buffer_overflow": a[5],
"rx_buffer_overflow": a[6],
"faults": a[7],
"ignition_line": a[8],
"ignition_can": a[9],
"controls_allowed": a[10],
"car_harness_status": a[11],
"safety_mode": a[12],
"safety_param": a[13],
"fault_status": a[14],
"power_save_enabled": a[15],
"heartbeat_lost": a[16],
"alternative_experience": a[17],
"interrupt_load": a[18],
"fan_power": a[19],
"safety_rx_checks_invalid": a[20],
2025-07-30 18:27:56 -07:00
"spi_error_count": a[21],
"sbu1_voltage_mV": a[22],
"sbu2_voltage_mV": a[23],
"som_reset_triggered": a[24],
Black (#254) * late usb * Added type support for black panda * Added harness presence and orientation detection * harness relay driving code * Added intercept support in black panda code. Switched around can0 and can2 * Disable ADCs after orientation detection. Ignition interrupts via harness * WIP: Hardware abstraction layer + black panda bringup * Fixed bootstub build * Fixed bootstub for pedal * Fixed infinite loops * Got CAN buses working on white again * Fixed pedal build and black can interfaces * Got CAN buses working on black panda * Finished loopback test for black panda * Erase all flash sectors on the panda. Increased binary limit. Added extra python functions. * Fixed python * Made new code MISRA compliant * Cleaned up ignition. Fixed build * Fixed health packet * Fixed CAN mode on black bug. Changed OBD to switch on ELM mode * Fixes from Github review * Fixed MISRA issue for pedal * Fixed failing gmlan tests * ELM327 safety: allow diagnostic on all buses * Cleaned up EON relay code * delete only 3 sectors instead of 11 to allow a new build to be flashed. Much faster to flash * Removed CAN only can0 output mode. Does not make sense on black panda due to reversibility issues. * Added heartbeat logic for EON code on panda. Go to NOOUTPUT if EON does not send a heartbeat for 5 seconds. * Remove all CAN buses live on EON startup. Shouldn't be necessary to have this separate case * Formatting * Added file I forgot to push * Added heartbeat to testing code to make sure EON tests don't fail. Should probably find a better way to do this though. Heartbeat thread didn't work, concurrent USB connection issues... * Safety: support black panda for Honda Bosch * Disable OBD2 if setting to NOOUTPUT mode * Run safety tests for all hw_types * Fail test if subtest fails * fix safety tests
2019-07-23 15:07:06 -07:00
}
2017-04-06 18:11:36 -07:00
@ensure_can_health_packet_version
def can_health(self, can_number):
LEC_ERROR_CODE = {
0: "No error",
1: "Stuff error",
2: "Form error",
3: "AckError",
4: "Bit1Error",
5: "Bit0Error",
6: "CRCError",
7: "NoChange",
}
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xc2, int(can_number), 0, self.CAN_HEALTH_STRUCT.size)
a = self.CAN_HEALTH_STRUCT.unpack(dat)
return {
"bus_off": a[0],
"bus_off_cnt": a[1],
"error_warning": a[2],
"error_passive": a[3],
"last_error": LEC_ERROR_CODE[a[4]],
"last_stored_error": LEC_ERROR_CODE[a[5]],
"last_data_error": LEC_ERROR_CODE[a[6]],
"last_data_stored_error": LEC_ERROR_CODE[a[7]],
"receive_error_cnt": a[8],
"transmit_error_cnt": a[9],
"total_error_cnt": a[10],
"total_tx_lost_cnt": a[11],
"total_rx_lost_cnt": a[12],
"total_tx_cnt": a[13],
"total_rx_cnt": a[14],
"total_fwd_cnt": a[15],
"total_tx_checksum_error_cnt": a[16],
"can_speed": a[17],
"can_data_speed": a[18],
"canfd_enabled": a[19],
"brs_enabled": a[20],
"canfd_non_iso": a[21],
"irq0_call_rate": a[22],
"irq1_call_rate": a[23],
"irq2_call_rate": a[24],
"can_core_reset_count": a[25],
}
2017-04-28 16:56:40 -07:00
# ******************* control *******************
def get_version(self):
2019-09-25 16:52:51 -07:00
return self._handle.controlRead(Panda.REQUEST_IN, 0xd6, 0, 0, 0x40).decode('utf8')
@staticmethod
2022-05-12 14:22:58 +02:00
def get_signature_from_firmware(fn) -> bytes:
with open(fn, 'rb') as f:
f.seek(-128, 2) # Seek from end of file
return f.read(128)
def get_signature(self) -> bytes:
part_1 = self._handle.controlRead(Panda.REQUEST_IN, 0xd3, 0, 0, 0x40)
part_2 = self._handle.controlRead(Panda.REQUEST_IN, 0xd4, 0, 0, 0x40)
return bytes(part_1 + part_2)
Black (#254) * late usb * Added type support for black panda * Added harness presence and orientation detection * harness relay driving code * Added intercept support in black panda code. Switched around can0 and can2 * Disable ADCs after orientation detection. Ignition interrupts via harness * WIP: Hardware abstraction layer + black panda bringup * Fixed bootstub build * Fixed bootstub for pedal * Fixed infinite loops * Got CAN buses working on white again * Fixed pedal build and black can interfaces * Got CAN buses working on black panda * Finished loopback test for black panda * Erase all flash sectors on the panda. Increased binary limit. Added extra python functions. * Fixed python * Made new code MISRA compliant * Cleaned up ignition. Fixed build * Fixed health packet * Fixed CAN mode on black bug. Changed OBD to switch on ELM mode * Fixes from Github review * Fixed MISRA issue for pedal * Fixed failing gmlan tests * ELM327 safety: allow diagnostic on all buses * Cleaned up EON relay code * delete only 3 sectors instead of 11 to allow a new build to be flashed. Much faster to flash * Removed CAN only can0 output mode. Does not make sense on black panda due to reversibility issues. * Added heartbeat logic for EON code on panda. Go to NOOUTPUT if EON does not send a heartbeat for 5 seconds. * Remove all CAN buses live on EON startup. Shouldn't be necessary to have this separate case * Formatting * Added file I forgot to push * Added heartbeat to testing code to make sure EON tests don't fail. Should probably find a better way to do this though. Heartbeat thread didn't work, concurrent USB connection issues... * Safety: support black panda for Honda Bosch * Disable OBD2 if setting to NOOUTPUT mode * Run safety tests for all hw_types * Fail test if subtest fails * fix safety tests
2019-07-23 15:07:06 -07:00
def get_type(self):
return self._handle.controlRead(Panda.REQUEST_IN, 0xc1, 0, 0, 0x40)
Black (#254) * late usb * Added type support for black panda * Added harness presence and orientation detection * harness relay driving code * Added intercept support in black panda code. Switched around can0 and can2 * Disable ADCs after orientation detection. Ignition interrupts via harness * WIP: Hardware abstraction layer + black panda bringup * Fixed bootstub build * Fixed bootstub for pedal * Fixed infinite loops * Got CAN buses working on white again * Fixed pedal build and black can interfaces * Got CAN buses working on black panda * Finished loopback test for black panda * Erase all flash sectors on the panda. Increased binary limit. Added extra python functions. * Fixed python * Made new code MISRA compliant * Cleaned up ignition. Fixed build * Fixed health packet * Fixed CAN mode on black bug. Changed OBD to switch on ELM mode * Fixes from Github review * Fixed MISRA issue for pedal * Fixed failing gmlan tests * ELM327 safety: allow diagnostic on all buses * Cleaned up EON relay code * delete only 3 sectors instead of 11 to allow a new build to be flashed. Much faster to flash * Removed CAN only can0 output mode. Does not make sense on black panda due to reversibility issues. * Added heartbeat logic for EON code on panda. Go to NOOUTPUT if EON does not send a heartbeat for 5 seconds. * Remove all CAN buses live on EON startup. Shouldn't be necessary to have this separate case * Formatting * Added file I forgot to push * Added heartbeat to testing code to make sure EON tests don't fail. Should probably find a better way to do this though. Heartbeat thread didn't work, concurrent USB connection issues... * Safety: support black panda for Honda Bosch * Disable OBD2 if setting to NOOUTPUT mode * Run safety tests for all hw_types * Fail test if subtest fails * fix safety tests
2019-07-23 15:07:06 -07:00
# Returns tuple with health packet version and CAN packet/USB packet version
def get_packets_versions(self):
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xdd, 0, 0, 3)
if dat and len(dat) == 3:
a = struct.unpack("BBB", dat)
return (a[0], a[1], a[2])
else:
return (0, 0, 0)
def get_mcu_type(self) -> McuType:
hw_type = self.get_type()
if hw_type in Panda.F4_DEVICES:
return McuType.F4
elif hw_type in Panda.H7_DEVICES:
return McuType.H7
raise ValueError(f"unknown HW type: {hw_type}")
2021-07-08 00:36:25 -07:00
def is_internal(self):
return self.get_type() in Panda.INTERNAL_DEVICES
2017-04-28 16:56:40 -07:00
def get_serial(self):
"""
Returns the comma-issued dongle ID from our provisioning
"""
2017-07-17 18:59:16 -07:00
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xd0, 0, 0, 0x20)
hashsig, calc_hash = dat[0x1c:], hashlib.sha1(dat[0:0x1c]).digest()[0:4]
2017-07-17 19:43:30 -07:00
assert(hashsig == calc_hash)
return [dat[0:0x10].decode("utf8"), dat[0x10:0x10 + 10].decode("utf8")]
2017-04-28 16:56:40 -07:00
2021-10-08 12:17:06 +02:00
def get_usb_serial(self):
"""
Returns the serial number reported from the USB descriptor;
matches the MCU UID
"""
2021-10-08 12:17:06 +02:00
return self._serial
def get_dfu_serial(self):
return PandaDFU.st_serial_to_dfu_serial(self._serial, self._mcu_type)
def get_uid(self):
"""
Returns the UID from the MCU
"""
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xc3, 0, 0, 12)
return binascii.hexlify(dat).decode()
2017-04-28 17:49:55 -07:00
def get_secret(self):
2017-07-17 18:59:16 -07:00
return self._handle.controlRead(Panda.REQUEST_IN, 0xd0, 1, 0, 0x10)
2017-04-28 17:49:55 -07:00
def get_interrupt_call_rate(self, irqnum):
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xc4, int(irqnum), 0, 4)
return struct.unpack("I", dat)[0]
2017-04-25 15:16:23 -07:00
# ******************* configuration *******************
2017-04-06 18:11:36 -07:00
def set_alternative_experience(self, alternative_experience, safety_param_sp=0):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xdf, int(alternative_experience), int(safety_param_sp), b'')
def set_power_save(self, power_save_enabled=0):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe7, int(power_save_enabled), 0, b'')
def set_safety_mode(self, mode=CarParams.SafetyModel.silent, param=0):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xdc, mode, param, b'')
Black (#254) * late usb * Added type support for black panda * Added harness presence and orientation detection * harness relay driving code * Added intercept support in black panda code. Switched around can0 and can2 * Disable ADCs after orientation detection. Ignition interrupts via harness * WIP: Hardware abstraction layer + black panda bringup * Fixed bootstub build * Fixed bootstub for pedal * Fixed infinite loops * Got CAN buses working on white again * Fixed pedal build and black can interfaces * Got CAN buses working on black panda * Finished loopback test for black panda * Erase all flash sectors on the panda. Increased binary limit. Added extra python functions. * Fixed python * Made new code MISRA compliant * Cleaned up ignition. Fixed build * Fixed health packet * Fixed CAN mode on black bug. Changed OBD to switch on ELM mode * Fixes from Github review * Fixed MISRA issue for pedal * Fixed failing gmlan tests * ELM327 safety: allow diagnostic on all buses * Cleaned up EON relay code * delete only 3 sectors instead of 11 to allow a new build to be flashed. Much faster to flash * Removed CAN only can0 output mode. Does not make sense on black panda due to reversibility issues. * Added heartbeat logic for EON code on panda. Go to NOOUTPUT if EON does not send a heartbeat for 5 seconds. * Remove all CAN buses live on EON startup. Shouldn't be necessary to have this separate case * Formatting * Added file I forgot to push * Added heartbeat to testing code to make sure EON tests don't fail. Should probably find a better way to do this though. Heartbeat thread didn't work, concurrent USB connection issues... * Safety: support black panda for Honda Bosch * Disable OBD2 if setting to NOOUTPUT mode * Run safety tests for all hw_types * Fail test if subtest fails * fix safety tests
2019-07-23 15:07:06 -07:00
def set_obd(self, obd):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xdb, int(obd), 0, b'')
def set_can_loopback(self, enable):
2017-07-17 15:29:31 -07:00
# set can loopback mode for all buses
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe5, int(enable), 0, b'')
def set_can_enable(self, bus_num, enable):
2020-09-28 16:19:09 +02:00
# sets the can transceiver enable pin
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf4, int(bus_num), int(enable), b'')
2017-07-17 19:43:30 -07:00
def set_can_speed_kbps(self, bus, speed):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xde, bus, int(speed * 10), b'')
2017-07-17 19:43:30 -07:00
def set_can_data_speed_kbps(self, bus, speed):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf9, bus, int(speed * 10), b'')
def set_canfd_non_iso(self, bus, non_iso):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xfc, bus, int(non_iso), b'')
def set_canfd_auto(self, bus, auto):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe8, bus, int(auto), b'')
2017-04-25 15:16:23 -07:00
def set_uart_baud(self, uart, rate):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe4, uart, int(rate / 300), b'')
2017-04-25 15:16:23 -07:00
def set_uart_parity(self, uart, parity):
# parity, 0=off, 1=even, 2=odd
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe2, uart, parity, b'')
2017-04-25 15:16:23 -07:00
2017-04-25 20:23:05 -07:00
def set_uart_callback(self, uart, install):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe3, uart, int(install), b'')
2017-04-25 20:23:05 -07:00
2017-04-25 15:16:23 -07:00
# ******************* can *******************
# The panda will NAK CAN writes when there is CAN congestion.
# libusb will try to send it again, with a max timeout.
# Timeout is in ms. If set to 0, the timeout is infinite.
CAN_SEND_TIMEOUT_MS = 10
def can_reset_communications(self):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xc0, 0, 0, b'')
@ensure_can_packet_version
def can_send_many(self, arr, *, fd=False, timeout=CAN_SEND_TIMEOUT_MS):
snds = pack_can_buffer(arr, chunk=(not self.spi), fd=fd)
for tx in snds:
while len(tx) > 0:
bs = self._handle.bulkWrite(3, tx, timeout=timeout)
tx = tx[bs:]
2017-04-06 18:11:36 -07:00
def can_send(self, addr, dat, bus, *, fd=False, timeout=CAN_SEND_TIMEOUT_MS):
self.can_send_many([[addr, dat, bus]], fd=fd, timeout=timeout)
2017-04-06 18:11:36 -07:00
@ensure_can_packet_version
2017-04-06 18:11:36 -07:00
def can_recv(self):
dat = bytearray()
while True:
2017-04-06 18:11:36 -07:00
try:
CAN_FIFOMailBox to CANPacket struct + USB dynamic packet size (#739) * Squashed commits, no cleanup * Few fixes * No init = garbage * Only receive with new canpacket * Add send with canpacket * Revert "Add send with canpacket" This reverts commit 7d06686ddd6d447c714b5289d31af24403d36931. * Packet must be aligned to word, or bad performance * Cleaner * Fix tests * Tests... * MISRA 10.4 * More MISRA * libpandasafety_py * cffi * even more tests... * typo * ... * ... * ... * Slight cleanup * MISRA 6.1 * MISRA 17.7 * Bug in bxcan + even style * MISRA 10.1 * Revert "MISRA 10.1" This reverts commit 404ae7fcc39556f80f528de9015702e69f4ea0a5. * ... * MISRA 10.1 and 10.4 suppress until next PR * MISRA 20.1 * ... * test_honda * ... * ... * test_toyota * test_volkswagen_mqb * test_volkswagen_pq * Sketchy thing... * Revert "Sketchy thing..." This reverts commit 3b2e5715bdc1954f7b7b3b7469ba3d0eaa06bdf9. * remove comment * bxcan extended address bug * Concept, experimental dynamic usb packet size * increase each buffer to 10240 bytes * raise python bulk read/write limits * ... * Move packet size to start * Experimental send, stream-like * New receive test, stream-like * cleanup * cleanup + rebase fixes * MISRA * Extra receive method, stream-like, commented out * type change * Revert back to buffer for send, stream commented * forgot ZLP * lower buffer, add rx failsafe * ... remove ZLP * return ZLP back * Add tx checks to panda fw * TX stream with counter * fix counter overflow * 13 free slots should be enough * limit tx usb packet * ... * Revert max_bulk_msg doubling * python lib improve speed * Stream with counter for RX, dirty, needs cleanup * Increase chunk length to 4096 bytes * cleanup fdcan.h * cleanup __init__.py * MISRA 12.1 * MISRA 10.8 * remove non-streaming usb functions * more main.c cleanup * MISRA 15.6 * MISRA 15.5 * MISRA 18.4 and suppress objectIndex * handling usb pakcets > 63bytes, naming and cleanup * Cleanup old from tests and update CANPacket_t struct * Switch to 4 bit DLC instead of 6 bit length * ops) * ... * pylint * receive python buffer increase * USB increase receive packet len * tweak buffers * No need for so high limits * MISRA 20.1 workaround * performance tweaks * cleanup, dlc to data_len_code naming * main.c naming * comments and cleanup for main.c usb * clean py lib * pylint * do not discard good rx messages on stream fail * cleanups * naming * remove bitstruct lib and lower tx limit * bitstruct lefovers * fix bug in VW test * remove adjusting data size and assert on wrong len * ... * test new memcpy before merging * Revert "test new memcpy before merging" This reverts commit 399465a264835061adabdd785718c4b6fc18c267. * macros for to/fromuint8_t array * MISRA hates me! * tests.c include macros instead * move CANPacket to can_definitions.h * vw_pq python test fix * new memcpy test, REMOVE * check without alignment * revert macros for uint8 arrays * Revert "revert macros for uint8 arrays" This reverts commit 581a9db735a42d0d68200bd270d87a8fd34e43fe. * check assert * Revert "check assert" This reverts commit 9e970d029a50597a1718b2bb0260196c050fd77f. * one more variation * Revert "one more variation" This reverts commit f6c0528b7ac7e125750dc0d9445c7ce97f6954b5. * what about read performance * Revert "what about read performance" This reverts commit d2610f90958a816fe7f1822157a84f85e97d9249. * check struct alignment to word * check for aligned memcpy again * cleanup * add CANPacket structure diagram * update CANPacket and add USB packet struct * bugfix + refactoring of EP1 * move dlc_to_len to header * missed include * typo... * MISRA * fk * lower MAX_CAN_MSGS_PER_BULK_TRANSFER * bump CAN_PACKET_VERSION to 2 * bump python lib CAN_PACKET_VERSION to 2 * rename parse_can_buffer to unpack_can_buffer * CANPacket_t const fields * Revert "CANPacket_t const fields" This reverts commit cf91c035b7706a14e317550c5f0501ae3fce7c70. * test.c relative path * cleanup * move macros to safety_declarations * Refactor pack/unpack funcs and add unittest * usb_protocol.h * oops * Update .github/workflows/test.yaml Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com> * remove print from unittest Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2021-11-12 16:36:34 -08:00
dat = self._handle.bulkRead(1, 16384) # Max receive batch size + 2 extra reserve frames
2017-04-06 18:11:36 -07:00
break
except (usb1.USBErrorIO, usb1.USBErrorOverflow):
logger.error("CAN: BAD RECV, RETRYING")
time.sleep(0.1)
msgs, self.can_rx_overflow_buffer = unpack_can_buffer(self.can_rx_overflow_buffer + dat)
return msgs
2017-04-06 18:11:36 -07:00
def can_clear(self, bus):
"""Clears all messages from the specified internal CAN ringbuffer as
though it were drained.
Args:
bus (int): can bus number to clear a tx queue, or 0xFFFF to clear the
global can rx queue.
"""
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf1, bus, 0, b'')
2017-04-06 18:11:36 -07:00
# ******************* serial *******************
2025-10-05 13:57:58 -07:00
def serial_read(self, port_number, maxlen=1024):
ret = b''
2017-07-18 12:15:19 -07:00
while 1:
2025-10-05 13:57:58 -07:00
r = bytes(self._handle.controlRead(Panda.REQUEST_IN, 0xe0, port_number, 0, 0x40))
if len(r) == 0 or len(ret) >= maxlen:
2017-07-18 12:15:19 -07:00
break
2025-10-05 13:57:58 -07:00
ret += r
return ret
2017-04-06 18:11:36 -07:00
def serial_write(self, port_number, ln):
2018-01-19 11:04:21 -08:00
ret = 0
if isinstance(ln, str):
ln = bytes(ln, 'utf-8')
for i in range(0, len(ln), 0x20):
ret += self._handle.bulkWrite(2, struct.pack("B", port_number) + ln[i:i + 0x20])
2018-01-19 11:04:21 -08:00
return ret
2017-04-06 18:11:36 -07:00
Modular Assistive Driving System (MADS) (#57) * improvements on the state machine for exiting controls and improvements on replay drive, and optimizations * New tests on hyundai for now to see how they behave with lkas and main button pressed interchangeably * cleaning up hyundai tests and ensuring we always cleanup mads states at the end of the tests * Adjusting tests * Adjusting the tests a bit more to ensure clean states * Cleaning up and simplifying logic * ensuring all tests always cleanup * improving the state * make static happy * Refactor safety replay script for better debugging and update Honda safety code The commit performs a comprehensive revision of the safety replay script, specifically focusing on introducing debug variables and enhancing the logging capabilities for improved debugging. Furthermore, changes were made to the Honda safety code. The test helpers within libpanda were also expanded for inclusion of additional test conditions. * Introduce 'ACC_MAIN_OFF' as a new disengagement reason in Sunnypilot's 'safety_mads.h' The Sunnypilot's 'safety_mads.h' file has been updated to include 'ACC_MAIN_OFF' as a new cause for disconnection in the 'DisengageReason' enumeration. If an 'acc_main_off' signal is received, the 'mads_exit_controls' function halts all requests for lateral control engagement. Additionally, the status of 'controls_requested_lat' now mirrors 'controls_allowed_lat' after a button press. * simpler logic cleaner * reorder code for readability * tmp * Refactor state transitions and add event handlers Renamed StateTransition to EdgeTransition for clarity and updated related logic. Introduced event handlers for button presses and ACC state changes, reducing duplicated control flow code. Improved encapsulation and maintainability by restructuring state update functions. * reorder * Refactor MADS state handling logic Removed redundant event handler functions and unnecessary timestamp fields to streamline the code. Simplified button and binary state updates by integrating logic directly into transition checks. Commented out unused fields * adding some more tests * split init * format * update naming * Refine lateral control request logic in safety_mads.h The logic for setting the `controls_requested_lat` variable in safety_mads.h has been refined. Previously, it switched state based on the current value of `controls_allowed_lat`. Now, it also takes into account the current state of `acc_main`, ensuring a more nuanced control request mechanism that accounts for different operational scenarios. * Fix button state handling in mads_exit_controls logic. Refactor button state transitions to better handle lateral control requests when ACC is active. Ensure controls are correctly disengaged under specific conditions, by setting `controls_requested_lat` more reliably during state transitions. This change improves safety by preventing inadvertent disengagement when ACC is not active. * Add test for LKAS button press with ACC main on This commit introduces a new test to ensure that controls remain enabled when the LKAS/LFA button is pressed while ACC main is on. It checks that LKAS button operations don't interfere with control permissions in this specific configuration, improving test coverage and preventing potential safety issues. * Add mismatch detection and change mads_acc_main to bool Enhanced mismatch detection logic by tracking cases where 'controls_allowed' is true while 'controls_allowed_lat' is false, updating the script to print relevant debug information. Additionally, changed the data type of 'mads_acc_main' and 'mads_acc_main_prev' from int to bool for improved type accuracy and consistency. * update controls_allowed_lat_pkt on health pkt to actually follow is_lat_active() which has the final word on whether we can allow lat or not. * Can't perform this test on toyota as we never really process a button disengagement for toyota * wow, we forgot about pcm hyundai can-fd * nuke nuke nuke * Revert "nuke nuke nuke" This reverts commit 9bf0de640a3439ac43c27bcbc6568853966d370b. * update name * event driven update states * add get_pcm_main_cruise_available * split PCM and non-PCM main cruise tets * fix some * pcm main cruise availability mutation * toyota pass fake lkas btn pressed * more * make pcm acc main rising edge on init * only falling edge when actually 0 (need test for mutation) * misra * remove state flags, main button related * skip lkas related tests with toyota and subaru fake button * need for honda * static * mutation * misra * skip nidec pcm alt * engage mads if controls allowed rising * static * remove non pcm properties * fixup! engage mads if controls allowed rising * move back * fix static * move around * Hyundai openpilot longitudinal main cruise button state handling * main button unit test * acc_main_on mismatch unit tests * clean up old main cruise button unit tests * add more reasons * cleanup * rename * rearrange * Revert "rearrange" This reverts commit f07caaa5b98b74c23667b387430ac48ba95bf21c. * more rearrange * rename * more * too slow * Revert "too slow" This reverts commit 31a249aebfa9c985e37be050e525b6924ca9e83d. * too slow v2 * cleanup * rename * more cleanup * Parse more flags from alt exp, more tests, hyundai main cruise allowed * missed * mutation for controls allowed rising edge * ford mutation * Update tests/safety/test.sh Co-authored-by: DevTekVE <devtekve@gmail.com> * license * unused * remove * comment * Apply suggestions from code review Co-authored-by: DevTekVE <devtekve@gmail.com> * comment * refactor alternative experience handling with helper function * use always allowed mads button alt exp * rename * parenthesis * use alternative experience for unit tests inits * cleanup * rename * mutation tests for alternative experience flags * bump timer * test for disengage and no disengage lateral on brake * test allow MADS engage with brake pressed * rename * move around * button combo test * use acc_main_on directly from global * fix caught failures from last commit's fix * Revert "use acc_main_on directly from global" This reverts commit 346964f55d020a287a1a679e22691ad8873e2a64. * Properly fix lmao * Add support for LKAS button handling across Chrysler platforms Introduced LKAS button message parsing for multiple Chrysler platforms, including specific handling for center stack button messages. Updated tests and safety configurations to reflect these changes, ensuring compatibility with different vehicle variants. This enhances modularity and improves safety feature integration. * Dockerfile: point to sunnypilot/opendbc * Happy days :) * clean * testx * Revert "Happy days :)" This reverts commit 7ea27b53c8f3b1e37677c1ce9498229fceac9de6. * symlink prior building * comment * only parse mads lateral, not stock op's lateral * do not allow controls allowed if acc_main_on is off * expose system_enabled, do not allow controls allowed to steer if system_mads is off * fix hyundai tests with acc_main_on requirement * fix test with new controls allowed with system_mads off * fix replay drive * Change 'DISABLE_DISENGAGE_LATERAL_ON_BRAKE' to 'DISENGAGE_LATERAL_ON_BRAKE' The commit modifies the usage of the 'DISABLE_DISENGAGE_LATERAL_ON_BRAKE' variable globally and replaces it with 'DISENGAGE_LATERAL_ON_BRAKE'. This change promotes correct and clear semantics, since the variable now indicates a state rather than the negation of a state. * Adding some more debug printouts on replay drive * remove unified engagement mode in panda * treat MADS button as user entry * controls allow should be allowed at all times * squash! treat MADS button as user entry * heartbeat for mads * heartbeat mismatch exit control * remove always allow mads button from alt * move to safety_mads * check heartbeat directly in main * remove main cruise allowed from alt * uint * squash! check heartbeat directly in main * update tests * not needed * fix mads_exit_controls sometimes not assigning disengage reason * more disengage lateral on brake tests * extern * missesd * honda mutation test * again * rename * more dlob test * update name * fix tests * fix panda tests * Refactor MADS state management to simplify pointer usage. This change replaces many pointer-based state variables with direct ones, improving code readability and reducing complexity. It also standardizes the use of `const` for parameters and updates function implementations accordingly. These improvements enhance maintainability and reduce potential for pointer-related errors. * Simplify braking logic in m_mads_check_braking function Removed redundant conditions to streamline braking logic. This change maintains functionality while improving code readability and maintainability. Only necessary checks are now performed to determine disengagement. * Prevent lateral control engagement during braking Added a condition to disable lateral control engagement when braking with disengage-on-brake enabled. This change is marked as a demonstration and is not final for merging. Moved the disengage_reason to be set only when an actual disengagement occurred. * Refactor MADS state handling and fix type consistency Remove redundant `get_mads_state` inline definition and migrate it to a static function. Fix return type syntax in `get_mads_pending_disengage_reason`. Minor formatting adjustments improve readability and code clarity. Refactor disengagement logic with enhanced reason tracking Added distinction between active and pending disengagement reasons to improve system state tracking. Updated related enums, structs, and logic to ensure proper handling during control transitions. Added new safety tests to verify behavior under braking and ACC conditions. Refactoring lateral control permissions and brake checks in MADS This revision refactors the MADS safety code. The aim is to simplify and improve readability. Operations and checks for brake states and lateral control permissions have been consolidated into fewer methods. In addition, unused 'previous_disengage' state tracking has been removed from MADSState structure to avoid unnecessary state tracking. Moreover, the 'can_allow_controls_lat' function has been removed entirely and its functionality has been incorporated into other functions, reducing the function count and complexity of the code. The braking status is now tracked with BinaryStateTracking for consistency. These changes maintain the system's functionality while optimizing the code and improving maintainability. * Why MISRA, why!? WHY!???? I DIDNT EVEN TOUCH THIS FILE OR NOWHERE NEAR! * Some format * no more messing with misra * const * more generic names * revert to validate * are you srs * make gpio.h stock again and add to supression lists the check on gpio.h since we are not even touching it and we don't plan on ever doing so * hard code to skip heartbeat check * update comment * cleanup * Update tests/safety/test_honda.py --------- Co-authored-by: DevTekVE <devtekve@gmail.com>
2024-12-15 18:05:31 -05:00
def send_heartbeat(self, engaged=True, engaged_mads=True):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf3, engaged, engaged_mads, b'')
# disable heartbeat checks for use outside of openpilot
# sending a heartbeat will reenable the checks
def set_heartbeat_disabled(self):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf8, 0, 0, b'')
# ****************** Timer *****************
def get_microsecond_timer(self):
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xa8, 0, 0, 4)
return struct.unpack("I", dat)[0]
# ******************* IR *******************
def set_ir_power(self, percentage):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xb0, int(percentage), 0, b'')
# ******************* Fan ******************
def set_fan_power(self, percentage):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xb1, int(percentage), 0, b'')
def get_fan_rpm(self):
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xb2, 0, 0, 2)
a = struct.unpack("H", dat)
return a[0]
# ****************** Siren *****************
def set_siren(self, enabled):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf6, int(enabled), 0, b'')
# ****************** Debug *****************
# arr: timer period
# ccrN: channel N pulse length
def set_clock_source_timer_params(self, arr, ccr1, ccr2, ccr3):
param1 = ((ccr1 & 0xFF) << 8) | (ccr2 & 0xFF)
param2 = ((ccr3 & 0xFF) << 8) | (arr & 0xFF)
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe6, param1, param2, b'')
def force_relay_drive(self, intercept_relay_drive, ignition_relay_drive):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xc5, (int(intercept_relay_drive) | int(ignition_relay_drive) << 1), 0, b'')
def read_som_gpio(self) -> bool:
r = self._handle.controlRead(Panda.REQUEST_IN, 0xc6, 0, 0, 1)
return r[0] == 1