Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions libosdp/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@
//! are specified by OSDP specification. This module is responsible to handling
//! such commands though [`OsdpCommand`].

use crate::OsdpError;
use crate::OsdpStatusReport;
use alloc::vec::Vec;
use serde::{Deserialize, Serialize};

use super::ConvertEndian;

type Result<T> = core::result::Result<T, OsdpError>;

/// LED Colors as specified in OSDP for the on_color/off_color parameters.
#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum OsdpLedColor {
Expand All @@ -37,6 +40,9 @@ pub enum OsdpLedColor {

/// Cyan Color
Cyan,

/// Unknown/Unsupported Color
Unknown(u8),
}

impl From<u8> for OsdpLedColor {
Expand All @@ -49,7 +55,7 @@ impl From<u8> for OsdpLedColor {
libosdp_sys::osdp_led_color_e_OSDP_LED_COLOR_BLUE => OsdpLedColor::Blue,
libosdp_sys::osdp_led_color_e_OSDP_LED_COLOR_MAGENTA => OsdpLedColor::Magenta,
libosdp_sys::osdp_led_color_e_OSDP_LED_COLOR_CYAN => OsdpLedColor::Cyan,
_ => panic!("Invalid LED color code"),
cc => OsdpLedColor::Unknown(cc),
}
}
}
Expand All @@ -64,6 +70,7 @@ impl From<OsdpLedColor> for u8 {
OsdpLedColor::Blue => libosdp_sys::osdp_led_color_e_OSDP_LED_COLOR_BLUE as u8,
OsdpLedColor::Magenta => libosdp_sys::osdp_led_color_e_OSDP_LED_COLOR_MAGENTA as u8,
OsdpLedColor::Cyan => libosdp_sys::osdp_led_color_e_OSDP_LED_COLOR_CYAN as u8,
OsdpLedColor::Unknown(cc) => cc,
}
}
}
Expand Down Expand Up @@ -583,40 +590,43 @@ impl From<OsdpCommand> for libosdp_sys::osdp_cmd {
}
}

