1 //! Safe wrapper for the `VIDIOC_EXPBUF` ioctl.
2 use bitflags::bitflags;
3 use nix::errno::Errno;
4 use nix::fcntl::OFlag;
5 use std::os::unix::io::{AsRawFd, FromRawFd};
6 use thiserror::Error;
7 
8 use crate::bindings::v4l2_exportbuffer;
9 use crate::QueueType;
10 
11 bitflags! {
12     /// Flags that can be passed when exporting the buffer.
13     #[derive(Clone, Copy, Debug)]
14     pub struct ExpbufFlags: u32 {
15         const CLOEXEC = OFlag::O_CLOEXEC.bits() as u32;
16         const RDONLY = OFlag::O_RDONLY.bits() as u32;
17         const WRONLY = OFlag::O_WRONLY.bits() as u32;
18         const RDWR = OFlag::O_RDWR.bits() as u32;
19     }
20 }
21 
22 #[doc(hidden)]
23 mod ioctl {
24     use crate::bindings::v4l2_exportbuffer;
25     nix::ioctl_readwrite!(vidioc_expbuf, b'V', 16, v4l2_exportbuffer);
26 }
27 
28 #[derive(Debug, Error)]
29 pub enum ExpbufError {
30     #[error("ioctl error: {0}")]
31     IoctlError(#[from] Errno),
32 }
33 
34 impl From<ExpbufError> for Errno {
from(err: ExpbufError) -> Self35     fn from(err: ExpbufError) -> Self {
36         match err {
37             ExpbufError::IoctlError(e) => e,
38         }
39     }
40 }
41 
42 /// Safe wrapper around the `VIDIOC_EXPBUF` ioctl.
expbuf<R: FromRawFd>( fd: &impl AsRawFd, queue: QueueType, index: usize, plane: usize, flags: ExpbufFlags, ) -> Result<R, ExpbufError>43 pub fn expbuf<R: FromRawFd>(
44     fd: &impl AsRawFd,
45     queue: QueueType,
46     index: usize,
47     plane: usize,
48     flags: ExpbufFlags,
49 ) -> Result<R, ExpbufError> {
50     let mut v4l2_expbuf = v4l2_exportbuffer {
51         type_: queue as u32,
52         index: index as u32,
53         plane: plane as u32,
54         flags: flags.bits(),
55         ..Default::default()
56     };
57 
58     unsafe { ioctl::vidioc_expbuf(fd.as_raw_fd(), &mut v4l2_expbuf) }?;
59 
60     Ok(unsafe { R::from_raw_fd(v4l2_expbuf.fd) })
61 }
62