| //! Safe wrapper for the `VIDIOC_EXPBUF` ioctl. |
| use bitflags::bitflags; |
| use nix::errno::Errno; |
| use nix::fcntl::OFlag; |
| use std::mem; |
| use std::os::unix::io::{AsRawFd, FromRawFd}; |
| use thiserror::Error; |
| |
| use crate::{bindings, QueueType}; |
| |
| bitflags! { |
| /// Flags that can be passed when exporting the buffer. |
| pub struct ExpbufFlags: u32 { |
| const CLOEXEC = OFlag::O_CLOEXEC.bits() as u32; |
| const RDONLY = OFlag::O_RDONLY.bits() as u32; |
| const WRONLY = OFlag::O_WRONLY.bits() as u32; |
| const RDWR = OFlag::O_RDWR.bits() as u32; |
| } |
| } |
| |
| #[doc(hidden)] |
| mod ioctl { |
| use crate::bindings::v4l2_exportbuffer; |
| nix::ioctl_readwrite!(vidioc_expbuf, b'V', 16, v4l2_exportbuffer); |
| } |
| |
| #[derive(Debug, Error)] |
| pub enum ExpbufError { |
| #[error("ioctl error: {0}")] |
| IoctlError(#[from] Errno), |
| } |
| |
| impl From<ExpbufError> for Errno { |
| fn from(err: ExpbufError) -> Self { |
| match err { |
| ExpbufError::IoctlError(e) => e, |
| } |
| } |
| } |
| |
| /// Safe wrapper around the `VIDIOC_EXPBUF` ioctl. |
| pub fn expbuf<F: AsRawFd, R: FromRawFd>( |
| fd: &F, |
| queue: QueueType, |
| index: usize, |
| plane: usize, |
| flags: ExpbufFlags, |
| ) -> Result<R, ExpbufError> { |
| let mut v4l2_expbuf = bindings::v4l2_exportbuffer { |
| type_: queue as u32, |
| index: index as u32, |
| plane: plane as u32, |
| flags: flags.bits(), |
| ..unsafe { mem::zeroed() } |
| }; |
| |
| unsafe { ioctl::vidioc_expbuf(fd.as_raw_fd(), &mut v4l2_expbuf) }?; |
| |
| Ok(unsafe { R::from_raw_fd(v4l2_expbuf.fd) }) |
| } |