Move PM35 protocol into shared C core
This commit is contained in:
@@ -139,6 +139,44 @@ class NativeProtocol:
|
||||
ctypes.c_uint8, ctypes.c_uint16, ctypes.c_void_p, ctypes.c_size_t,
|
||||
]
|
||||
lib.pcan_abi_balsam_register_name.restype = ctypes.c_size_t
|
||||
lib.pcan_abi_periph28335_crc16.argtypes = [ctypes.c_void_p, ctypes.c_size_t]
|
||||
lib.pcan_abi_periph28335_crc16.restype = ctypes.c_uint16
|
||||
lib.pcan_abi_periph28335_append_crc.argtypes = [
|
||||
ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p, ctypes.c_size_t,
|
||||
]
|
||||
lib.pcan_abi_periph28335_append_crc.restype = ctypes.c_size_t
|
||||
lib.pcan_abi_periph28335_build_read.argtypes = [
|
||||
ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint16,
|
||||
ctypes.c_void_p, ctypes.c_size_t,
|
||||
]
|
||||
lib.pcan_abi_periph28335_build_read.restype = ctypes.c_size_t
|
||||
lib.pcan_abi_periph28335_build_write.argtypes = [
|
||||
ctypes.c_uint8, ctypes.c_uint16, ctypes.c_uint16,
|
||||
ctypes.c_void_p, ctypes.c_size_t,
|
||||
]
|
||||
lib.pcan_abi_periph28335_build_write.restype = ctypes.c_size_t
|
||||
lib.pcan_abi_periph28335_build_command.argtypes = [
|
||||
ctypes.c_uint8, ctypes.c_uint8, ctypes.c_void_p, ctypes.c_size_t,
|
||||
]
|
||||
lib.pcan_abi_periph28335_build_command.restype = ctypes.c_size_t
|
||||
lib.pcan_abi_periph28335_expected_read_size.argtypes = [ctypes.c_uint16]
|
||||
lib.pcan_abi_periph28335_expected_read_size.restype = ctypes.c_size_t
|
||||
lib.pcan_abi_periph28335_decode_read.argtypes = [
|
||||
ctypes.c_void_p, ctypes.c_size_t, ctypes.c_uint8, ctypes.c_uint16,
|
||||
ctypes.POINTER(ctypes.c_uint16), ctypes.c_size_t,
|
||||
]
|
||||
lib.pcan_abi_periph28335_decode_read.restype = ctypes.c_int
|
||||
lib.pcan_abi_periph28335_validate_write.argtypes = [
|
||||
ctypes.c_void_p, ctypes.c_size_t, ctypes.c_void_p, ctypes.c_size_t,
|
||||
]
|
||||
lib.pcan_abi_periph28335_validate_write.restype = ctypes.c_int
|
||||
lib.pcan_abi_periph28335_project_count.restype = ctypes.c_size_t
|
||||
lib.pcan_abi_periph28335_project_name.argtypes = [ctypes.c_size_t]
|
||||
lib.pcan_abi_periph28335_project_name.restype = ctypes.c_char_p
|
||||
lib.pcan_abi_periph28335_command_name.argtypes = [
|
||||
ctypes.c_size_t, ctypes.c_size_t,
|
||||
]
|
||||
lib.pcan_abi_periph28335_command_name.restype = ctypes.c_char_p
|
||||
lib.pcan_abi_frame_encode.argtypes = [
|
||||
ctypes.c_uint8, ctypes.c_uint8, ctypes.c_uint32,
|
||||
ctypes.c_void_p, ctypes.c_uint8, ctypes.c_void_p, ctypes.c_size_t,
|
||||
@@ -220,6 +258,83 @@ class NativeProtocol:
|
||||
device, address, output, len(output))
|
||||
return output.value.decode("utf-8")
|
||||
|
||||
@staticmethod
|
||||
def _bytes_buffer(data: bytes):
|
||||
return (ctypes.c_uint8 * len(data)).from_buffer_copy(data) if data else None
|
||||
|
||||
def periph28335_crc16(self, data: bytes) -> int:
|
||||
return int(self.lib.pcan_abi_periph28335_crc16(
|
||||
self._bytes_buffer(data), len(data)))
|
||||
|
||||
def periph28335_append_crc(self, payload: bytes) -> bytes:
|
||||
source = self._bytes_buffer(payload)
|
||||
output = (ctypes.c_uint8 * (len(payload) + 2))()
|
||||
size = int(self.lib.pcan_abi_periph28335_append_crc(
|
||||
source, len(payload), output, len(output)))
|
||||
if size == 0:
|
||||
raise ValueError("SETProtocol rejected PM35 payload")
|
||||
return bytes(output[:size])
|
||||
|
||||
def periph28335_build_read(self, controller: int, start: int,
|
||||
count: int) -> bytes:
|
||||
output = (ctypes.c_uint8 * 8)()
|
||||
size = int(self.lib.pcan_abi_periph28335_build_read(
|
||||
controller, start, count, output, len(output)))
|
||||
if size == 0:
|
||||
raise ValueError("SETProtocol rejected PM35 read request")
|
||||
return bytes(output[:size])
|
||||
|
||||
def periph28335_build_write(self, controller: int, address: int,
|
||||
value: int) -> bytes:
|
||||
output = (ctypes.c_uint8 * 8)()
|
||||
size = int(self.lib.pcan_abi_periph28335_build_write(
|
||||
controller, address, value, output, len(output)))
|
||||
if size == 0:
|
||||
raise ValueError("SETProtocol rejected PM35 write request")
|
||||
return bytes(output[:size])
|
||||
|
||||
def periph28335_build_command(self, controller: int,
|
||||
command_index: int) -> bytes:
|
||||
output = (ctypes.c_uint8 * 8)()
|
||||
size = int(self.lib.pcan_abi_periph28335_build_command(
|
||||
controller, command_index, output, len(output)))
|
||||
if size == 0:
|
||||
raise ValueError("SETProtocol rejected PM35 command")
|
||||
return bytes(output[:size])
|
||||
|
||||
def periph28335_expected_read_size(self, count: int) -> int:
|
||||
return int(self.lib.pcan_abi_periph28335_expected_read_size(count))
|
||||
|
||||
def periph28335_decode_read(self, data: bytes, controller: int,
|
||||
count: int) -> tuple[int, tuple[int, ...]]:
|
||||
source = self._bytes_buffer(data)
|
||||
output = (ctypes.c_uint16 * count)()
|
||||
status = int(self.lib.pcan_abi_periph28335_decode_read(
|
||||
source, len(data), controller, count, output, count))
|
||||
return status, tuple(int(value) for value in output) if status == 0 else ()
|
||||
|
||||
def periph28335_validate_write(self, response: bytes,
|
||||
request: bytes) -> int:
|
||||
return int(self.lib.pcan_abi_periph28335_validate_write(
|
||||
self._bytes_buffer(response), len(response),
|
||||
self._bytes_buffer(request), len(request)))
|
||||
|
||||
def periph28335_catalog(self) -> dict[str, tuple[str, ...]]:
|
||||
result: dict[str, tuple[str, ...]] = {}
|
||||
for project in range(int(self.lib.pcan_abi_periph28335_project_count())):
|
||||
raw_name = self.lib.pcan_abi_periph28335_project_name(project)
|
||||
if not raw_name:
|
||||
raise NativeProtocolUnavailable("invalid PM35 project catalog")
|
||||
commands = []
|
||||
for command in range(17):
|
||||
raw_command = self.lib.pcan_abi_periph28335_command_name(
|
||||
project, command)
|
||||
if raw_command is None:
|
||||
raise NativeProtocolUnavailable("invalid PM35 command catalog")
|
||||
commands.append(raw_command.decode("utf-8"))
|
||||
result[raw_name.decode("utf-8")] = tuple(commands)
|
||||
return result
|
||||
|
||||
def encode(self, sequence: int, flags: int, can_id: int, data: bytes) -> bytes:
|
||||
if len(data) > 8:
|
||||
raise ValueError("DLC cannot exceed 8 bytes")
|
||||
|
||||
Reference in New Issue
Block a user