impl From<libosdp_sys::osdp_cmd> for OsdpCommand {
fn from(value: libosdp_sys::osdp_cmd) -> Self {
impl TryFrom<libosdp_sys::osdp_cmd> for OsdpCommand {
type Error = OsdpError;

fn try_from(value: libosdp_sys::osdp_cmd) -> Result<Self> {
match value.id {
libosdp_sys::osdp_cmd_e_OSDP_CMD_LED => {
OsdpCommand::Led(unsafe { value.__bindgen_anon_1.led.into() })
Ok(OsdpCommand::Led(unsafe { value.__bindgen_anon_1.led.into() }))
}
libosdp_sys::osdp_cmd_e_OSDP_CMD_BUZZER => {
OsdpCommand::Buzzer(unsafe { value.__bindgen_anon_1.buzzer.into() })
Ok(OsdpCommand::Buzzer(unsafe { value.__bindgen_anon_1.buzzer.into() }))
}
libosdp_sys::osdp_cmd_e_OSDP_CMD_TEXT => {
OsdpCommand::Text(unsafe { value.__bindgen_anon_1.text.into() })
Ok(OsdpCommand::Text(unsafe { value.__bindgen_anon_1.text.into() }))
}
libosdp_sys::osdp_cmd_e_OSDP_CMD_OUTPUT => {
OsdpCommand::Output(unsafe { value.__bindgen_anon_1.output.into() })
Ok(OsdpCommand::Output(unsafe { value.__bindgen_anon_1.output.into() }))
}
libosdp_sys::osdp_cmd_e_OSDP_CMD_COMSET => {
OsdpCommand::ComSet(unsafe { value.__bindgen_anon_1.comset.into() })
Ok(OsdpCommand::ComSet(unsafe { value.__bindgen_anon_1.comset.into() }))
}
libosdp_sys::osdp_cmd_e_OSDP_CMD_COMSET_DONE => {
OsdpCommand::ComSetDone(unsafe { value.__bindgen_anon_1.comset.into() })
Ok(OsdpCommand::ComSetDone(unsafe { value.__bindgen_anon_1.comset.into() }))
}
libosdp_sys::osdp_cmd_e_OSDP_CMD_KEYSET => {
OsdpCommand::KeySet(unsafe { value.__bindgen_anon_1.keyset.into() })
Ok(OsdpCommand::KeySet(unsafe { value.__bindgen_anon_1.keyset.into() }))
}
libosdp_sys::osdp_cmd_e_OSDP_CMD_MFG => {
OsdpCommand::Mfg(unsafe { value.__bindgen_anon_1.mfg.into() })
Ok(OsdpCommand::Mfg(unsafe { value.__bindgen_anon_1.mfg.into() }))
}
libosdp_sys::osdp_cmd_e_OSDP_CMD_FILE_TX => {
OsdpCommand::FileTx(unsafe { value.__bindgen_anon_1.file_tx.into() })
Ok(OsdpCommand::FileTx(unsafe { value.__bindgen_anon_1.file_tx.into() }))
}
libosdp_sys::osdp_cmd_e_OSDP_CMD_STATUS => {
OsdpCommand::Status(unsafe { value.__bindgen_anon_1.status.into() })
let data = unsafe { value.__bindgen_anon_1.status.try_into() }?;
Ok(OsdpCommand::Status(data))
}
_ => panic!("Unknown event"),
_ => Err(OsdpError::Parse("Unknown event".into())),
}
}
}
Expand Down
12 changes: 8 additions & 4 deletions libosdp/src/cp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,13 @@ extern "C" fn trampoline<F>(data: *mut c_void, pd: i32, event: *mut libosdp_sys:
where
F: FnMut(i32, OsdpEvent) -> i32,
{
let event: OsdpEvent = unsafe { (*event).into() };
let callback: &mut F = unsafe { &mut *(data as *mut F) };
callback(pd, event)
match unsafe { (*event).try_into() } {
Ok(event) => {
let callback: &mut F = unsafe { &mut *(data as *mut F) };
callback(pd, event)
},
Err(_) => -1, // Failed to parse the event data -> Send NAK
}
}

type EventCallback =
Expand Down Expand Up @@ -178,7 +182,7 @@ impl ControlPanel {
if rc < 0 {
Err(OsdpError::Query("capability"))
} else {
Ok(cap.into())
Ok(cap.try_into()?)
}
}

Expand Down
83 changes: 47 additions & 36 deletions libosdp/src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//! module is responsible to handling such events though [`OsdpEvent`].

use crate::OsdpError;
use alloc::vec::Vec;
use alloc::{vec::Vec, format};
use serde::{Deserialize, Serialize};

use super::ConvertEndian;
Expand All @@ -32,16 +32,18 @@ pub enum OsdpCardFormats {
Wiegand,
}

impl From<libosdp_sys::osdp_event_cardread_format_e> for OsdpCardFormats {
fn from(value: libosdp_sys::osdp_event_cardread_format_e) -> Self {
impl TryFrom<libosdp_sys::osdp_event_cardread_format_e> for OsdpCardFormats {
type Error = OsdpError;

fn try_from(value: libosdp_sys::osdp_event_cardread_format_e) -> Result<Self> {
match value {
libosdp_sys::osdp_event_cardread_format_e_OSDP_CARD_FMT_RAW_UNSPECIFIED => {
OsdpCardFormats::Unspecified
Ok(OsdpCardFormats::Unspecified)
}
libosdp_sys::osdp_event_cardread_format_e_OSDP_CARD_FMT_RAW_WIEGAND => {
OsdpCardFormats::Wiegand
Ok(OsdpCardFormats::Wiegand)
}
_ => panic!("Unknown osdp card format"),
cf => Err(OsdpError::Parse(format!("Unknown card format ({cf})").into())),
}
}
}
Expand Down Expand Up @@ -117,20 +119,21 @@ impl OsdpEventCardRead {
}
}

impl From<libosdp_sys::osdp_event_cardread> for OsdpEventCardRead {
fn from(value: libosdp_sys::osdp_event_cardread) -> Self {
let direction = value.direction == 1;
let format = value.format.into();
impl TryFrom<libosdp_sys::osdp_event_cardread> for OsdpEventCardRead {
type Error = OsdpError;

fn try_from(value: libosdp_sys::osdp_event_cardread) -> Result<Self> {
let format = value.format.try_into()?;
let len = value.length as usize;
let (nr_bits, nr_bytes) = (len, len.div_ceil(8));
let data = value.data[0..nr_bytes].to_vec();
OsdpEventCardRead {

Ok(OsdpEventCardRead {
reader_no: value.reader_no,
format,
direction,
direction: value.direction == 1,
nr_bits,
data,
}
data: value.data[0..nr_bytes].to_vec(),
})
}
}

Expand Down Expand Up @@ -245,22 +248,24 @@ pub enum OsdpStatusReportType {
Local,
}

impl From<libosdp_sys::osdp_status_report_type> for OsdpStatusReportType {
fn from(value: libosdp_sys::osdp_status_report_type) -> Self {
impl TryFrom<libosdp_sys::osdp_status_report_type> for OsdpStatusReportType {
type Error = OsdpError;

fn try_from(value: libosdp_sys::osdp_status_report_type) -> Result<Self> {
match value {
libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_INPUT => {
OsdpStatusReportType::Input
Ok(OsdpStatusReportType::Input)
}
libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_OUTPUT => {
OsdpStatusReportType::Output
Ok(OsdpStatusReportType::Output)
}
libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_REMOTE => {
OsdpStatusReportType::Remote
Ok(OsdpStatusReportType::Remote)
}
libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_LOCAL => {
OsdpStatusReportType::Local
Ok(OsdpStatusReportType::Local)
}
_ => panic!("Invalid enum entry"),
rt => Err(OsdpError::Parse(format!("Unknown report type ({rt})").into())),
}
}
}
Expand Down Expand Up @@ -304,13 +309,15 @@ pub struct OsdpStatusReport {
pub report: [u8; 64],
}

impl From<libosdp_sys::osdp_status_report> for OsdpStatusReport {
fn from(value: libosdp_sys::osdp_status_report) -> Self {
OsdpStatusReport {
type_: value.type_.into(),
impl TryFrom<libosdp_sys::osdp_status_report> for OsdpStatusReport {
type Error = OsdpError;

fn try_from(value: libosdp_sys::osdp_status_report) -> Result<Self> {
Ok(OsdpStatusReport {
type_: value.type_.try_into()?,
nr_entries: value.nr_entries as usize,
report: value.report,
}
})
}
}

Expand Down Expand Up @@ -377,22 +384,26 @@ impl From<OsdpEvent> for libosdp_sys::osdp_event {
}
}

impl From<libosdp_sys::osdp_event> for OsdpEvent {
fn from(value: libosdp_sys::osdp_event) -> Self {
impl TryFrom<libosdp_sys::osdp_event> for OsdpEvent {
type Error = OsdpError;

fn try_from(value: libosdp_sys::osdp_event) -> Result<Self> {
match value.type_ {
libosdp_sys::osdp_event_type_OSDP_EVENT_CARDREAD => {
OsdpEvent::CardRead(unsafe { value.__bindgen_anon_1.cardread.into() })
let data = unsafe { value.__bindgen_anon_1.cardread.try_into() }?;
Ok(OsdpEvent::CardRead(data))
}
libosdp_sys::osdp_event_type_OSDP_EVENT_KEYPRESS => {
OsdpEvent::KeyPress(unsafe { value.__bindgen_anon_1.keypress.into() })
Ok(OsdpEvent::KeyPress(unsafe { value.__bindgen_anon_1.keypress.into() }))
}
libosdp_sys::osdp_event_type_OSDP_EVENT_MFGREP => {
OsdpEvent::MfgReply(unsafe { value.__bindgen_anon_1.mfgrep.into() })
Ok(OsdpEvent::MfgReply(unsafe { value.__bindgen_anon_1.mfgrep.into() }))
}
libosdp_sys::osdp_event_type_OSDP_EVENT_STATUS => {
OsdpEvent::Status(unsafe { value.__bindgen_anon_1.status.into() })
let data = unsafe { value.__bindgen_anon_1.status.try_into() }?;
Ok(OsdpEvent::Status(data))
}
_ => panic!("Unknown event"),
et => Err(OsdpError::Parse(format!("Unknown event ({et})").into())),
}
}
}
Expand All @@ -419,7 +430,7 @@ mod tests {
assert_eq!(event_struct.data[0], 0x55);
assert_eq!(event_struct.data[1], 0xAA);

assert_eq!(event, event_struct.into());
assert_eq!(event, event_struct.try_into().unwrap());

let event = OsdpEventCardRead::new_wiegand(15, vec![0x55, 0xAA]).unwrap();
let event_struct: osdp_event_cardread = event.clone().into();
Expand All @@ -433,6 +444,6 @@ mod tests {
assert_eq!(event_struct.data[0], 0x55);
assert_eq!(event_struct.data[1], 0xAA);

assert_eq!(event, event_struct.into());
assert_eq!(event, event_struct.try_into().unwrap());
}
}
17 changes: 10 additions & 7 deletions libosdp/src/pd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,17 @@ extern "C" fn trampoline<F>(data_ptr: *mut c_void, cmd_ptr: *mut libosdp_sys::os
where
F: FnMut(&mut OsdpCommand) -> i32,
{
let mut cmd: OsdpCommand = unsafe { cmd_ptr.read().into() };
let callback: &mut F = unsafe { &mut *(data_ptr as *mut F) };
let res = callback(&mut cmd);
// TODO: Free data_ptr's box?
unsafe {
cmd_ptr.write(cmd.into());
match unsafe { cmd_ptr.read().try_into() } {
Ok(mut cmd) => {
let callback: &mut F = unsafe { &mut *(data_ptr as *mut F) };
let res = callback(&mut cmd);
unsafe {
cmd_ptr.write(cmd.into());
}
res
},
Err(_) => -1, // Failed to parse the command data -> Send NAK
}
res
}

fn get_trampoline<F>(_closure: &F) -> CommandCallback
Expand Down
11 changes: 10 additions & 1 deletion libosdp/src/pdcap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ pub enum PdCapability {
/// 1 - IEC 60839-11-5
/// 2 - SIA OSDP 2.2
OsdpVersion(PdCapEntity),

/// Unknown/Unsupported capability
Unknown(u8, PdCapEntity),
}

#[rustfmt::skip]
Expand Down Expand Up @@ -267,7 +270,7 @@ impl From<libosdp_sys::osdp_pd_cap> for PdCapability {
libosdp_sys::osdp_pd_cap_function_code_e_OSDP_PD_CAP_OSDP_VERSION => {
PdCapability::OsdpVersion(e)
}
_ => panic!("Unknown function code"),
fc => PdCapability::Unknown(fc, e)
}
}
}
Expand Down Expand Up @@ -324,6 +327,7 @@ impl From<PdCapability> for u8 {
PdCapability::OsdpVersion(_) => {
libosdp_sys::osdp_pd_cap_function_code_e_OSDP_PD_CAP_OSDP_VERSION as u8
}
PdCapability::Unknown(fc, _) => fc
}
}
}
Expand Down Expand Up @@ -412,6 +416,11 @@ impl From<PdCapability> for libosdp_sys::osdp_pd_cap {
compliance_level: e.compliance,
num_items: e.num_items,
},
PdCapability::Unknown(_, e) => libosdp_sys::osdp_pd_cap {
function_code,
compliance_level: e.compliance,
num_items: e.num_items,
},
}
}
}