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}