ove/
gpio.rs

1// Copyright (C) 2026 Kamil Lulko <kamil.lulko@gmail.com>
2//
3// SPDX-License-Identifier: GPL-3.0-or-later
4//
5// This file is part of oveRTOS.
6
7//! GPIO control for oveRTOS.
8//!
9//! Provides pin configuration, digital read/write, and interrupt registration.
10//! Pins are identified by a `(port, pin)` pair where both are zero-based indices
11//! matching the platform's GPIO numbering.
12
13use crate::bindings;
14use crate::error::{Error, Result};
15
16/// GPIO pin direction/pull mode.
17#[repr(u32)]
18#[derive(Debug, Copy, Clone, PartialEq, Eq)]
19pub enum GpioMode {
20    /// Pin configured as a digital input.
21    Input = 0,
22    /// Pin configured as a push-pull output.
23    OutputPP = 1,
24    /// Pin configured as an open-drain output.
25    OutputOD = 2,
26}
27
28/// GPIO interrupt trigger mode.
29#[repr(u32)]
30#[derive(Debug, Copy, Clone, PartialEq, Eq)]
31pub enum GpioIrqMode {
32    /// Trigger interrupt on rising edge.
33    Rising = 0x01,
34    /// Trigger interrupt on falling edge.
35    Falling = 0x02,
36    /// Trigger interrupt on both edges.
37    Both = 0x03,
38}
39
40/// Configure a GPIO pin's direction and pull mode.
41///
42/// # Errors
43/// Returns [`Error::InvalidParam`] if `port` or `pin` is out of range.
44pub fn configure(port: u32, pin: u32, mode: GpioMode) -> Result<()> {
45    let rc = unsafe { bindings::ove_gpio_configure(port, pin, mode as bindings::ove_gpio_mode_t) };
46    Error::from_code(rc)
47}
48
49/// Set a GPIO pin's output level (`value`: 0 = low, non-zero = high).
50///
51/// # Errors
52/// Returns [`Error::InvalidParam`] if `port` or `pin` is out of range.
53pub fn set(port: u32, pin: u32, value: i32) -> Result<()> {
54    let rc = unsafe { bindings::ove_gpio_set(port, pin, value) };
55    Error::from_code(rc)
56}
57
58/// Read a GPIO pin input value. Returns the pin level (0 or 1) on success.
59pub fn get(port: u32, pin: u32) -> Result<i32> {
60    let rc = unsafe { bindings::ove_gpio_get(port, pin) };
61    if rc < 0 {
62        Error::from_code(rc)?;
63    }
64    Ok(rc)
65}
66
67/// Register a GPIO interrupt callback.
68///
69/// # Safety
70/// The callback and user_data must remain valid for the lifetime of the
71/// registration.
72pub unsafe fn irq_register(
73    port: u32,
74    pin: u32,
75    mode: GpioIrqMode,
76    callback: bindings::ove_gpio_irq_cb,
77    user_data: *mut core::ffi::c_void,
78) -> Result<()> {
79    let rc = unsafe {
80        bindings::ove_gpio_irq_register(port, pin, mode as bindings::ove_gpio_irq_mode_t, callback, user_data)
81    };
82    Error::from_code(rc)
83}
84
85/// Enable a previously registered GPIO interrupt.
86///
87/// # Errors
88/// Returns an error if the interrupt has not been registered or the pin is invalid.
89pub fn irq_enable(port: u32, pin: u32) -> Result<()> {
90    let rc = unsafe { bindings::ove_gpio_irq_enable(port, pin) };
91    Error::from_code(rc)
92}
93
94/// Disable a registered GPIO interrupt without removing the registration.
95///
96/// # Errors
97/// Returns an error if the interrupt has not been registered or the pin is invalid.
98pub fn irq_disable(port: u32, pin: u32) -> Result<()> {
99    let rc = unsafe { bindings::ove_gpio_irq_disable(port, pin) };
100    Error::from_code(rc)
101}