mirror of
https://github.com/mofeng-git/One-KVM.git
synced 2026-06-14 03:32:00 +08:00
150 lines
4.3 KiB
Rust
150 lines
4.3 KiB
Rust
use std::os::unix::io::AsRawFd;
|
|
|
|
use nix::errno::Errno;
|
|
use thiserror::Error;
|
|
|
|
use crate::bindings::v4l2_standard;
|
|
use crate::bindings::v4l2_std_id;
|
|
use crate::bindings::v4l2_streamparm;
|
|
use crate::QueueType;
|
|
|
|
#[doc(hidden)]
|
|
mod ioctl {
|
|
use crate::bindings::v4l2_standard;
|
|
use crate::bindings::v4l2_std_id;
|
|
use crate::bindings::v4l2_streamparm;
|
|
|
|
nix::ioctl_readwrite!(vidioc_g_parm, b'V', 21, v4l2_streamparm);
|
|
nix::ioctl_readwrite!(vidioc_s_parm, b'V', 22, v4l2_streamparm);
|
|
nix::ioctl_read!(vidioc_g_std, b'V', 23, v4l2_std_id);
|
|
nix::ioctl_write_ptr!(vidioc_s_std, b'V', 24, v4l2_std_id);
|
|
nix::ioctl_readwrite!(vidioc_enumstd, b'V', 25, v4l2_standard);
|
|
nix::ioctl_read!(vidioc_querystd, b'V', 63, v4l2_std_id);
|
|
}
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum GParmError {
|
|
#[error("ioctl error: {0}")]
|
|
IoctlError(Errno),
|
|
}
|
|
|
|
impl From<GParmError> for Errno {
|
|
fn from(err: GParmError) -> Self {
|
|
match err {
|
|
GParmError::IoctlError(e) => e,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Safe wrapper around the `VIDIOC_G_PARM` ioctl.
|
|
pub fn g_parm<O: From<v4l2_streamparm>>(
|
|
fd: &impl AsRawFd,
|
|
queue: QueueType,
|
|
) -> Result<O, GParmError> {
|
|
let mut parm = v4l2_streamparm {
|
|
type_: queue as u32,
|
|
..Default::default()
|
|
};
|
|
|
|
match unsafe { ioctl::vidioc_g_parm(fd.as_raw_fd(), &mut parm) } {
|
|
Ok(_) => Ok(O::from(parm)),
|
|
Err(e) => Err(GParmError::IoctlError(e)),
|
|
}
|
|
}
|
|
|
|
/// Safe wrapper around the `VIDIOC_S_PARM` ioctl.
|
|
pub fn s_parm<I: Into<v4l2_streamparm>, O: From<v4l2_streamparm>>(
|
|
fd: &impl AsRawFd,
|
|
parm: I,
|
|
) -> Result<O, GParmError> {
|
|
let mut parm = parm.into();
|
|
|
|
match unsafe { ioctl::vidioc_s_parm(fd.as_raw_fd(), &mut parm) } {
|
|
Ok(_) => Ok(O::from(parm)),
|
|
Err(e) => Err(GParmError::IoctlError(e)),
|
|
}
|
|
}
|
|
|
|
/// Safe wrapper around the `VIDIOC_G_STD` ioctl.
|
|
pub fn g_std<O: From<v4l2_std_id>>(fd: &impl AsRawFd) -> Result<O, GParmError> {
|
|
let mut std_id: v4l2_std_id = 0;
|
|
|
|
match unsafe { ioctl::vidioc_g_std(fd.as_raw_fd(), &mut std_id) } {
|
|
Ok(_) => Ok(O::from(std_id)),
|
|
Err(e) => Err(GParmError::IoctlError(e)),
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum SStdError {
|
|
#[error("unsupported standard requested")]
|
|
Unsupported,
|
|
#[error("ioctl error: {0}")]
|
|
IoctlError(Errno),
|
|
}
|
|
|
|
impl From<SStdError> for Errno {
|
|
fn from(err: SStdError) -> Self {
|
|
match err {
|
|
SStdError::Unsupported => Errno::EINVAL,
|
|
SStdError::IoctlError(e) => e,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Safe wrapper around the `VIDIOC_S_STD` ioctl.
|
|
pub fn s_std<I: Into<v4l2_std_id>>(fd: &impl AsRawFd, std_id: I) -> Result<(), SStdError> {
|
|
let std_id = std_id.into();
|
|
|
|
match unsafe { ioctl::vidioc_s_std(fd.as_raw_fd(), &std_id) } {
|
|
Ok(_) => Ok(()),
|
|
Err(Errno::EINVAL) => Err(SStdError::Unsupported),
|
|
Err(e) => Err(SStdError::IoctlError(e)),
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum EnumStdError {
|
|
#[error("requested index is out of bounds")]
|
|
OutOfBounds,
|
|
#[error("standard video timings are not supported for this input or output")]
|
|
Unsupported,
|
|
#[error("ioctl error: {0}")]
|
|
IoctlError(Errno),
|
|
}
|
|
|
|
impl From<EnumStdError> for Errno {
|
|
fn from(err: EnumStdError) -> Self {
|
|
match err {
|
|
EnumStdError::OutOfBounds => Errno::EINVAL,
|
|
EnumStdError::Unsupported => Errno::ENODATA,
|
|
EnumStdError::IoctlError(e) => e,
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Safe wrapper around the `VIDIOC_ENUMSTD` ioctl.
|
|
pub fn enumstd<O: From<v4l2_standard>>(fd: &impl AsRawFd, index: u32) -> Result<O, EnumStdError> {
|
|
let mut standard = v4l2_standard {
|
|
index,
|
|
..Default::default()
|
|
};
|
|
|
|
match unsafe { ioctl::vidioc_enumstd(fd.as_raw_fd(), &mut standard) } {
|
|
Ok(_) => Ok(O::from(standard)),
|
|
Err(Errno::EINVAL) => Err(EnumStdError::OutOfBounds),
|
|
Err(Errno::ENODATA) => Err(EnumStdError::Unsupported),
|
|
Err(e) => Err(EnumStdError::IoctlError(e)),
|
|
}
|
|
}
|
|
|
|
/// Safe wrapper around the `VIDIOC_QUERYSTD` ioctl.
|
|
pub fn querystd<O: From<v4l2_std_id>>(fd: &impl AsRawFd) -> Result<O, GParmError> {
|
|
let mut std_id: v4l2_std_id = 0;
|
|
|
|
match unsafe { ioctl::vidioc_querystd(fd.as_raw_fd(), &mut std_id) } {
|
|
Ok(_) => Ok(O::from(std_id)),
|
|
Err(e) => Err(GParmError::IoctlError(e)),
|
|
}
|
|
}
|