owa4x 0.4.15

Idiomatic wrapper around the owa4x-sys crate
Documentation
use crate::owa_error::OwaError;
use std::ffi::c_void;

#[cfg(any(
    target_arch = "x86_64",
    all(target_arch = "aarch64", target_os = "macos")
))]
use crate::sys_stub as owa;
#[cfg(target_arch = "arm")]
use owa4x_sys as owa;
#[cfg(all(target_arch = "aarch64", not(target_os = "macos")))]
use owa5x_sys as owa;

#[derive(Debug, serde::Serialize, Default)]
pub enum NetworkRegistration {
    #[default]
    NoNetwork,
    Registered,
    RegisteredButRoaming,
    SosOnly,
}

pub struct Gprs {
    pub signal_strength: u8,
}

impl Gprs {
    pub fn initialize() -> Result<Self, OwaError> {
        let mut is_active = 0;
        unsafe {
            owa::GSM_IsActive(&mut is_active);
        }
        debug!("GSM active: {:?}", is_active);
        let mut gsm_config = owa::TGSM_MODULE_CONFIGURATION::default();
        let gsm_ptr: *mut c_void = &mut gsm_config as *mut _ as *mut c_void;
        unsafe {
            let err = owa::GSM_Initialize(gsm_ptr) as u32;
            debug!("GSM Initialize returned: {:?}", err);
            if err != owa::NO_ERROR {
                let _e = owa::GSM_Finalize();
                return Err(OwaError::from_or_unknown(err));
            }
            debug!("Starting GSM");
            let err = owa::GSM_Start() as u32;
            debug!("GSM_Start returned: {:?}", err);
            if err != owa::NO_ERROR {
                let e = owa::GSM_Finalize();
                debug!("GSM_Finalize: {:?}", e);
                return Err(OwaError::from_or_unknown(err));
            }
        }
        debug!("Returning gprs");
        Ok(Gprs { signal_strength: 0 })
    }

    pub fn get_is_active(&self) -> Result<bool, OwaError> {
        let mut s: u8 = 255;
        let res = unsafe { owa::GSM_GetSignalStrength(&mut s) as u32 };
        if res != owa::NO_ERROR {
            return Err(OwaError::from_or_unknown(res));
        }
        Ok(s != 0)
    }

    pub fn get_signal_strength(&self) -> Result<u8, OwaError> {
        let mut s: u8 = 255;
        let res = unsafe { owa::GSM_GetSignalStrength(&mut s) as u32 };
        if res != owa::NO_ERROR {
            return Err(OwaError::from_or_unknown(res));
        }
        Ok(s)
    }

    pub fn get_signal_quality(&self) -> Result<u8, OwaError> {
        let mut s: u8 = 255;
        let res = unsafe { owa::GSM_GetSignalQuality(&mut s) as u32 };
        if res != owa::NO_ERROR {
            return Err(OwaError::from_or_unknown(res));
        }
        Ok(s)
    }

    pub fn get_network_status(&self) -> Result<NetworkRegistration, OwaError> {
        let mut s: u8 = 255;
        let res = unsafe { owa::GSM_GetSignalQuality(&mut s) as u32 };
        if res != owa::NO_ERROR {
            return Err(OwaError::from_or_unknown(res));
        }
        match s {
            0 => Ok(NetworkRegistration::NoNetwork),
            1 => Ok(NetworkRegistration::Registered),
            2 => Ok(NetworkRegistration::RegisteredButRoaming),
            3 => Ok(NetworkRegistration::SosOnly),
            _ => Err(OwaError::UnknownError),
        }
    }

    pub fn get_imei(&self) -> Result<String, OwaError> {
        let mut buffer = vec![0u8; 16];
        let res = unsafe { owa::GSM_GetIMEI(buffer.as_mut_ptr(), 15) as u32 };
        if res != owa::NO_ERROR {
            return Err(OwaError::from_or_unknown(res));
        }
        let read_length = buffer.iter().position(|&b| b == 0);
        if read_length.is_none() {
            return Err(OwaError::ParseError);
        }
        buffer.truncate(read_length.unwrap());
        let s = std::ffi::CString::new(buffer)
            .unwrap()
            .into_string()
            .unwrap();

        Ok(s)
    }
}