feat: add EskinDeviceFunc FFI bindings and update Python/README

- Add FFI wrappers for all EskinDeviceFunc trait methods:
  eskin_read_hdw_version, eskin_read_matrix_row/col,
  eskin_read_device_config1/2, eskin_write_device_config1/2,
  eskin_write_matrix_row/col
- Extract sdk_error_to_code() helper for SdkError -> SdkErrorCode conversion
- Update C header (include/eskin_ffi.h) with new function declarations
- Update Python FFI bindings (example/python/eskin_ffi.py) with new methods
- Update README with Python usage instructions and full FFI interface table
This commit is contained in:
lenn
2026-05-07 10:00:04 +08:00
parent 127ade0b37
commit 96f1e7db1e
7 changed files with 490 additions and 18 deletions

View File

@@ -1,9 +1,10 @@
import ctypes
from ctypes import (
Structure, POINTER, c_void_p, c_char_p, c_uint8, c_uint16,
Structure, POINTER, c_void_p, c_char, c_char_p, c_uint8, c_uint16,
c_uint32, c_uint64, c_int16, c_bool
)
LIB_PATH = "./libeskin_finger_sdk.so"
class EskinSdkVersion(Structure):
_fields_ = [
@@ -14,8 +15,8 @@ class EskinSdkVersion(Structure):
class EskinDevice:
def __init__(self, lib_path: str):
self._lib = ctypes.CDLL(lib_path)
def __init__(self):
self._lib = ctypes.CDLL(LIB_PATH)
self._setup_functions()
self._handle = None
@@ -42,6 +43,53 @@ class EskinDevice:
c_void_p, c_uint32, POINTER(c_uint8), c_uint16, POINTER(c_uint16)
]
# EskinDeviceFunc bindings
lib.eskin_read_hdw_version.restype = c_uint32
lib.eskin_read_hdw_version.argtypes = [
c_void_p, POINTER(c_char), c_uint32, POINTER(c_uint32)
]
lib.eskin_read_matrix_row.restype = c_uint32
lib.eskin_read_matrix_row.argtypes = [
c_void_p, POINTER(c_uint8)
]
lib.eskin_read_matrix_col.restype = c_uint32
lib.eskin_read_matrix_col.argtypes = [
c_void_p, POINTER(c_uint8)
]
lib.eskin_read_device_config1.restype = c_uint32
lib.eskin_read_device_config1.argtypes = [
c_void_p, POINTER(c_uint8)
]
lib.eskin_read_device_config2.restype = c_uint32
lib.eskin_read_device_config2.argtypes = [
c_void_p, POINTER(c_uint8)
]
lib.eskin_write_device_config1.restype = c_uint32
lib.eskin_write_device_config1.argtypes = [
c_void_p, c_bool, POINTER(c_uint16)
]
lib.eskin_write_device_config2.restype = c_uint32
lib.eskin_write_device_config2.argtypes = [
c_void_p, c_bool, POINTER(c_uint16)
]
lib.eskin_write_matrix_row.restype = c_uint32
lib.eskin_write_matrix_row.argtypes = [
c_void_p, c_uint8, POINTER(c_uint16)
]
lib.eskin_write_matrix_col.restype = c_uint32
lib.eskin_write_matrix_col.argtypes = [
c_void_p, c_uint8, POINTER(c_uint16)
]
def version(self) -> tuple:
v = self._lib.eskin_version()
return (v.major, v.minor, v.patch)
@@ -79,6 +127,89 @@ class EskinDevice:
raise RuntimeError(f"write_register failed: error={err}")
return ret.value
def read_hdw_version(self) -> str:
"""读取硬件版本号"""
buf = (c_char * 64)()
actual = c_uint32(0)
err = self._lib.eskin_read_hdw_version(
self._handle, buf, len(buf), ctypes.byref(actual)
)
if err != 0:
raise RuntimeError(f"read_hdw_version failed: error={err}")
return buf[:actual.value].decode("utf-8")
def read_matrix_row(self) -> int:
"""读取矩阵行数"""
out = c_uint8(0)
err = self._lib.eskin_read_matrix_row(self._handle, ctypes.byref(out))
if err != 0:
raise RuntimeError(f"read_matrix_row failed: error={err}")
return out.value
def read_matrix_col(self) -> int:
"""读取矩阵列数"""
out = c_uint8(0)
err = self._lib.eskin_read_matrix_col(self._handle, ctypes.byref(out))
if err != 0:
raise RuntimeError(f"read_matrix_col failed: error={err}")
return out.value
def read_device_config1(self) -> int:
"""读取设备配置寄存器1"""
out = c_uint8(0)
err = self._lib.eskin_read_device_config1(self._handle, ctypes.byref(out))
if err != 0:
raise RuntimeError(f"read_device_config1 failed: error={err}")
return out.value
def read_device_config2(self) -> int:
"""读取设备配置寄存器2"""
out = c_uint8(0)
err = self._lib.eskin_read_device_config2(self._handle, ctypes.byref(out))
if err != 0:
raise RuntimeError(f"read_device_config2 failed: error={err}")
return out.value
def write_device_config1(self, enable: bool) -> int:
"""写入设备配置寄存器1"""
ret = c_uint16(0)
err = self._lib.eskin_write_device_config1(
self._handle, enable, ctypes.byref(ret)
)
if err != 0:
raise RuntimeError(f"write_device_config1 failed: error={err}")
return ret.value
def write_device_config2(self, enable: bool) -> int:
"""写入设备配置寄存器2"""
ret = c_uint16(0)
err = self._lib.eskin_write_device_config2(
self._handle, enable, ctypes.byref(ret)
)
if err != 0:
raise RuntimeError(f"write_device_config2 failed: error={err}")
return ret.value
def write_matrix_row(self, row: int) -> int:
"""写入矩阵行数"""
ret = c_uint16(0)
err = self._lib.eskin_write_matrix_row(
self._handle, row, ctypes.byref(ret)
)
if err != 0:
raise RuntimeError(f"write_matrix_row failed: error={err}")
return ret.value
def write_matrix_col(self, col: int) -> int:
"""写入矩阵列数"""
ret = c_uint16(0)
err = self._lib.eskin_write_matrix_col(
self._handle, col, ctypes.byref(ret)
)
if err != 0:
raise RuntimeError(f"write_matrix_col failed: error={err}")
return ret.value
def __enter__(self):
return self