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