1 //! Safe wrapper for the `VIDIOC_STREAM(ON|OFF)` ioctls.
2 use crate::QueueType;
3 use nix::errno::Errno;
4 use std::os::unix::io::AsRawFd;
5 use thiserror::Error;
6 
7 #[doc(hidden)]
8 mod ioctl {
9     nix::ioctl_write_ptr!(vidioc_streamon, b'V', 18, u32);
10     nix::ioctl_write_ptr!(vidioc_streamoff, b'V', 19, u32);
11 }
12 
13 #[derive(Debug, Error)]
14 pub enum StreamOnError {
15     #[error("queue type ({0}) not supported, or no buffers allocated or enqueued")]
16     InvalidQueue(QueueType),
17     #[error("invalid pad configuration")]
18     InvalidPadConfig,
19     #[error("invalid pipeline link configuration")]
20     InvalidPipelineConfig,
21     #[error("ioctl error: {0}")]
22     IoctlError(Errno),
23 }
24 
25 impl From<StreamOnError> for Errno {
from(err: StreamOnError) -> Self26     fn from(err: StreamOnError) -> Self {
27         match err {
28             StreamOnError::InvalidQueue(_) => Errno::EINVAL,
29             StreamOnError::InvalidPadConfig => Errno::EPIPE,
30             StreamOnError::InvalidPipelineConfig => Errno::ENOLINK,
31             StreamOnError::IoctlError(e) => e,
32         }
33     }
34 }
35 
36 /// Safe wrapper around the `VIDIOC_STREAMON` ioctl.
streamon(fd: &impl AsRawFd, queue: QueueType) -> Result<(), StreamOnError>37 pub fn streamon(fd: &impl AsRawFd, queue: QueueType) -> Result<(), StreamOnError> {
38     match unsafe { ioctl::vidioc_streamon(fd.as_raw_fd(), &(queue as u32)) } {
39         Ok(_) => Ok(()),
40         Err(Errno::EINVAL) => Err(StreamOnError::InvalidQueue(queue)),
41         Err(Errno::EPIPE) => Err(StreamOnError::InvalidPadConfig),
42         Err(Errno::ENOLINK) => Err(StreamOnError::InvalidPipelineConfig),
43         Err(e) => Err(StreamOnError::IoctlError(e)),
44     }
45 }
46 
47 #[derive(Debug, Error)]
48 pub enum StreamOffError {
49     #[error("queue type not supported")]
50     InvalidQueue,
51     #[error("ioctl error: {0}")]
52     IoctlError(Errno),
53 }
54 
55 impl From<StreamOffError> for Errno {
from(err: StreamOffError) -> Self56     fn from(err: StreamOffError) -> Self {
57         match err {
58             StreamOffError::InvalidQueue => Errno::EINVAL,
59             StreamOffError::IoctlError(e) => e,
60         }
61     }
62 }
63 
64 /// Safe wrapper around the `VIDIOC_STREAMOFF` ioctl.
streamoff(fd: &impl AsRawFd, queue: QueueType) -> Result<(), StreamOffError>65 pub fn streamoff(fd: &impl AsRawFd, queue: QueueType) -> Result<(), StreamOffError> {
66     match unsafe { ioctl::vidioc_streamoff(fd.as_raw_fd(), &(queue as u32)) } {
67         Ok(_) => Ok(()),
68         Err(Errno::EINVAL) => Err(StreamOffError::InvalidQueue),
69         Err(e) => Err(StreamOffError::IoctlError(e)),
70     }
71 }
72