secugen_rs 0.2.0

Rust bindings for the SecuGen SDK
Documentation
use std::{ffi::c_void, mem::MaybeUninit};

use crate::{
    CreateSGFPMObject, SGDeviceInfoParam, SGFDxDeviceName_SG_DEV_AUTO,
    SGFDxErrorCode_SGFDX_ERROR_NONE, SGFDxErrorCode_SGFDX_ERROR_WRONG_IMAGE,
    SGFPM_EnableCheckOfFingerLiveness, SGFPM_EnableSmartCapture, SGFPM_GetDeviceInfo,
    SGFPM_GetImage, SGFPM_GetMatchingScore, SGFPM_Init, SGFPM_MatchTemplate, SGFPM_OpenDevice,
    SGFPM_SetBrightness, SGFPM_SetFakeDetectionLevel, SGFPM,SGFPM_Terminate,SGFPM_CloseDevice
};

#[derive(Debug, Clone, Copy)]
#[cfg(target_os = "linux")]
pub struct DeviceInfo {
    pub image_width: u64,
    pub image_height: u64,
    pub com_speed: u64,
    pub com_port: u64,
}

#[derive(Debug, Clone, Copy)]
#[cfg(target_os = "windows")]
pub struct DeviceInfo {
    pub image_width: u32,
    pub image_height: u32,
    pub com_speed: u32,
    pub com_port: u32,
}

#[derive(Debug)]

pub struct FPM {
    sgfpm: *mut SGFPM,
    pub device_info: Option<DeviceInfo>,
}

impl Drop for FPM {
    fn drop(&mut self) {
        unsafe {
            SGFPM_CloseDevice(self.sgfpm as *mut c_void);
            SGFPM_Terminate(self.sgfpm as *mut c_void);
        }
    }
}

impl FPM {
    pub fn new() -> Self {
        Self {
            sgfpm: std::ptr::null_mut(),
            device_info: None,
        }
    }

    pub fn capture_image(&mut self) -> Result<Vec<u8>, String> {
        if let Some(device_info) = self.device_info {
            let buffer_size = (device_info.image_width * device_info.image_height) as usize;
            let mut buffer = vec![0xCCu8; buffer_size];

            let err = unsafe { SGFPM_GetImage(self.sgfpm as *mut c_void, buffer.as_mut_ptr()) };

            if err != SGFDxErrorCode_SGFDX_ERROR_NONE.try_into().unwrap() {
                if err != SGFDxErrorCode_SGFDX_ERROR_WRONG_IMAGE.try_into().unwrap() {
                    return Err(format!("GetImage(): Failed : ErrorCode = {}", err));
                }
            }

            return Ok(buffer);
        } else {
            return Err("Device not initialized".to_string());
        }
    }

    pub fn match_template(
        &mut self,
        mut min_template_1: Vec<u8>,
        mut min_template_2: Vec<u8>,
        secu_level: u32,
    ) -> Result<bool, String> {
        let mut matched = 0;

        unsafe {
            let err = SGFPM_MatchTemplate(
                self.sgfpm as *mut c_void,
                min_template_1.as_mut_ptr(),
                min_template_2.as_mut_ptr(),
                secu_level.try_into().unwrap(),
                &mut matched as *mut i32,
            );

            if err != SGFDxErrorCode_SGFDX_ERROR_NONE.try_into().unwrap() {
                return Err(format!("MatchTemplate(): Failed : ErrorCode = {}", err));
            }
        }

        Ok(matched == 1)
    }

    pub fn get_matching_score(
        &mut self,
        mut min_template_1: Vec<u8>,
        mut min_template_2: Vec<u8>,
    ) -> Result<u64, String> {
        #[cfg(target_os = "linux")]
        let mut score: u64 = 0;
    
        #[cfg(target_os = "windows")]
        let mut score: u32 = 0;
    
        #[cfg(target_os = "linux")]
        let score_ptr = &mut score as *mut u64;
    
        #[cfg(target_os = "windows")]
        let score_ptr = &mut score as *mut u32;

        unsafe {
            let err = SGFPM_GetMatchingScore(
                self.sgfpm as *mut c_void,
                min_template_1.as_mut_ptr(),
                min_template_2.as_mut_ptr(),
                score_ptr,
            );

            if err != SGFDxErrorCode_SGFDX_ERROR_NONE.try_into().unwrap() {
                return Err(format!("MatchTemplate(): Failed : ErrorCode = {}", err));
            }
        }

        Ok(score.try_into().unwrap())
    }

    pub fn init_device(
        &mut self,
        brightness: Option<u64>,
        fake_detection_level: Option<i32>,
        smart_capture: Option<bool>,
        check_finger_liveness: Option<i32>,
    ) -> Result<bool, String> {
        let mut sgfpm = MaybeUninit::uninit();

        unsafe {
            CreateSGFPMObject(sgfpm.as_mut_ptr());
        }

        self.sgfpm = unsafe { sgfpm.assume_init() };

        if self.sgfpm.is_null() {
            return Err("Failed to create SGFPM object".to_string());
        }

        unsafe {
            let err = SGFPM_Init(
                self.sgfpm as *mut c_void,
                SGFDxDeviceName_SG_DEV_AUTO.try_into().unwrap(),
            );

            if err != SGFDxErrorCode_SGFDX_ERROR_NONE.try_into().unwrap() {
                return Err(format!("Init: Failed : ErrorCode = {}", err));
            }

            let err = SGFPM_OpenDevice(self.sgfpm as *mut c_void, 0);

            if err != SGFDxErrorCode_SGFDX_ERROR_NONE.try_into().unwrap() {
                return Err(format!("OpenDevice: Failed : ErrorCode = {}", err));
            }

            if let Some(v) = brightness {
                SGFPM_SetBrightness(self.sgfpm as *mut c_void, v.try_into().unwrap());
            } else {
                SGFPM_SetBrightness(self.sgfpm as *mut c_void, 50);
            }

            if let Some(v) = fake_detection_level {
                SGFPM_SetFakeDetectionLevel(self.sgfpm as *mut c_void, v);
            }

            if let Some(v) = smart_capture {
                SGFPM_EnableSmartCapture(self.sgfpm as *mut c_void, v);
            }

            if let Some(v) = check_finger_liveness {
                SGFPM_EnableCheckOfFingerLiveness(self.sgfpm as *mut c_void, v);
            }

            let mut p_info: MaybeUninit<SGDeviceInfoParam> = MaybeUninit::uninit();
            let err = SGFPM_GetDeviceInfo(self.sgfpm as *mut c_void, p_info.as_mut_ptr());

            if err != SGFDxErrorCode_SGFDX_ERROR_NONE.try_into().unwrap() {
                return Err(format!("GetDeviceInfo: Failed : ErrorCode = {}", err));
            }

            let p_info = p_info.assume_init();

            let device_info = DeviceInfo {
                image_width: p_info.ImageWidth,
                image_height: p_info.ImageHeight,
                com_speed: p_info.ComSpeed,
                com_port: p_info.ComPort,
            };

            self.device_info = Some(device_info);

            Ok(true)
        }
    }

    pub fn close_device(&mut self) -> Result<bool, String> {
        unsafe {
            let err = SGFPM_CloseDevice(self.sgfpm as *mut c_void);

            if err != SGFDxErrorCode_SGFDX_ERROR_NONE.try_into().unwrap() {
                return Err(format!("CloseDevice: Failed : ErrorCode = {}", err));
            }

            Ok(true)
        }
    }
}