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_frmsizeenum;
7 use crate::PixelFormat;
8
9 /// A wrapper for the 'v4l2_frmsizeenum' union member types
10 #[derive(Debug)]
11 pub enum FrmSizeTypes<'a> {
12 Discrete(&'a bindings::v4l2_frmsize_discrete),
13 StepWise(&'a bindings::v4l2_frmsize_stepwise),
14 }
15
16 impl v4l2_frmsizeenum {
17 /// Safely access the size member of the struct based on the
18 /// returned type.
size(&self) -> Option<FrmSizeTypes>19 pub fn size(&self) -> Option<FrmSizeTypes> {
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_frmsizetypes_V4L2_FRMSIZE_TYPE_DISCRETE => {
24 Some(FrmSizeTypes::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_frmsizetypes_V4L2_FRMSIZE_TYPE_CONTINUOUS
32 | bindings::v4l2_frmsizetypes_V4L2_FRMSIZE_TYPE_STEPWISE => {
33 Some(FrmSizeTypes::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_frmsizeenum;
46 nix::ioctl_readwrite!(vidioc_enum_framesizes, b'V', 74, v4l2_frmsizeenum);
47 }
48
49 #[derive(Debug, Error)]
50 pub enum FrameSizeError {
51 #[error("Unexpected ioctl error: {0}")]
52 IoctlError(nix::Error),
53 }
54
55 impl From<FrameSizeError> for Errno {
from(err: FrameSizeError) -> Self56 fn from(err: FrameSizeError) -> Self {
57 match err {
58 FrameSizeError::IoctlError(e) => e,
59 }
60 }
61 }
62
63 /// Safe wrapper around the `VIDIOC_ENUM_FRAMESIZES` ioctl.
enum_frame_sizes<O: From<v4l2_frmsizeenum>>( fd: &impl AsRawFd, index: u32, pixel_format: PixelFormat, ) -> Result<O, FrameSizeError>64 pub fn enum_frame_sizes<O: From<v4l2_frmsizeenum>>(
65 fd: &impl AsRawFd,
66 index: u32,
67 pixel_format: PixelFormat,
68 ) -> Result<O, FrameSizeError> {
69 let mut frame_size = v4l2_frmsizeenum {
70 index,
71 pixel_format: pixel_format.into(),
72 ..Default::default()
73 };
74
75 match unsafe { ioctl::vidioc_enum_framesizes(fd.as_raw_fd(), &mut frame_size) } {
76 Ok(_) => Ok(O::from(frame_size)),
77 Err(e) => Err(FrameSizeError::IoctlError(e)),
78 }
79 }
80