1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use crate::{
bindings,
error::{get_errno, Error},
prelude::DataSource,
};
#[derive(Debug)]
pub struct AdiDigitalInput {
port: u8,
expander_port: u8,
}
impl AdiDigitalInput {
pub unsafe fn new(port: u8, expander_port: u8) -> Result<Self, AdiDigitalInputError> {
match bindings::ext_adi_port_set_config(
expander_port,
port,
bindings::adi_port_config_e_E_ADI_DIGITAL_IN,
) {
bindings::PROS_ERR_ => Err(AdiDigitalInputError::from_errno()),
_ => Ok(Self {
port,
expander_port,
}),
}
}
pub fn read(&self) -> Result<bool, AdiDigitalInputError> {
match unsafe { bindings::ext_adi_digital_read(self.expander_port, self.port) } {
bindings::PROS_ERR_ => Err(AdiDigitalInputError::from_errno()),
0 => Ok(false),
_ => Ok(true),
}
}
}
impl DataSource for AdiDigitalInput {
type Data = bool;
type Error = AdiDigitalInputError;
fn read(&self) -> Result<Self::Data, Self::Error> {
self.read()
}
}
#[derive(Debug)]
pub enum AdiDigitalInputError {
PortsOutOfRange,
PortsNotDigitalInput,
Unknown(i32),
}
impl AdiDigitalInputError {
fn from_errno() -> Self {
match get_errno() {
libc::ENXIO => Self::PortsOutOfRange,
libc::EADDRINUSE => Self::PortsNotDigitalInput,
x => Self::Unknown(x),
}
}
}
impl From<AdiDigitalInputError> for Error {
fn from(err: AdiDigitalInputError) -> Self {
match err {
AdiDigitalInputError::PortsOutOfRange => Error::Custom("port is out of range".into()),
AdiDigitalInputError::PortsNotDigitalInput => {
Error::Custom("port is not an ADI digital input".into())
}
AdiDigitalInputError::Unknown(n) => Error::System(n),
}
}
}