linux_media/request.rs
1use std::os::fd::{AsRawFd, BorrowedFd, FromRawFd, OwnedFd};
2
3use linux_media_sys as media;
4
5use crate::error;
6use crate::ioctl;
7
8/// A request associated with a media device.
9///
10/// # Details
11/// This is a wrapper for the media control API's request, which is tied to a specific media device.
12#[derive(Debug)]
13pub struct Request<'a> {
14 /// The file descriptor of the media device from which the request was allocated.
15 media_fd: BorrowedFd<'a>,
16 /// The file descriptor corresponding to the request allocated on the media device (referenced by media_fd).
17 request_fd: OwnedFd,
18}
19
20impl<'a> Request<'a> {
21 pub fn new(media_fd: BorrowedFd<'a>) -> error::Result<Self> {
22 unsafe {
23 let mut request_fd: libc::c_int = -1;
24 ioctl!(media_fd, media::MEDIA_IOC_REQUEST_ALLOC, &mut request_fd)?;
25 Ok(Self {
26 media_fd,
27 request_fd: OwnedFd::from_raw_fd(request_fd),
28 })
29 }
30 }
31
32 /// Allocate a new request on the same media device
33 pub fn new_request(&self) -> error::Result<Self> {
34 Self::new(self.media_fd)
35 }
36
37 /// Initializes the request for recycling without re-allocating it.
38 ///
39 /// # Details
40 /// Reinitializes the request, provided that it has not been queued yet or that it has already been queued and completed.
41 /// After reinitialization, the request is ready to be queued again for subsequent operations.
42 ///
43 /// # Errors
44 /// If the request is still queued and has not yet completed, this function returns [`error::Error::DeviceIsBusy`]. No other errors are possible.
45 pub fn init(&mut self) -> error::Result<()> {
46 unsafe { ioctl!(self.request_fd, media::MEDIA_REQUEST_IOC_REINIT) }
47 }
48
49 /// Enqueue the request
50 ///
51 /// # Errors
52 /// - `RequestIsAlreadyQueued` : The request was already queued or the application queued the first buffer directly, but later attempted to use a request. It is not permitted to mix the two APIs.
53 /// - `RequestNotContainBuffers` : The request did not contain any buffers. All requests are required to have at least one buffer. This can also be returned if some required configuration is missing in the request.
54 /// - `OutOfMemory` : Out of memory when allocating internal data structures for this request.
55 /// - `RequestHasInvalidData` : The request has invalid data.
56 /// - `HardwareBadState` : The hardware is in a bad state. To recover, the application needs to stop streaming to reset the hardware state and then try to restart streaming.
57 pub fn queue(&self) -> error::Result<()> {
58 use error::Error::*;
59 let api = media::MEDIA_REQUEST_IOC_QUEUE;
60 unsafe {
61 ioctl!(self.request_fd, api).map_err(|err| {
62 let fd = self.request_fd.as_raw_fd();
63 if let Ioctl { ref code, .. } = err {
64 match code.raw_os_error() {
65 Some(code @ libc::EBUSY) => RequestIsAlreadyQueued { fd, code, api },
66 Some(code @ libc::ENOENT) => RequestNotContainBuffers { fd, code, api },
67 Some(code @ libc::ENOMEM) => OutOfMemory { fd, code, api },
68 Some(code @ libc::EINVAL) => RequestHasInvalidData { fd, code, api },
69 Some(code @ libc::EIO) => HardwareBadState { fd, code, api },
70 _ => err,
71 }
72 } else {
73 err
74 }
75 })
76 }
77 }
78}