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}