libgpiod/
request_config.rs

1// SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause
2// SPDX-FileCopyrightText: 2022 Linaro Ltd.
3// SPDX-FileCopyrightText: 2022 Viresh Kumar <viresh.kumar@linaro.org>
4
5use std::ffi::{CStr, CString};
6use std::os::raw::c_char;
7use std::str;
8
9use super::{Error, OperationType, Result, gpiod};
10
11/// Request configuration objects
12///
13/// Request config objects are used to pass a set of options to the kernel at
14/// the time of the line request. The mutators don't return error values. If the
15/// values are invalid, in general they are silently adjusted to acceptable
16/// ranges.
17
18#[derive(Debug, Eq, PartialEq)]
19pub struct Config {
20    pub(crate) config: *mut gpiod::gpiod_request_config,
21}
22
23// SAFETY: Config models a wrapper around an owned gpiod_request_config and may
24// be safely sent to other threads.
25unsafe impl Send for Config {}
26
27impl Config {
28    /// Create a new request config object.
29    pub fn new() -> Result<Self> {
30        // SAFETY: The `gpiod_request_config` returned by libgpiod is guaranteed to live as long
31        // as the `struct Config`.
32        let config = unsafe { gpiod::gpiod_request_config_new() };
33        if config.is_null() {
34            return Err(Error::OperationFailed(
35                OperationType::RequestConfigNew,
36                errno::errno(),
37            ));
38        }
39
40        Ok(Self { config })
41    }
42
43    /// Set the consumer name for the request.
44    ///
45    /// If the consumer string is too long, it will be truncated to the max
46    /// accepted length.
47    pub fn set_consumer(&mut self, consumer: &str) -> Result<&mut Self> {
48        let consumer = CString::new(consumer).map_err(|_| Error::InvalidString)?;
49
50        // SAFETY: `gpiod_request_config` is guaranteed to be valid here.
51        unsafe {
52            gpiod::gpiod_request_config_set_consumer(
53                self.config,
54                consumer.as_ptr() as *const c_char,
55            )
56        }
57
58        Ok(self)
59    }
60
61    /// Get the consumer name configured in the request config.
62    pub fn consumer(&self) -> Result<&str> {
63        // SAFETY: The string returned by libgpiod is guaranteed to live as long
64        // as the `struct Config`.
65        let consumer = unsafe { gpiod::gpiod_request_config_get_consumer(self.config) };
66        if consumer.is_null() {
67            return Err(Error::OperationFailed(
68                OperationType::RequestConfigGetConsumer,
69                errno::errno(),
70            ));
71        }
72
73        // SAFETY: The string is guaranteed to be valid here by the C API.
74        unsafe { CStr::from_ptr(consumer) }
75            .to_str()
76            .map_err(Error::StringNotUtf8)
77    }
78
79    /// Set the size of the kernel event buffer for the request.
80    pub fn set_event_buffer_size(&mut self, size: usize) -> &mut Self {
81        // SAFETY: `gpiod_request_config` is guaranteed to be valid here.
82        unsafe { gpiod::gpiod_request_config_set_event_buffer_size(self.config, size) }
83
84        self
85    }
86
87    /// Get the edge event buffer size setting for the request config.
88    pub fn event_buffer_size(&self) -> usize {
89        // SAFETY: `gpiod_request_config` is guaranteed to be valid here.
90        unsafe { gpiod::gpiod_request_config_get_event_buffer_size(self.config) }
91    }
92}
93
94impl Drop for Config {
95    /// Free the request config object and release all associated resources.
96    fn drop(&mut self) {
97        // SAFETY: `gpiod_request_config` is guaranteed to be valid here.
98        unsafe { gpiod::gpiod_request_config_free(self.config) }
99    }
100}