#![cfg_attr(not(feature = "std"), no_std)]
#![warn(missing_debug_implementations)]
#![warn(rust_2018_idioms)]
#![warn(missing_docs)]
extern crate alloc;
mod channel;
mod commands;
mod cp;
mod events;
mod file;
mod pd;
mod pdcap;
mod pdid;
mod pdinfo;
pub use channel::*;
pub use commands::*;
pub use events::*;
pub use file::*;
pub use pdcap::*;
pub use pdid::*;
pub use pdinfo::*;
#[allow(unused_imports)]
use alloc::{borrow::ToOwned, boxed::Box, format, string::String};
#[cfg(feature = "std")]
use thiserror::Error;
pub use cp::{ControlPanel, ControlPanelBuilder};
pub use pd::PeripheralDevice;
#[derive(Debug, Default)]
#[cfg_attr(feature = "std", derive(Error))]
pub enum OsdpError {
#[cfg_attr(feature = "std", error("Invalid PdInfo {0}"))]
PdInfo(&'static str),
#[cfg_attr(feature = "std", error("Invalid OsdpCommand"))]
Command,
#[cfg_attr(feature = "std", error("Invalid OsdpEvent"))]
Event,
#[cfg_attr(feature = "std", error("Failed to query {0} from device"))]
Query(&'static str),
#[cfg_attr(feature = "std", error("File transfer failed: {0}"))]
FileTransfer(&'static str),
#[cfg_attr(feature = "std", error("Failed to setup device"))]
Setup,
#[cfg_attr(feature = "std", error("Type {0} parse error"))]
Parse(String),
#[cfg_attr(feature = "std", error("Channel error: {0}"))]
Channel(&'static str),
#[cfg_attr(feature = "std", error("PD info build error: {0}"))]
PdInfoBuilder(&'static str),
#[cfg(feature = "std")]
#[error("IO Error")]
IO(#[from] std::io::Error),
#[cfg(not(feature = "std"))]
IO(Box<dyn embedded_io::Error>),
#[default]
#[cfg_attr(feature = "std", error("Unknown/Unspecified error"))]
Unknown,
}
#[cfg(feature = "defmt-03")]
impl defmt::Format for OsdpError {
fn format(&self, f: defmt::Formatter<'_>) {
match self {
OsdpError::PdInfo(e) => defmt::write!(f, "OsdpError::PdInfo({0})", e),
OsdpError::Command => defmt::write!(f, "OsdpError::Command"),
OsdpError::Event => defmt::write!(f, "OsdpError::Event"),
OsdpError::Query(e) => defmt::write!(f, "OsdpError::Query({0})", e),
OsdpError::FileTransfer(e) => defmt::write!(f, "OsdpError::FileTransfer({0})", e),
OsdpError::Setup => defmt::write!(f, "OsdpError::Setup"),
OsdpError::Parse(e) => defmt::write!(f, "OsdpError::Parse({0})", e.as_str()),
OsdpError::Channel(e) => defmt::write!(f, "OsdpError::Channel({0})", e),
OsdpError::PdInfoBuilder(e) => defmt::write!(f, "OsdpError::PdInfoBuilder({0})", e),
OsdpError::IO(_) => defmt::write!(f, "OsdpError::IO"), OsdpError::Unknown => defmt::write!(f, "OsdpError::Unknown"),
}
}
}
impl From<core::convert::Infallible> for OsdpError {
fn from(_: core::convert::Infallible) -> Self {
unreachable!()
}
}
impl From<ChannelError> for OsdpError {
fn from(value: ChannelError) -> OsdpError {
match value {
ChannelError::WouldBlock => OsdpError::Channel("WouldBlock"),
ChannelError::TransportError => OsdpError::Channel("TransportError"),
}
}
}
pub trait ConvertEndian {
fn as_be(&self) -> u32;
fn as_le(&self) -> u32;
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct OsdpFlag: u32 {
const EnforceSecure = libosdp_sys::OSDP_FLAG_ENFORCE_SECURE;
const InstallMode = libosdp_sys::OSDP_FLAG_INSTALL_MODE;
const IgnoreUnsolicited = libosdp_sys::OSDP_FLAG_IGN_UNSOLICITED;
}
}
impl core::str::FromStr for OsdpFlag {
type Err = OsdpError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"EnforceSecure" => Ok(OsdpFlag::EnforceSecure),
"InstallMode" => Ok(OsdpFlag::InstallMode),
"IgnoreUnsolicited" => Ok(OsdpFlag::IgnoreUnsolicited),
_ => Err(OsdpError::Parse(format!("OsdpFlag: {s}"))),
}
}
}
#[allow(dead_code)]
fn cstr_to_string(s: *const ::core::ffi::c_char) -> String {
let s = unsafe { core::ffi::CStr::from_ptr(s) };
s.to_str().unwrap().to_owned()
}
pub fn get_version() -> &'static str {
let s = unsafe { libosdp_sys::osdp_get_version() };
let s = unsafe { core::ffi::CStr::from_ptr(s) };
s.to_str().unwrap()
}
pub fn get_source_info() -> &'static str {
let s = unsafe { libosdp_sys::osdp_get_source_info() };
let s = unsafe { core::ffi::CStr::from_ptr(s) };
s.to_str().unwrap()
}