1 use nix::errno::Errno;
2 use std::os::unix::io::AsRawFd;
3 use thiserror::Error;
4
5 use crate::bindings;
6 use crate::bindings::v4l2_frmivalenum;
7 use crate::PixelFormat;
8
9 /// A wrapper for the 'v4l2_frmivalenum' union member types
10 #[derive(Debug)]
11 pub enum FrmIvalTypes<'a> {
12 Discrete(&'a bindings::v4l2_fract),
13 StepWise(&'a bindings::v4l2_frmival_stepwise),
14 }
15
16 impl v4l2_frmivalenum {
17 /// Safely access the intervals member of the struct based on the
18 /// returned type.
intervals(&self) -> Option<FrmIvalTypes>19 pub fn intervals(&self) -> Option<FrmIvalTypes> {
20 match self.type_ {
21 // SAFETY: the member of the union that gets used by the driver
22 // is determined by the type
23 bindings::v4l2_frmivaltypes_V4L2_FRMIVAL_TYPE_DISCRETE => {
24 Some(FrmIvalTypes::Discrete(unsafe {
25 &self.__bindgen_anon_1.discrete
26 }))
27 }
28
29 // SAFETY: the member of the union that gets used by the driver
30 // is determined by the type
31 bindings::v4l2_frmivaltypes_V4L2_FRMIVAL_TYPE_CONTINUOUS
32 | bindings::v4l2_frmivaltypes_V4L2_FRMIVAL_TYPE_STEPWISE => {
33 Some(FrmIvalTypes::StepWise(unsafe {
34 &self.__bindgen_anon_1.stepwise
35 }))
36 }
37
38 _ => None,
39 }
40 }
41 }
42
43 #[doc(hidden)]
44 mod ioctl {
45 use crate::bindings::v4l2_frmivalenum;
46 nix::ioctl_readwrite!(vidioc_enum_frameintervals, b'V', 75, v4l2_frmivalenum);
47 }
48
49 #[derive(Debug, Error)]
50 pub enum FrameIntervalsError {
51 #[error("Unexpected ioctl error: {0}")]
52 IoctlError(nix::Error),
53 }
54
55 impl From<FrameIntervalsError> for Errno {
from(err: FrameIntervalsError) -> Self56 fn from(err: FrameIntervalsError) -> Self {
57 match err {
58 FrameIntervalsError::IoctlError(e) => e,
59 }
60 }
61 }
62 /// Safe wrapper around the `VIDIOC_ENUM_FRAMEINTERVALS` ioctl.
enum_frame_intervals<O: From<v4l2_frmivalenum>>( fd: &impl AsRawFd, index: u32, pixel_format: PixelFormat, width: u32, height: u32, ) -> Result<O, FrameIntervalsError>63 pub fn enum_frame_intervals<O: From<v4l2_frmivalenum>>(
64 fd: &impl AsRawFd,
65 index: u32,
66 pixel_format: PixelFormat,
67 width: u32,
68 height: u32,
69 ) -> Result<O, FrameIntervalsError> {
70 let mut frame_interval = v4l2_frmivalenum {
71 index,
72 pixel_format: pixel_format.into(),
73 width,
74 height,
75 ..Default::default()
76 };
77
78 match unsafe { ioctl::vidioc_enum_frameintervals(fd.as_raw_fd(), &mut frame_interval) } {
79 Ok(_) => Ok(O::from(frame_interval)),
80 Err(e) => Err(FrameIntervalsError::IoctlError(e)),
81 }
82 }
83