1use crate::OsdpError;
12use alloc::vec::Vec;
13use serde::{Deserialize, Serialize};
14
15use super::ConvertEndian;
16
17type Result<T> = core::result::Result<T, OsdpError>;
18
19#[cfg(feature = "defmt-03")]
20use defmt::panic;
21
22#[derive(Clone, Copy, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
25#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
26pub enum OsdpCardFormats {
27 #[default]
29 Unspecified,
30
31 Wiegand,
33}
34
35impl From<libosdp_sys::osdp_event_cardread_format_e> for OsdpCardFormats {
36 fn from(value: libosdp_sys::osdp_event_cardread_format_e) -> Self {
37 match value {
38 libosdp_sys::osdp_event_cardread_format_e_OSDP_CARD_FMT_RAW_UNSPECIFIED => {
39 OsdpCardFormats::Unspecified
40 }
41 libosdp_sys::osdp_event_cardread_format_e_OSDP_CARD_FMT_RAW_WIEGAND => {
42 OsdpCardFormats::Wiegand
43 }
44 _ => panic!("Unknown osdp card format"),
45 }
46 }
47}
48
49impl From<OsdpCardFormats> for libosdp_sys::osdp_event_cardread_format_e {
50 fn from(val: OsdpCardFormats) -> Self {
51 match val {
52 OsdpCardFormats::Unspecified => {
53 libosdp_sys::osdp_event_cardread_format_e_OSDP_CARD_FMT_RAW_UNSPECIFIED
54 }
55 OsdpCardFormats::Wiegand => {
56 libosdp_sys::osdp_event_cardread_format_e_OSDP_CARD_FMT_RAW_WIEGAND
57 }
58 }
59 }
60}
61
62#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
64#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
65pub struct OsdpEventCardRead {
66 pub reader_no: i32,
73
74 pub format: OsdpCardFormats,
76
77 pub direction: bool,
83
84 pub nr_bits: usize,
88
89 pub data: Vec<u8>,
91}
92
93impl OsdpEventCardRead {
94 pub fn new_raw(data: Vec<u8>) -> Self {
96 Self {
97 reader_no: 0,
98 format: OsdpCardFormats::Unspecified,
99 direction: false,
100 nr_bits: data.len() * 8,
101 data,
102 }
103 }
104
105 pub fn new_wiegand(nr_bits: usize, data: Vec<u8>) -> Result<Self> {
107 if nr_bits > data.len() * 8 {
108 return Err(OsdpError::Command);
109 }
110 Ok(Self {
111 reader_no: 0,
112 format: OsdpCardFormats::Wiegand,
113 direction: false,
114 nr_bits,
115 data,
116 })
117 }
118}
119
120impl From<libosdp_sys::osdp_event_cardread> for OsdpEventCardRead {
121 fn from(value: libosdp_sys::osdp_event_cardread) -> Self {
122 let direction = value.direction == 1;
123 let format = value.format.into();
124 let len = value.length as usize;
125 let (nr_bits, nr_bytes) = (len, len.div_ceil(8));
126 let data = value.data[0..nr_bytes].to_vec();
127 OsdpEventCardRead {
128 reader_no: value.reader_no,
129 format,
130 direction,
131 nr_bits,
132 data,
133 }
134 }
135}
136
137impl From<OsdpEventCardRead> for libosdp_sys::osdp_event_cardread {
138 fn from(value: OsdpEventCardRead) -> Self {
139 let mut data = [0; libosdp_sys::OSDP_EVENT_CARDREAD_MAX_DATALEN as usize];
140 let length = value.nr_bits as i32;
141 data[..value.data.len()].copy_from_slice(&value.data[..]);
142 libosdp_sys::osdp_event_cardread {
143 reader_no: value.reader_no,
144 format: value.format.into(),
145 direction: value.direction as i32,
146 length,
147 data,
148 }
149 }
150}
151
152#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
154#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
155pub struct OsdpEventKeyPress {
156 pub reader_no: i32,
163
164 pub data: Vec<u8>,
166}
167
168impl OsdpEventKeyPress {
169 pub fn new(data: Vec<u8>) -> Self {
171 Self { reader_no: 0, data }
172 }
173}
174
175impl From<libosdp_sys::osdp_event_keypress> for OsdpEventKeyPress {
176 fn from(value: libosdp_sys::osdp_event_keypress) -> Self {
177 let n = value.length as usize;
178 let data = value.data[0..n].to_vec();
179 OsdpEventKeyPress {
180 reader_no: value.reader_no,
181 data,
182 }
183 }
184}
185
186impl From<OsdpEventKeyPress> for libosdp_sys::osdp_event_keypress {
187 fn from(value: OsdpEventKeyPress) -> Self {
188 let mut data = [0; libosdp_sys::OSDP_EVENT_KEYPRESS_MAX_DATALEN as usize];
189 data[..value.data.len()].copy_from_slice(&value.data[..]);
190 libosdp_sys::osdp_event_keypress {
191 reader_no: value.reader_no,
192 length: value.data.len() as i32,
193 data,
194 }
195 }
196}
197
198#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, Hash)]
200#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
201pub struct OsdpEventMfgReply {
202 pub vendor_code: (u8, u8, u8),
204
205 pub data: Vec<u8>,
207}
208
209impl From<libosdp_sys::osdp_event_mfgrep> for OsdpEventMfgReply {
210 fn from(value: libosdp_sys::osdp_event_mfgrep) -> Self {
211 let n = value.length as usize;
212 let data = value.data[0..n].to_vec();
213 let bytes = value.vendor_code.to_le_bytes();
214 let vendor_code: (u8, u8, u8) = (bytes[0], bytes[1], bytes[2]);
215 OsdpEventMfgReply {
216 vendor_code,
217 data,
218 }
219 }
220}
221
222impl From<OsdpEventMfgReply> for libosdp_sys::osdp_event_mfgrep {
223 fn from(value: OsdpEventMfgReply) -> Self {
224 let mut data = [0; libosdp_sys::OSDP_EVENT_MFGREP_MAX_DATALEN as usize];
225 data[..value.data.len()].copy_from_slice(&value.data[..]);
226 libosdp_sys::osdp_event_mfgrep {
227 vendor_code: value.vendor_code.as_le(),
228 length: value.data.len() as u8,
229 data,
230 }
231 }
232}
233
234#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
236#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
237pub enum OsdpStatusReportType {
238 Input,
240 Output,
242 Remote,
244 Local,
246}
247
248impl From<libosdp_sys::osdp_status_report_type> for OsdpStatusReportType {
249 fn from(value: libosdp_sys::osdp_status_report_type) -> Self {
250 match value {
251 libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_INPUT => {
252 OsdpStatusReportType::Input
253 }
254 libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_OUTPUT => {
255 OsdpStatusReportType::Output
256 }
257 libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_REMOTE => {
258 OsdpStatusReportType::Remote
259 }
260 libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_LOCAL => {
261 OsdpStatusReportType::Local
262 }
263 _ => panic!("Invalid enum entry"),
264 }
265 }
266}
267
268impl From<OsdpStatusReportType> for libosdp_sys::osdp_status_report_type {
269 fn from(value: OsdpStatusReportType) -> Self {
270 match value {
271 OsdpStatusReportType::Input => {
272 libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_INPUT
273 }
274 OsdpStatusReportType::Output => {
275 libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_OUTPUT
276 }
277 OsdpStatusReportType::Remote => {
278 libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_REMOTE
279 }
280 OsdpStatusReportType::Local => {
281 libosdp_sys::osdp_status_report_type_OSDP_STATUS_REPORT_LOCAL
282 }
283 }
284 }
285}
286
287#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, Hash)]
296#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
297pub struct OsdpStatusReport {
298 pub type_: OsdpStatusReportType,
300 pub nr_entries: usize,
302 #[serde(with = "serde_arrays")]
304 pub report: [u8; 64],
305}
306
307impl From<libosdp_sys::osdp_status_report> for OsdpStatusReport {
308 fn from(value: libosdp_sys::osdp_status_report) -> Self {
309 OsdpStatusReport {
310 type_: value.type_.into(),
311 nr_entries: value.nr_entries as usize,
312 report: value.report,
313 }
314 }
315}
316
317impl From<OsdpStatusReport> for libosdp_sys::osdp_status_report {
318 fn from(value: OsdpStatusReport) -> Self {
319 libosdp_sys::osdp_status_report {
320 type_: value.type_.into(),
321 nr_entries: value.nr_entries as i32,
322 report: value.report,
323 }
324 }
325}
326
327#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
332#[cfg_attr(feature = "defmt-03", derive(defmt::Format))]
333pub enum OsdpEvent {
334 CardRead(OsdpEventCardRead),
336
337 KeyPress(OsdpEventKeyPress),
339
340 MfgReply(OsdpEventMfgReply),
342
343 Status(OsdpStatusReport),
345}
346
347impl From<OsdpEvent> for libosdp_sys::osdp_event {
348 fn from(value: OsdpEvent) -> Self {
349 match value {
350 OsdpEvent::CardRead(e) => libosdp_sys::osdp_event {
351 type_: libosdp_sys::osdp_event_type_OSDP_EVENT_CARDREAD,
352 flags: 0,
353 __bindgen_anon_1: libosdp_sys::osdp_event__bindgen_ty_1 {
354 cardread: e.clone().into(),
355 },
356 },
357 OsdpEvent::KeyPress(e) => libosdp_sys::osdp_event {
358 type_: libosdp_sys::osdp_event_type_OSDP_EVENT_KEYPRESS,
359 flags: 0,
360 __bindgen_anon_1: libosdp_sys::osdp_event__bindgen_ty_1 {
361 keypress: e.clone().into(),
362 },
363 },
364 OsdpEvent::MfgReply(e) => libosdp_sys::osdp_event {
365 type_: libosdp_sys::osdp_event_type_OSDP_EVENT_MFGREP,
366 flags: 0,
367 __bindgen_anon_1: libosdp_sys::osdp_event__bindgen_ty_1 {
368 mfgrep: e.clone().into(),
369 },
370 },
371 OsdpEvent::Status(e) => libosdp_sys::osdp_event {
372 type_: libosdp_sys::osdp_event_type_OSDP_EVENT_STATUS,
373 flags: 0,
374 __bindgen_anon_1: libosdp_sys::osdp_event__bindgen_ty_1 { status: e.into() },
375 },
376 }
377 }
378}
379
380impl From<libosdp_sys::osdp_event> for OsdpEvent {
381 fn from(value: libosdp_sys::osdp_event) -> Self {
382 match value.type_ {
383 libosdp_sys::osdp_event_type_OSDP_EVENT_CARDREAD => {
384 OsdpEvent::CardRead(unsafe { value.__bindgen_anon_1.cardread.into() })
385 }
386 libosdp_sys::osdp_event_type_OSDP_EVENT_KEYPRESS => {
387 OsdpEvent::KeyPress(unsafe { value.__bindgen_anon_1.keypress.into() })
388 }
389 libosdp_sys::osdp_event_type_OSDP_EVENT_MFGREP => {
390 OsdpEvent::MfgReply(unsafe { value.__bindgen_anon_1.mfgrep.into() })
391 }
392 libosdp_sys::osdp_event_type_OSDP_EVENT_STATUS => {
393 OsdpEvent::Status(unsafe { value.__bindgen_anon_1.status.into() })
394 }
395 _ => panic!("Unknown event"),
396 }
397 }
398}
399
400#[cfg(test)]
401mod tests {
402 use super::OsdpEventCardRead;
403 use libosdp_sys::{
404 osdp_event_cardread, osdp_event_cardread_format_e_OSDP_CARD_FMT_RAW_UNSPECIFIED,
405 osdp_event_cardread_format_e_OSDP_CARD_FMT_RAW_WIEGAND,
406 };
407
408 #[test]
409 fn test_event_cardread() {
410 let event = OsdpEventCardRead::new_raw(vec![0x55, 0xAA]);
411 let event_struct: osdp_event_cardread = event.clone().into();
412
413 assert_eq!(event_struct.length, 2 * 8);
414 assert_eq!(event_struct.direction, 0);
415 assert_eq!(
416 event_struct.format,
417 osdp_event_cardread_format_e_OSDP_CARD_FMT_RAW_UNSPECIFIED
418 );
419 assert_eq!(event_struct.data[0], 0x55);
420 assert_eq!(event_struct.data[1], 0xAA);
421
422 assert_eq!(event, event_struct.into());
423
424 let event = OsdpEventCardRead::new_wiegand(15, vec![0x55, 0xAA]).unwrap();
425 let event_struct: osdp_event_cardread = event.clone().into();
426
427 assert_eq!(event_struct.length, 15);
428 assert_eq!(event_struct.direction, 0);
429 assert_eq!(
430 event_struct.format,
431 osdp_event_cardread_format_e_OSDP_CARD_FMT_RAW_WIEGAND
432 );
433 assert_eq!(event_struct.data[0], 0x55);
434 assert_eq!(event_struct.data[1], 0xAA);
435
436 assert_eq!(event, event_struct.into());
437 }
438}