use std::ffi::{c_char, c_int, c_void};
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum HalDtype {
U8 = 0,
I8 = 1,
U16 = 2,
I16 = 3,
U32 = 4,
I32 = 5,
U64 = 6,
I64 = 7,
F16 = 8,
F32 = 9,
F64 = 10,
}
pub const HAL_DMABUF_MAX_NDIM: usize = 8;
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct HalDmabufTensorInfo {
pub size: usize,
pub offset: usize,
pub shape: [usize; 8],
pub ndim: usize,
pub fd: c_int,
pub dtype: HalDtype,
}
impl Default for HalDmabufTensorInfo {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
const _: () = assert!(
std::mem::size_of::<[usize; 8]>() == std::mem::size_of::<[usize; HAL_DMABUF_MAX_NDIM]>()
);
#[cfg(target_pointer_width = "64")]
const _: () = assert!(std::mem::size_of::<HalDmabufTensorInfo>() == 96);
#[derive(Debug)]
pub struct HalDmaBufFunctions {
pub get_instance: unsafe extern "C" fn() -> *mut c_void,
pub is_supported: unsafe extern "C" fn(*mut c_void) -> c_int,
pub get_tensor_info:
unsafe extern "C" fn(*mut c_void, c_int, *mut HalDmabufTensorInfo, usize) -> c_int,
pub sync_for_device: unsafe extern "C" fn(*mut c_void, c_int) -> c_int,
pub sync_for_cpu: unsafe extern "C" fn(*mut c_void, c_int) -> c_int,
}
impl HalDmaBufFunctions {
#[must_use]
pub unsafe fn try_load(lib: &libloading::Library) -> Option<Self> {
unsafe {
Some(Self {
get_instance: *lib.get(b"hal_dmabuf_get_instance\0").ok()?,
is_supported: *lib.get(b"hal_dmabuf_is_supported\0").ok()?,
get_tensor_info: *lib.get(b"hal_dmabuf_get_tensor_info\0").ok()?,
sync_for_device: *lib.get(b"hal_dmabuf_sync_for_device\0").ok()?,
sync_for_cpu: *lib.get(b"hal_dmabuf_sync_for_cpu\0").ok()?,
})
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy)]
pub struct HalCameraAdaptorFormatInfo {
pub input_channels: c_int,
pub output_channels: c_int,
pub fourcc: [u8; 8],
}
impl Default for HalCameraAdaptorFormatInfo {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
#[derive(Debug)]
pub struct HalCameraAdaptorFunctions {
pub is_supported: unsafe extern "C" fn(*mut c_void, *const c_char) -> c_int,
pub get_format_info: unsafe extern "C" fn(
*mut c_void,
*const c_char,
*mut HalCameraAdaptorFormatInfo,
usize,
) -> c_int,
}
impl HalCameraAdaptorFunctions {
#[must_use]
pub unsafe fn try_load(lib: &libloading::Library) -> Option<Self> {
unsafe {
Some(Self {
is_supported: *lib.get(b"hal_camera_adaptor_is_supported\0").ok()?,
get_format_info: *lib.get(b"hal_camera_adaptor_get_format_info\0").ok()?,
})
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hal_dtype_discriminants() {
assert_eq!(HalDtype::U8 as u32, 0);
assert_eq!(HalDtype::I8 as u32, 1);
assert_eq!(HalDtype::U16 as u32, 2);
assert_eq!(HalDtype::I16 as u32, 3);
assert_eq!(HalDtype::U32 as u32, 4);
assert_eq!(HalDtype::I32 as u32, 5);
assert_eq!(HalDtype::U64 as u32, 6);
assert_eq!(HalDtype::I64 as u32, 7);
assert_eq!(HalDtype::F16 as u32, 8);
assert_eq!(HalDtype::F32 as u32, 9);
assert_eq!(HalDtype::F64 as u32, 10);
}
#[test]
fn tensor_info_default_is_zeroed() {
let info = HalDmabufTensorInfo::default();
assert_eq!(info.size, 0);
assert_eq!(info.offset, 0);
assert_eq!(info.ndim, 0);
assert_eq!(info.fd, 0);
assert!(info.shape.iter().all(|&s| s == 0));
}
#[test]
fn hal_dmabuf_max_ndim() {
assert_eq!(HAL_DMABUF_MAX_NDIM, 8);
}
#[test]
fn camera_adaptor_format_info_default_is_zeroed() {
let info = HalCameraAdaptorFormatInfo::default();
assert_eq!(info.input_channels, 0);
assert_eq!(info.output_channels, 0);
assert!(info.fourcc.iter().all(|&b| b == 0));
}
#[test]
fn camera_adaptor_format_info_clone_copy() {
let mut info = HalCameraAdaptorFormatInfo {
input_channels: 4,
output_channels: 3,
..Default::default()
};
info.fourcc[..4].copy_from_slice(b"RGBA");
let copied = info;
assert_eq!(copied.input_channels, 4);
assert_eq!(copied.output_channels, 3);
assert_eq!(&copied.fourcc[..4], b"RGBA");
}
#[test]
fn camera_adaptor_format_info_debug() {
let info = HalCameraAdaptorFormatInfo::default();
let debug = format!("{info:?}");
assert!(debug.contains("HalCameraAdaptorFormatInfo"));
assert!(debug.contains("input_channels"));
}
}