use super::{
Error, OperationType, Result, gpiod,
line::{Offset, Settings, SettingsMap, Value},
};
#[derive(Debug, Eq, PartialEq)]
pub struct Config {
pub(crate) config: *mut gpiod::gpiod_line_config,
}
unsafe impl Send for Config {}
impl Config {
pub fn new() -> Result<Self> {
let config = unsafe { gpiod::gpiod_line_config_new() };
if config.is_null() {
return Err(Error::OperationFailed(
OperationType::LineConfigNew,
errno::errno(),
));
}
Ok(Self { config })
}
pub fn reset(&mut self) {
unsafe { gpiod::gpiod_line_config_reset(self.config) }
}
pub fn add_line_settings(
&mut self,
offsets: &[Offset],
settings: Settings,
) -> Result<&mut Self> {
let ret = unsafe {
gpiod::gpiod_line_config_add_line_settings(
self.config,
offsets.as_ptr(),
offsets.len(),
settings.settings,
)
};
if ret == -1 {
Err(Error::OperationFailed(
OperationType::LineConfigAddSettings,
errno::errno(),
))
} else {
Ok(self)
}
}
pub fn set_output_values(&mut self, values: &[Value]) -> Result<&mut Self> {
let mut mapped_values = Vec::new();
for value in values {
mapped_values.push(value.value());
}
let ret = unsafe {
gpiod::gpiod_line_config_set_output_values(
self.config,
mapped_values.as_ptr(),
values.len(),
)
};
if ret == -1 {
Err(Error::OperationFailed(
OperationType::LineConfigSetOutputValues,
errno::errno(),
))
} else {
Ok(self)
}
}
pub fn line_settings(&self) -> Result<SettingsMap> {
let mut map = SettingsMap::new();
let num_lines = unsafe { gpiod::gpiod_line_config_get_num_configured_offsets(self.config) };
let mut offsets = vec![0; num_lines];
let num_stored = unsafe {
gpiod::gpiod_line_config_get_configured_offsets(
self.config,
offsets.as_mut_ptr(),
num_lines,
)
};
for offset in &offsets[0..num_stored] {
let settings =
unsafe { gpiod::gpiod_line_config_get_line_settings(self.config, *offset) };
if settings.is_null() {
return Err(Error::OperationFailed(
OperationType::LineConfigGetSettings,
errno::errno(),
));
}
let settings = unsafe { Settings::from_raw(settings) };
map.insert(*offset as Offset, settings);
}
Ok(map)
}
}
impl Drop for Config {
fn drop(&mut self) {
unsafe { gpiod::gpiod_line_config_free(self.config) }
}
}