Files

84 lines
2.3 KiB
Python

import ctypes
import os
from panda import LEN_TO_DLC
libpanda_dir = os.path.dirname(os.path.abspath(__file__))
libpanda_fn = os.path.join(libpanda_dir, "libpanda.so")
class CANPacketHeader(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
("fd", ctypes.c_uint8, 1),
("bus", ctypes.c_uint8, 3),
("data_len_code", ctypes.c_uint8, 4),
]
class CANPacketAddress(ctypes.LittleEndianStructure):
_pack_ = 1
_fields_ = [
("rejected", ctypes.c_uint32, 1),
("returned", ctypes.c_uint32, 1),
("extended", ctypes.c_uint32, 1),
("addr", ctypes.c_uint32, 29),
]
class CANPacketFields(ctypes.LittleEndianStructure):
_pack_ = 1
_anonymous_ = ("header", "address")
_fields_ = [
("header", CANPacketHeader),
("address", CANPacketAddress),
("checksum", ctypes.c_uint8),
("data", ctypes.c_uint8 * 64),
]
class CANPacket(ctypes.Union):
# Match CANPacket_t's packed fields and aligned(4) attribute.
_anonymous_ = ("packet",)
_fields_ = [("packet", CANPacketFields), ("_alignment", ctypes.c_uint32)]
class CANRing(ctypes.Structure):
_fields_ = [
("w_ptr", ctypes.c_uint32),
("r_ptr", ctypes.c_uint32),
("fifo_size", ctypes.c_uint32),
("elems", ctypes.POINTER(CANPacket)),
]
libpanda = ctypes.CDLL(libpanda_fn)
for name in ("rx_q", "tx1_q", "tx2_q", "tx3_q"):
setattr(libpanda, name, ctypes.POINTER(CANRing).in_dll(libpanda, name))
for name, argtypes, restype in (
("set_safety_hooks", [ctypes.c_uint16, ctypes.c_uint16], ctypes.c_int),
("can_pop", [ctypes.POINTER(CANRing), ctypes.POINTER(CANPacket)], ctypes.c_bool),
("can_push", [ctypes.POINTER(CANRing), ctypes.POINTER(CANPacket)], ctypes.c_bool),
("can_set_checksum", [ctypes.POINTER(CANPacket)], None),
("comms_can_read", [ctypes.POINTER(ctypes.c_uint8), ctypes.c_uint32], ctypes.c_int),
("comms_can_write", [ctypes.c_char_p, ctypes.c_uint32], None),
("comms_can_reset", [], None),
("can_slots_empty", [ctypes.POINTER(CANRing)], ctypes.c_uint32),
):
func = getattr(libpanda, name)
func.argtypes = argtypes
func.restype = restype
def make_CANPacket(addr: int, bus: int, dat) -> CANPacket:
ret = CANPacket()
ret.extended = 1 if addr >= 0x800 else 0
ret.addr = addr
ret.data_len_code = LEN_TO_DLC[len(dat)]
ret.bus = bus
ret.data[:len(dat)] = bytes(dat)
libpanda.can_set_checksum(ret)
return ret