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