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:
25
README.md
25
README.md
@@ -98,18 +98,30 @@ int main() {
|
|||||||
|
|
||||||
## 使用 Python
|
## 使用 Python
|
||||||
|
|
||||||
|
### 构建 & 准备
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
# 将生成的 .so 文件复制到 python 示例目录下
|
||||||
|
cp target/release/libeskin_finger_sdk.so example/python/
|
||||||
cd example/python
|
cd example/python
|
||||||
LD_LIBRARY_PATH=../../target/release python3 example.py
|
python3 example.py
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> **注意:** Python 示例默认从当前目录加载 `libeskin_finger_sdk.so`,请确保 `.so` 文件已复制到 `example/python/` 目录下,或修改 `example.py` 中的 `LIB_PATH` 指向正确的路径。
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from eskin_ffi import EskinDevice
|
from eskin_ffi import EskinDevice
|
||||||
|
|
||||||
with EskinDevice("target/release/libeskin_finger_sdk.so") as dev:
|
with EskinDevice("libeskin_finger_sdk.so") as dev:
|
||||||
dev.open("/dev/ttyUSB0")
|
dev.open("/dev/ttyUSB0")
|
||||||
|
|
||||||
|
# 读取硬件版本
|
||||||
|
print(f"Hardware version: {dev.read_hdw_version()}")
|
||||||
|
|
||||||
|
# 读取矩阵尺寸
|
||||||
|
print(f"Matrix: {dev.read_matrix_row()} x {dev.read_matrix_col()}")
|
||||||
|
|
||||||
# 读寄存器
|
# 读寄存器
|
||||||
data = dev.read_register(0x0000, 4)
|
data = dev.read_register(0x0000, 4)
|
||||||
print(f"Serial: {data.hex()}")
|
print(f"Serial: {data.hex()}")
|
||||||
@@ -129,6 +141,15 @@ with EskinDevice("target/release/libeskin_finger_sdk.so") as dev:
|
|||||||
| `eskin_close(handle)` | 关闭设备,释放 handle |
|
| `eskin_close(handle)` | 关闭设备,释放 handle |
|
||||||
| `eskin_read_register(handle, addr, length, buf, buf_len, actual_len)` | 读寄存器原始字节 |
|
| `eskin_read_register(handle, addr, length, buf, buf_len, actual_len)` | 读寄存器原始字节 |
|
||||||
| `eskin_write_register(handle, addr, data, data_len, return_count)` | 写寄存器原始字节 |
|
| `eskin_write_register(handle, addr, data, data_len, return_count)` | 写寄存器原始字节 |
|
||||||
|
| `eskin_read_hdw_version(handle, buf, buf_len, actual_len)` | 读取硬件版本号 |
|
||||||
|
| `eskin_read_matrix_row(handle, out)` | 读取矩阵行数 |
|
||||||
|
| `eskin_read_matrix_col(handle, out)` | 读取矩阵列数 |
|
||||||
|
| `eskin_read_device_config1(handle, out)` | 读取设备配置寄存器1 |
|
||||||
|
| `eskin_read_device_config2(handle, out)` | 读取设备配置寄存器2 |
|
||||||
|
| `eskin_write_device_config1(handle, enable, return_count)` | 写入设备配置寄存器1 |
|
||||||
|
| `eskin_write_device_config2(handle, enable, return_count)` | 写入设备配置寄存器2 |
|
||||||
|
| `eskin_write_matrix_row(handle, row, return_count)` | 写入矩阵行数 |
|
||||||
|
| `eskin_write_matrix_col(handle, col, return_count)` | 写入矩阵列数 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import ctypes
|
import ctypes
|
||||||
from ctypes import (
|
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
|
c_uint32, c_uint64, c_int16, c_bool
|
||||||
)
|
)
|
||||||
|
|
||||||
|
LIB_PATH = "./libeskin_finger_sdk.so"
|
||||||
|
|
||||||
class EskinSdkVersion(Structure):
|
class EskinSdkVersion(Structure):
|
||||||
_fields_ = [
|
_fields_ = [
|
||||||
@@ -14,8 +15,8 @@ class EskinSdkVersion(Structure):
|
|||||||
|
|
||||||
|
|
||||||
class EskinDevice:
|
class EskinDevice:
|
||||||
def __init__(self, lib_path: str):
|
def __init__(self):
|
||||||
self._lib = ctypes.CDLL(lib_path)
|
self._lib = ctypes.CDLL(LIB_PATH)
|
||||||
self._setup_functions()
|
self._setup_functions()
|
||||||
self._handle = None
|
self._handle = None
|
||||||
|
|
||||||
@@ -42,6 +43,53 @@ class EskinDevice:
|
|||||||
c_void_p, c_uint32, POINTER(c_uint8), c_uint16, POINTER(c_uint16)
|
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:
|
def version(self) -> tuple:
|
||||||
v = self._lib.eskin_version()
|
v = self._lib.eskin_version()
|
||||||
return (v.major, v.minor, v.patch)
|
return (v.major, v.minor, v.patch)
|
||||||
@@ -79,6 +127,89 @@ class EskinDevice:
|
|||||||
raise RuntimeError(f"write_register failed: error={err}")
|
raise RuntimeError(f"write_register failed: error={err}")
|
||||||
return ret.value
|
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):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
from eskin_ffi import EskinDevice
|
||||||
|
|
||||||
|
def main():
|
||||||
|
dev = EskinDevice()
|
||||||
|
|
||||||
|
# SDK 版本
|
||||||
|
ver = dev.version()
|
||||||
|
print(f"ESkin SDK version: {ver[0]}.{ver[1]}.{ver[2]}")
|
||||||
|
|
||||||
|
# 打开设备
|
||||||
|
dev.open("/dev/ttyUSB0")
|
||||||
|
print("Device opened")
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 读取硬件版本
|
||||||
|
hdw_ver = dev.read_hdw_version()
|
||||||
|
print(f"Hardware version: {hdw_ver}")
|
||||||
|
|
||||||
|
# 读取矩阵尺寸
|
||||||
|
row = dev.read_matrix_row()
|
||||||
|
col = dev.read_matrix_col()
|
||||||
|
print(f"Matrix size: {row} x {col}")
|
||||||
|
|
||||||
|
# 读取设备配置
|
||||||
|
cfg1 = dev.read_device_config1()
|
||||||
|
# cfg2 = dev.read_device_config2()
|
||||||
|
print(f"Device config1: 0x{cfg1:02X}")
|
||||||
|
# print(f"Device config2: 0x{cfg2:02X}")
|
||||||
|
|
||||||
|
# 写入矩阵尺寸示例
|
||||||
|
# ret = dev.write_matrix_row(16)
|
||||||
|
# print(f"Write matrix row: returned {ret} bytes")
|
||||||
|
# ret = dev.write_matrix_col(16)
|
||||||
|
# print(f"Write matrix col: returned {ret} bytes")
|
||||||
|
|
||||||
|
# 写入设备配置示例
|
||||||
|
# ret = dev.write_device_config1(True)
|
||||||
|
# print(f"Write device config1: returned {ret} bytes")
|
||||||
|
# ret = dev.write_device_config2(False)
|
||||||
|
# print(f"Write device config2: returned {ret} bytes")
|
||||||
|
|
||||||
|
# 原始寄存器读写
|
||||||
|
data = dev.read_register(0x1C00, 168)
|
||||||
|
print(f"Serial number: {data.hex().upper()}")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
dev.close()
|
||||||
|
print("Device closed")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -60,6 +60,59 @@ EskinSdkErrorCode eskin_write_register(
|
|||||||
uint16_t* return_count
|
uint16_t* return_count
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Device function interfaces (EskinDeviceFunc)
|
||||||
|
|
||||||
|
EskinSdkErrorCode eskin_read_hdw_version(
|
||||||
|
EskinDeviceHandle handle,
|
||||||
|
char* buf,
|
||||||
|
uint32_t buf_len,
|
||||||
|
uint32_t* actual_len
|
||||||
|
);
|
||||||
|
|
||||||
|
EskinSdkErrorCode eskin_read_matrix_row(
|
||||||
|
EskinDeviceHandle handle,
|
||||||
|
uint8_t* out
|
||||||
|
);
|
||||||
|
|
||||||
|
EskinSdkErrorCode eskin_read_matrix_col(
|
||||||
|
EskinDeviceHandle handle,
|
||||||
|
uint8_t* out
|
||||||
|
);
|
||||||
|
|
||||||
|
EskinSdkErrorCode eskin_read_device_config1(
|
||||||
|
EskinDeviceHandle handle,
|
||||||
|
uint8_t* out
|
||||||
|
);
|
||||||
|
|
||||||
|
EskinSdkErrorCode eskin_read_device_config2(
|
||||||
|
EskinDeviceHandle handle,
|
||||||
|
uint8_t* out
|
||||||
|
);
|
||||||
|
|
||||||
|
EskinSdkErrorCode eskin_write_device_config1(
|
||||||
|
EskinDeviceHandle handle,
|
||||||
|
bool enable,
|
||||||
|
uint16_t* return_count
|
||||||
|
);
|
||||||
|
|
||||||
|
EskinSdkErrorCode eskin_write_device_config2(
|
||||||
|
EskinDeviceHandle handle,
|
||||||
|
bool enable,
|
||||||
|
uint16_t* return_count
|
||||||
|
);
|
||||||
|
|
||||||
|
EskinSdkErrorCode eskin_write_matrix_row(
|
||||||
|
EskinDeviceHandle handle,
|
||||||
|
uint8_t row,
|
||||||
|
uint16_t* return_count
|
||||||
|
);
|
||||||
|
|
||||||
|
EskinSdkErrorCode eskin_write_matrix_col(
|
||||||
|
EskinDeviceHandle handle,
|
||||||
|
uint8_t col,
|
||||||
|
uint16_t* return_count
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ impl EskinDeviceFunc for EskinDeviceInner {
|
|||||||
|
|
||||||
fn read_device_config2(&mut self) -> Result<u8, SdkError> {
|
fn read_device_config2(&mut self) -> Result<u8, SdkError> {
|
||||||
let enabled = self.read_register(0x0018, 1)
|
let enabled = self.read_register(0x0018, 1)
|
||||||
.map_err(|_| SdkError::FrameError("read device config1 failed".into()))?;
|
.map_err(|_| SdkError::FrameError("read device config2 failed".into()))?;
|
||||||
Ok(enabled[0])
|
Ok(enabled[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
235
src/ffi/mod.rs
235
src/ffi/mod.rs
@@ -1,6 +1,7 @@
|
|||||||
use std::{ptr};
|
use std::{ptr};
|
||||||
use std::ffi::{CStr, c_char};
|
use std::ffi::{CStr, c_char};
|
||||||
use crate::device::EskinDevice;
|
use crate::device::EskinDevice;
|
||||||
|
use crate::device::EskinDeviceFunc;
|
||||||
use crate::transport::SerialPortTransport;
|
use crate::transport::SerialPortTransport;
|
||||||
use crate::{config::DeviceConfig, device::EskinDeviceInner, error::SdkErrorCode};
|
use crate::{config::DeviceConfig, device::EskinDeviceInner, error::SdkErrorCode};
|
||||||
|
|
||||||
@@ -31,6 +32,27 @@ struct DeviceWrapper {
|
|||||||
last_me_raw: Vec<u8>
|
last_me_raw: Vec<u8>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sdk_error_to_code(err: crate::error::SdkError) -> SdkErrorCode {
|
||||||
|
match err {
|
||||||
|
crate::error::SdkError::Timeout => SdkErrorCode::Timeout,
|
||||||
|
crate::error::SdkError::FrameError(_) => SdkErrorCode::FrameError,
|
||||||
|
crate::error::SdkError::CrcError { .. } => SdkErrorCode::CrcError,
|
||||||
|
crate::error::SdkError::DeviceError(_) => SdkErrorCode::DeviceError,
|
||||||
|
crate::error::SdkError::IoError(_) => SdkErrorCode::IoError,
|
||||||
|
crate::error::SdkError::NotInitialized => SdkErrorCode::NotInitialized,
|
||||||
|
crate::error::SdkError::AlreadyStreaming => SdkErrorCode::AlreadyStreaming,
|
||||||
|
crate::error::SdkError::NotStreaming => SdkErrorCode::NotStreaming,
|
||||||
|
crate::error::SdkError::DeviceNotFound(_) => SdkErrorCode::DeviceNotFound,
|
||||||
|
crate::error::SdkError::DeviceAlreadyOpen => SdkErrorCode::DeviceAlreadyOpen,
|
||||||
|
crate::error::SdkError::ConfigError(_) => SdkErrorCode::ConfigError,
|
||||||
|
crate::error::SdkError::ChannelClosed => SdkErrorCode::ChannelClosed,
|
||||||
|
crate::error::SdkError::InternalError(_) => SdkErrorCode::InternalError,
|
||||||
|
crate::error::SdkError::BufferOverflow(_) => SdkErrorCode::BufferOverflow,
|
||||||
|
crate::error::SdkError::InvalidParameter(_) => SdkErrorCode::InvalidParameter,
|
||||||
|
crate::error::SdkError::ProtocolError(_) => SdkErrorCode::ProtocolError,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[unsafe(no_mangle)]
|
#[unsafe(no_mangle)]
|
||||||
pub extern "C" fn eskin_version() -> EskinSdkVersion {
|
pub extern "C" fn eskin_version() -> EskinSdkVersion {
|
||||||
EskinSdkVersion { major: 0, minor: 1, patch: 0 }
|
EskinSdkVersion { major: 0, minor: 1, patch: 0 }
|
||||||
@@ -111,11 +133,7 @@ pub unsafe extern "C" fn eskin_read_register(
|
|||||||
|
|
||||||
let data = match wrapper.device.read_register(addr, length) {
|
let data = match wrapper.device.read_register(addr, length) {
|
||||||
Ok(d) => d,
|
Ok(d) => d,
|
||||||
Err(crate::error::SdkError::Timeout) => return SdkErrorCode::Timeout,
|
Err(e) => return sdk_error_to_code(e),
|
||||||
Err(crate::error::SdkError::FrameError(_)) => return SdkErrorCode::FrameError,
|
|
||||||
Err(crate::error::SdkError::CrcError { .. }) => return SdkErrorCode::CrcError,
|
|
||||||
Err(crate::error::SdkError::DeviceError(_)) => return SdkErrorCode::DeviceError,
|
|
||||||
Err(_) => return SdkErrorCode::IoError,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let copy_len = std::cmp::min(data.len(), buf_len as usize);
|
let copy_len = std::cmp::min(data.len(), buf_len as usize);
|
||||||
@@ -148,10 +166,207 @@ pub unsafe extern "C" fn eskin_write_register(
|
|||||||
unsafe { *return_count = count };
|
unsafe { *return_count = count };
|
||||||
SdkErrorCode::Success
|
SdkErrorCode::Success
|
||||||
}
|
}
|
||||||
Err(crate::error::SdkError::Timeout) => SdkErrorCode::Timeout,
|
Err(e) => sdk_error_to_code(e),
|
||||||
Err(crate::error::SdkError::FrameError(_)) => SdkErrorCode::FrameError,
|
}
|
||||||
Err(crate::error::SdkError::CrcError { .. }) => SdkErrorCode::CrcError,
|
}
|
||||||
Err(crate::error::SdkError::DeviceError(_)) => SdkErrorCode::DeviceError,
|
|
||||||
Err(_) => SdkErrorCode::IoError,
|
/// 读取硬件版本,写入 buf 中,以 null 结尾
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn eskin_read_hdw_version(
|
||||||
|
handle: EskinDeviceHandle,
|
||||||
|
buf: *mut c_char,
|
||||||
|
buf_len: u32,
|
||||||
|
actual_len: *mut u32,
|
||||||
|
) -> SdkErrorCode {
|
||||||
|
if handle.is_null() || buf.is_null() || actual_len.is_null() {
|
||||||
|
return SdkErrorCode::InvalidPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wrapper = unsafe { &mut *(handle as *mut DeviceWrapper) };
|
||||||
|
|
||||||
|
match wrapper.device.read_hdw_version() {
|
||||||
|
Ok(version) => {
|
||||||
|
let bytes = version.as_bytes();
|
||||||
|
let copy_len = std::cmp::min(bytes.len(), (buf_len as usize).saturating_sub(1));
|
||||||
|
unsafe {
|
||||||
|
ptr::copy_nonoverlapping(bytes.as_ptr(), buf as *mut u8, copy_len);
|
||||||
|
*buf.add(copy_len) = 0; // null terminator
|
||||||
|
*actual_len = bytes.len() as u32;
|
||||||
|
}
|
||||||
|
SdkErrorCode::Success
|
||||||
|
}
|
||||||
|
Err(e) => sdk_error_to_code(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 读取矩阵行数
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn eskin_read_matrix_row(
|
||||||
|
handle: EskinDeviceHandle,
|
||||||
|
out: *mut u8,
|
||||||
|
) -> SdkErrorCode {
|
||||||
|
if handle.is_null() || out.is_null() {
|
||||||
|
return SdkErrorCode::InvalidPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wrapper = unsafe { &mut *(handle as *mut DeviceWrapper) };
|
||||||
|
|
||||||
|
match wrapper.device.read_matrix_row() {
|
||||||
|
Ok(row) => {
|
||||||
|
unsafe { *out = row };
|
||||||
|
SdkErrorCode::Success
|
||||||
|
}
|
||||||
|
Err(e) => sdk_error_to_code(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 读取矩阵列数
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn eskin_read_matrix_col(
|
||||||
|
handle: EskinDeviceHandle,
|
||||||
|
out: *mut u8,
|
||||||
|
) -> SdkErrorCode {
|
||||||
|
if handle.is_null() || out.is_null() {
|
||||||
|
return SdkErrorCode::InvalidPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wrapper = unsafe { &mut *(handle as *mut DeviceWrapper) };
|
||||||
|
|
||||||
|
match wrapper.device.read_matrix_col() {
|
||||||
|
Ok(col) => {
|
||||||
|
unsafe { *out = col };
|
||||||
|
SdkErrorCode::Success
|
||||||
|
}
|
||||||
|
Err(e) => sdk_error_to_code(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 读取设备配置寄存器1
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn eskin_read_device_config1(
|
||||||
|
handle: EskinDeviceHandle,
|
||||||
|
out: *mut u8,
|
||||||
|
) -> SdkErrorCode {
|
||||||
|
if handle.is_null() || out.is_null() {
|
||||||
|
return SdkErrorCode::InvalidPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wrapper = unsafe { &mut *(handle as *mut DeviceWrapper) };
|
||||||
|
|
||||||
|
match wrapper.device.read_device_config1() {
|
||||||
|
Ok(val) => {
|
||||||
|
unsafe { *out = val };
|
||||||
|
SdkErrorCode::Success
|
||||||
|
}
|
||||||
|
Err(e) => sdk_error_to_code(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 读取设备配置寄存器2
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn eskin_read_device_config2(
|
||||||
|
handle: EskinDeviceHandle,
|
||||||
|
out: *mut u8,
|
||||||
|
) -> SdkErrorCode {
|
||||||
|
if handle.is_null() || out.is_null() {
|
||||||
|
return SdkErrorCode::InvalidPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wrapper = unsafe { &mut *(handle as *mut DeviceWrapper) };
|
||||||
|
|
||||||
|
match wrapper.device.read_device_config2() {
|
||||||
|
Ok(val) => {
|
||||||
|
unsafe { *out = val };
|
||||||
|
SdkErrorCode::Success
|
||||||
|
}
|
||||||
|
Err(e) => sdk_error_to_code(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 写入设备配置寄存器1
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn eskin_write_device_config1(
|
||||||
|
handle: EskinDeviceHandle,
|
||||||
|
enable: bool,
|
||||||
|
return_count: *mut u16,
|
||||||
|
) -> SdkErrorCode {
|
||||||
|
if handle.is_null() || return_count.is_null() {
|
||||||
|
return SdkErrorCode::InvalidPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wrapper = unsafe { &mut *(handle as *mut DeviceWrapper) };
|
||||||
|
|
||||||
|
match wrapper.device.write_device_config1(enable) {
|
||||||
|
Ok(count) => {
|
||||||
|
unsafe { *return_count = count };
|
||||||
|
SdkErrorCode::Success
|
||||||
|
}
|
||||||
|
Err(e) => sdk_error_to_code(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 写入设备配置寄存器2
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn eskin_write_device_config2(
|
||||||
|
handle: EskinDeviceHandle,
|
||||||
|
enable: bool,
|
||||||
|
return_count: *mut u16,
|
||||||
|
) -> SdkErrorCode {
|
||||||
|
if handle.is_null() || return_count.is_null() {
|
||||||
|
return SdkErrorCode::InvalidPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wrapper = unsafe { &mut *(handle as *mut DeviceWrapper) };
|
||||||
|
|
||||||
|
match wrapper.device.write_device_config2(enable) {
|
||||||
|
Ok(count) => {
|
||||||
|
unsafe { *return_count = count };
|
||||||
|
SdkErrorCode::Success
|
||||||
|
}
|
||||||
|
Err(e) => sdk_error_to_code(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 写入矩阵行数
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn eskin_write_matrix_row(
|
||||||
|
handle: EskinDeviceHandle,
|
||||||
|
row: u8,
|
||||||
|
return_count: *mut u16,
|
||||||
|
) -> SdkErrorCode {
|
||||||
|
if handle.is_null() || return_count.is_null() {
|
||||||
|
return SdkErrorCode::InvalidPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wrapper = unsafe { &mut *(handle as *mut DeviceWrapper) };
|
||||||
|
|
||||||
|
match wrapper.device.write_matrix_row(row) {
|
||||||
|
Ok(count) => {
|
||||||
|
unsafe { *return_count = count };
|
||||||
|
SdkErrorCode::Success
|
||||||
|
}
|
||||||
|
Err(e) => sdk_error_to_code(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 写入矩阵列数
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn eskin_write_matrix_col(
|
||||||
|
handle: EskinDeviceHandle,
|
||||||
|
col: u8,
|
||||||
|
return_count: *mut u16,
|
||||||
|
) -> SdkErrorCode {
|
||||||
|
if handle.is_null() || return_count.is_null() {
|
||||||
|
return SdkErrorCode::InvalidPointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
let wrapper = unsafe { &mut *(handle as *mut DeviceWrapper) };
|
||||||
|
|
||||||
|
match wrapper.device.write_matrix_col(col) {
|
||||||
|
Ok(count) => {
|
||||||
|
unsafe { *return_count = count };
|
||||||
|
SdkErrorCode::Success
|
||||||
|
}
|
||||||
|
Err(e) => sdk_error_to_code(e),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use eskin_finger_sdk::{config::DeviceConfig, device::{EskinDevice, EskinDeviceInner}, transport::SerialPortTransport};
|
use eskin_finger_sdk::{config::DeviceConfig, device::{EskinDevice, EskinDeviceFunc, EskinDeviceInner}, transport::SerialPortTransport};
|
||||||
fn main() {
|
fn main() {
|
||||||
let transport = SerialPortTransport::new("COM10", 921600);
|
let transport = SerialPortTransport::new("/dev/ttyUSB0", 921600);
|
||||||
let config = DeviceConfig::default();
|
let config = DeviceConfig::default();
|
||||||
let mut device = EskinDeviceInner::new(config, Box::new(transport));
|
let mut device = EskinDeviceInner::new(config, Box::new(transport));
|
||||||
device.open().unwrap();
|
device.open().unwrap();
|
||||||
@@ -15,6 +15,7 @@ fn main() {
|
|||||||
read_col(&mut device);
|
read_col(&mut device);
|
||||||
read_config(&mut device);
|
read_config(&mut device);
|
||||||
|
|
||||||
|
device.read_device_config2().unwrap();
|
||||||
device.close().unwrap();
|
device.close().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user