Skip to content

Commit

Permalink
ioctl: add input/output selection/enumeration support
Browse files Browse the repository at this point in the history
Gnurou committed Mar 1, 2023
1 parent a065259 commit b0cfeef
Showing 2 changed files with 108 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/src/ioctl.rs
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@ mod encoder_cmd;
mod enum_fmt;
mod expbuf;
mod g_fmt;
mod g_input;
mod g_selection;
mod mmap;
mod qbuf;
@@ -29,6 +30,7 @@ pub use encoder_cmd::*;
pub use enum_fmt::*;
pub use expbuf::*;
pub use g_fmt::*;
pub use g_input::*;
pub use g_selection::*;
pub use mmap::*;
use nix::errno::Errno;
106 changes: 106 additions & 0 deletions lib/src/ioctl/g_input.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
use std::ffi::c_int;
use std::mem;
use std::os::unix::io::AsRawFd;

use nix::errno::Errno;
use thiserror::Error;

use crate::bindings::v4l2_input;
use crate::bindings::v4l2_output;

#[doc(hidden)]
mod ioctl {
use std::ffi::c_int;

use crate::bindings::v4l2_input;
use crate::bindings::v4l2_output;

nix::ioctl_readwrite!(vidioc_enuminput, b'V', 26, v4l2_input);
nix::ioctl_read!(vidioc_g_input, b'V', 38, c_int);
nix::ioctl_readwrite!(vidioc_s_input, b'V', 39, c_int);

nix::ioctl_read!(vidioc_g_output, b'V', 46, c_int);
nix::ioctl_readwrite!(vidioc_s_output, b'V', 47, c_int);
nix::ioctl_readwrite!(vidioc_enumoutput, b'V', 48, v4l2_output);
}

#[derive(Debug, Error)]
pub enum SelectionError {
#[error("selection {0} is out of range")]
OutOfRange(usize),
#[error("ioctl error: {0}")]
IoctlError(Errno),
}

impl From<SelectionError> for Errno {
fn from(err: SelectionError) -> Self {
match err {
SelectionError::OutOfRange(_) => Errno::EINVAL,
SelectionError::IoctlError(e) => e,
}
}
}

pub fn enuminput<F: AsRawFd, R: From<v4l2_input>>(
fd: &F,
index: usize,
) -> Result<R, SelectionError> {
let mut input = v4l2_input {
index: index as u32,
..unsafe { mem::zeroed() }
};

match unsafe { ioctl::vidioc_enuminput(fd.as_raw_fd(), &mut input) } {
Ok(_) => Ok(R::from(input)),
Err(Errno::EINVAL) => Err(SelectionError::OutOfRange(index)),
Err(e) => Err(SelectionError::IoctlError(e)),
}
}

pub fn g_input<F: AsRawFd>(fd: &F) -> Result<usize, Errno> {
let mut input: c_int = 0;

unsafe { ioctl::vidioc_g_input(fd.as_raw_fd(), &mut input) }.map(|r| r as usize)
}

pub fn s_input<F: AsRawFd>(fd: &F, index: usize) -> Result<(), SelectionError> {
let mut input: c_int = index as c_int;

match unsafe { ioctl::vidioc_s_input(fd.as_raw_fd(), &mut input) } {
Ok(_) => Ok(()),
Err(Errno::EINVAL) => Err(SelectionError::OutOfRange(index)),
Err(e) => Err(SelectionError::IoctlError(e)),
}
}

pub fn enumoutput<F: AsRawFd, R: From<v4l2_output>>(
fd: &F,
index: usize,
) -> Result<R, SelectionError> {
let mut output = v4l2_output {
index: index as u32,
..unsafe { mem::zeroed() }
};

match unsafe { ioctl::vidioc_enumoutput(fd.as_raw_fd(), &mut output) } {
Ok(_) => Ok(R::from(output)),
Err(Errno::EINVAL) => Err(SelectionError::OutOfRange(index)),
Err(e) => Err(SelectionError::IoctlError(e)),
}
}

pub fn g_output<F: AsRawFd>(fd: &F) -> Result<usize, Errno> {
let mut output: c_int = 0;

unsafe { ioctl::vidioc_g_output(fd.as_raw_fd(), &mut output) }.map(|r| r as usize)
}

pub fn s_output<F: AsRawFd>(fd: &F, index: usize) -> Result<(), SelectionError> {
let mut output: c_int = index as c_int;

match unsafe { ioctl::vidioc_s_output(fd.as_raw_fd(), &mut output) } {
Ok(_) => Ok(()),
Err(Errno::EINVAL) => Err(SelectionError::OutOfRange(index)),
Err(e) => Err(SelectionError::IoctlError(e)),
}
}

0 comments on commit b0cfeef

Please sign in to comment.