| // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause |
| // SPDX-FileCopyrightText: 2022 Linaro Ltd. |
| // SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org> |
| |
| use std::ffi::{CStr, CString}; |
| use std::os::raw::c_char; |
| use std::str; |
| |
| use super::{gpiod, Error, OperationType, Result}; |
| |
| /// Request configuration objects |
| /// |
| /// Request config objects are used to pass a set of options to the kernel at |
| /// the time of the line request. The mutators don't return error values. If the |
| /// values are invalid, in general they are silently adjusted to acceptable |
| /// ranges. |
| |
| #[derive(Debug, Eq, PartialEq)] |
| pub struct Config { |
| pub(crate) config: *mut gpiod::gpiod_request_config, |
| } |
| |
| impl Config { |
| /// Create a new request config object. |
| pub fn new() -> Result<Self> { |
| // SAFETY: The `gpiod_request_config` returned by libgpiod is guaranteed to live as long |
| // as the `struct Config`. |
| let config = unsafe { gpiod::gpiod_request_config_new() }; |
| if config.is_null() { |
| return Err(Error::OperationFailed( |
| OperationType::RequestConfigNew, |
| errno::errno(), |
| )); |
| } |
| |
| Ok(Self { config }) |
| } |
| |
| /// Set the consumer name for the request. |
| /// |
| /// If the consumer string is too long, it will be truncated to the max |
| /// accepted length. |
| pub fn set_consumer(&mut self, consumer: &str) -> Result<&mut Self> { |
| let consumer = CString::new(consumer).map_err(|_| Error::InvalidString)?; |
| |
| // SAFETY: `gpiod_request_config` is guaranteed to be valid here. |
| unsafe { |
| gpiod::gpiod_request_config_set_consumer( |
| self.config, |
| consumer.as_ptr() as *const c_char, |
| ) |
| } |
| |
| Ok(self) |
| } |
| |
| /// Get the consumer name configured in the request config. |
| pub fn consumer(&self) -> Result<&str> { |
| // SAFETY: The string returned by libgpiod is guaranteed to live as long |
| // as the `struct Config`. |
| let consumer = unsafe { gpiod::gpiod_request_config_get_consumer(self.config) }; |
| if consumer.is_null() { |
| return Err(Error::OperationFailed( |
| OperationType::RequestConfigGetConsumer, |
| errno::errno(), |
| )); |
| } |
| |
| // SAFETY: The string is guaranteed to be valid here by the C API. |
| unsafe { CStr::from_ptr(consumer) } |
| .to_str() |
| .map_err(Error::StringNotUtf8) |
| } |
| |
| /// Set the size of the kernel event buffer for the request. |
| pub fn set_event_buffer_size(&mut self, size: usize) -> &mut Self { |
| // SAFETY: `gpiod_request_config` is guaranteed to be valid here. |
| unsafe { gpiod::gpiod_request_config_set_event_buffer_size(self.config, size) } |
| |
| self |
| } |
| |
| /// Get the edge event buffer size setting for the request config. |
| pub fn event_buffer_size(&self) -> usize { |
| // SAFETY: `gpiod_request_config` is guaranteed to be valid here. |
| unsafe { gpiod::gpiod_request_config_get_event_buffer_size(self.config) as usize } |
| } |
| } |
| |
| impl Drop for Config { |
| /// Free the request config object and release all associated resources. |
| fn drop(&mut self) { |
| // SAFETY: `gpiod_request_config` is guaranteed to be valid here. |
| unsafe { gpiod::gpiod_request_config_free(self.config) } |
| } |
| } |