1 use crate::ioctl::ioctl_and_convert;
2 use crate::ioctl::IoctlConvertError;
3 use crate::ioctl::IoctlConvertResult;
4 use crate::ioctl::UncheckedV4l2Buffer;
5 use crate::QueueType;
6 
7 use std::convert::TryFrom;
8 use std::fmt::Debug;
9 use std::os::unix::io::AsRawFd;
10 
11 use nix::errno::Errno;
12 use thiserror::Error;
13 
14 #[doc(hidden)]
15 mod ioctl {
16     use crate::bindings::v4l2_buffer;
17     nix::ioctl_readwrite!(vidioc_dqbuf, b'V', 17, v4l2_buffer);
18 }
19 
20 #[derive(Debug, Error)]
21 pub enum DqBufIoctlError {
22     #[error("end-of-stream reached")]
23     Eos,
24     #[error("no buffer ready for dequeue")]
25     NotReady,
26     #[error("unexpected ioctl error: {0}")]
27     Other(Errno),
28 }
29 
30 impl From<Errno> for DqBufIoctlError {
from(error: Errno) -> Self31     fn from(error: Errno) -> Self {
32         match error {
33             Errno::EAGAIN => Self::NotReady,
34             Errno::EPIPE => Self::Eos,
35             error => Self::Other(error),
36         }
37     }
38 }
39 
40 impl From<DqBufIoctlError> for Errno {
from(err: DqBufIoctlError) -> Self41     fn from(err: DqBufIoctlError) -> Self {
42         match err {
43             DqBufIoctlError::Eos => Errno::EPIPE,
44             DqBufIoctlError::NotReady => Errno::EAGAIN,
45             DqBufIoctlError::Other(e) => e,
46         }
47     }
48 }
49 
50 pub type DqBufError<CE> = IoctlConvertError<DqBufIoctlError, CE>;
51 pub type DqBufResult<O, CE> = IoctlConvertResult<O, DqBufIoctlError, CE>;
52 
53 /// Safe wrapper around the `VIDIOC_DQBUF` ioctl.
dqbuf<O>(fd: &impl AsRawFd, queue: QueueType) -> DqBufResult<O, O::Error> where O: TryFrom<UncheckedV4l2Buffer>, O::Error: std::fmt::Debug,54 pub fn dqbuf<O>(fd: &impl AsRawFd, queue: QueueType) -> DqBufResult<O, O::Error>
55 where
56     O: TryFrom<UncheckedV4l2Buffer>,
57     O::Error: std::fmt::Debug,
58 {
59     let mut v4l2_buf = UncheckedV4l2Buffer::new_for_querybuf(queue, None);
60 
61     ioctl_and_convert(
62         unsafe { ioctl::vidioc_dqbuf(fd.as_raw_fd(), v4l2_buf.as_mut()) }
63             .map(|_| v4l2_buf)
64             .map_err(Into::into),
65     )
66 }
67