xref: /aosp_15_r20/external/virtio-media/device/src/ioctl.rs (revision 1b4853f54772485c5dd4001ae33a7a958bcc97a1)
1*1b4853f5SAndroid Build Coastguard Worker // Copyright 2024 The ChromiumOS Authors
2*1b4853f5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*1b4853f5SAndroid Build Coastguard Worker // found in the LICENSE file.
4*1b4853f5SAndroid Build Coastguard Worker 
5*1b4853f5SAndroid Build Coastguard Worker use std::io::Result as IoResult;
6*1b4853f5SAndroid Build Coastguard Worker 
7*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_audio;
8*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_audioout;
9*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_buffer;
10*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_control;
11*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_create_buffers;
12*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_decoder_cmd;
13*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_dv_timings;
14*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_dv_timings_cap;
15*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_enc_idx;
16*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_encoder_cmd;
17*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_enum_dv_timings;
18*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_event_subscription;
19*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_ext_control;
20*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_ext_controls;
21*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_fmtdesc;
22*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_format;
23*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_frequency;
24*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_frequency_band;
25*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_frmivalenum;
26*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_frmsizeenum;
27*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_input;
28*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_modulator;
29*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_output;
30*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_plane;
31*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_query_ext_ctrl;
32*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_queryctrl;
33*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_querymenu;
34*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_rect;
35*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_requestbuffers;
36*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_selection;
37*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_standard;
38*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_std_id;
39*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_streamparm;
40*1b4853f5SAndroid Build Coastguard Worker use v4l2r::bindings::v4l2_tuner;
41*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::AudioMode;
42*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::CtrlId;
43*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::CtrlWhich;
44*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::EventType as V4l2EventType;
45*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::QueryCtrlFlags;
46*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::SelectionFlags;
47*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::SelectionTarget;
48*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::SelectionType;
49*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::SubscribeEventFlags;
50*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::TunerMode;
51*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::TunerTransmissionFlags;
52*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::TunerType;
53*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::UncheckedV4l2Buffer;
54*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::V4l2Buffer;
55*1b4853f5SAndroid Build Coastguard Worker use v4l2r::ioctl::V4l2PlanesWithBacking;
56*1b4853f5SAndroid Build Coastguard Worker use v4l2r::memory::MemoryType;
57*1b4853f5SAndroid Build Coastguard Worker use v4l2r::QueueDirection;
58*1b4853f5SAndroid Build Coastguard Worker use v4l2r::QueueType;
59*1b4853f5SAndroid Build Coastguard Worker 
60*1b4853f5SAndroid Build Coastguard Worker use crate::protocol::RespHeader;
61*1b4853f5SAndroid Build Coastguard Worker use crate::protocol::SgEntry;
62*1b4853f5SAndroid Build Coastguard Worker use crate::protocol::V4l2Ioctl;
63*1b4853f5SAndroid Build Coastguard Worker use crate::FromDescriptorChain;
64*1b4853f5SAndroid Build Coastguard Worker use crate::ReadFromDescriptorChain;
65*1b4853f5SAndroid Build Coastguard Worker use crate::ToDescriptorChain;
66*1b4853f5SAndroid Build Coastguard Worker use crate::WriteToDescriptorChain;
67*1b4853f5SAndroid Build Coastguard Worker 
68*1b4853f5SAndroid Build Coastguard Worker /// Module allowing select V4L2 structures from implementing zerocopy and implementations of
69*1b4853f5SAndroid Build Coastguard Worker /// [`FromDescriptorChain`] and [`ToDescriptorChain`] for them.
70*1b4853f5SAndroid Build Coastguard Worker mod v4l2_zerocopy {
71*1b4853f5SAndroid Build Coastguard Worker     use v4l2r::bindings;
72*1b4853f5SAndroid Build Coastguard Worker     use zerocopy::AsBytes;
73*1b4853f5SAndroid Build Coastguard Worker     use zerocopy::FromBytes;
74*1b4853f5SAndroid Build Coastguard Worker     use zerocopy::FromZeroes;
75*1b4853f5SAndroid Build Coastguard Worker 
76*1b4853f5SAndroid Build Coastguard Worker     use crate::FromDescriptorChain;
77*1b4853f5SAndroid Build Coastguard Worker     use crate::ReadFromDescriptorChain;
78*1b4853f5SAndroid Build Coastguard Worker     use crate::ToDescriptorChain;
79*1b4853f5SAndroid Build Coastguard Worker 
80*1b4853f5SAndroid Build Coastguard Worker     /// Wrapper allowing any structure to be read/written using zerocopy. This obviously should be
81*1b4853f5SAndroid Build Coastguard Worker     /// used with caution and thus is private.
82*1b4853f5SAndroid Build Coastguard Worker     #[repr(transparent)]
83*1b4853f5SAndroid Build Coastguard Worker     struct ForceZeroCopyWrapper<T: Sized>(T);
84*1b4853f5SAndroid Build Coastguard Worker 
85*1b4853f5SAndroid Build Coastguard Worker     unsafe impl<T: Sized> FromZeroes for ForceZeroCopyWrapper<T> {
only_derive_is_allowed_to_implement_this_trait()86*1b4853f5SAndroid Build Coastguard Worker         fn only_derive_is_allowed_to_implement_this_trait() {}
87*1b4853f5SAndroid Build Coastguard Worker     }
88*1b4853f5SAndroid Build Coastguard Worker 
89*1b4853f5SAndroid Build Coastguard Worker     unsafe impl<T: Sized> FromBytes for ForceZeroCopyWrapper<T> {
only_derive_is_allowed_to_implement_this_trait()90*1b4853f5SAndroid Build Coastguard Worker         fn only_derive_is_allowed_to_implement_this_trait() {}
91*1b4853f5SAndroid Build Coastguard Worker     }
92*1b4853f5SAndroid Build Coastguard Worker 
93*1b4853f5SAndroid Build Coastguard Worker     unsafe impl<T: Sized> AsBytes for ForceZeroCopyWrapper<T> {
only_derive_is_allowed_to_implement_this_trait() where Self: Sized,94*1b4853f5SAndroid Build Coastguard Worker         fn only_derive_is_allowed_to_implement_this_trait()
95*1b4853f5SAndroid Build Coastguard Worker         where
96*1b4853f5SAndroid Build Coastguard Worker             Self: Sized,
97*1b4853f5SAndroid Build Coastguard Worker         {
98*1b4853f5SAndroid Build Coastguard Worker         }
99*1b4853f5SAndroid Build Coastguard Worker     }
100*1b4853f5SAndroid Build Coastguard Worker 
101*1b4853f5SAndroid Build Coastguard Worker     impl<T> FromDescriptorChain for ForceZeroCopyWrapper<T> {
read_from_chain<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self>102*1b4853f5SAndroid Build Coastguard Worker         fn read_from_chain<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
103*1b4853f5SAndroid Build Coastguard Worker             reader.read_obj()
104*1b4853f5SAndroid Build Coastguard Worker         }
105*1b4853f5SAndroid Build Coastguard Worker     }
106*1b4853f5SAndroid Build Coastguard Worker 
107*1b4853f5SAndroid Build Coastguard Worker     impl<T> ToDescriptorChain for ForceZeroCopyWrapper<T> {
write_to_chain<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()>108*1b4853f5SAndroid Build Coastguard Worker         fn write_to_chain<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
109*1b4853f5SAndroid Build Coastguard Worker             writer.write_all(self.as_bytes())
110*1b4853f5SAndroid Build Coastguard Worker         }
111*1b4853f5SAndroid Build Coastguard Worker     }
112*1b4853f5SAndroid Build Coastguard Worker 
113*1b4853f5SAndroid Build Coastguard Worker     /// Trait granting implementations of [`FromDescriptorChain`] and [`ToDescriptorChain`] to
114*1b4853f5SAndroid Build Coastguard Worker     /// implementors.
115*1b4853f5SAndroid Build Coastguard Worker     ///
116*1b4853f5SAndroid Build Coastguard Worker     /// # Safety
117*1b4853f5SAndroid Build Coastguard Worker     ///
118*1b4853f5SAndroid Build Coastguard Worker     /// Only types that can be read from an arbitrary stream of data should implement this. This
119*1b4853f5SAndroid Build Coastguard Worker     /// covers all V4L2 types used in ioctls.
120*1b4853f5SAndroid Build Coastguard Worker     unsafe trait ForceZeroCopy {}
121*1b4853f5SAndroid Build Coastguard Worker 
122*1b4853f5SAndroid Build Coastguard Worker     impl<T: ForceZeroCopy> FromDescriptorChain for T {
read_from_chain<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self>123*1b4853f5SAndroid Build Coastguard Worker         fn read_from_chain<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
124*1b4853f5SAndroid Build Coastguard Worker             ForceZeroCopyWrapper::<T>::read_from_chain(reader).map(|r| r.0)
125*1b4853f5SAndroid Build Coastguard Worker         }
126*1b4853f5SAndroid Build Coastguard Worker     }
127*1b4853f5SAndroid Build Coastguard Worker 
128*1b4853f5SAndroid Build Coastguard Worker     impl<T: ForceZeroCopy> ToDescriptorChain for T {
write_to_chain<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()>129*1b4853f5SAndroid Build Coastguard Worker         fn write_to_chain<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
130*1b4853f5SAndroid Build Coastguard Worker             unsafe { std::mem::transmute::<&T, &ForceZeroCopyWrapper<T>>(self) }
131*1b4853f5SAndroid Build Coastguard Worker                 .write_to_chain(writer)
132*1b4853f5SAndroid Build Coastguard Worker         }
133*1b4853f5SAndroid Build Coastguard Worker     }
134*1b4853f5SAndroid Build Coastguard Worker 
135*1b4853f5SAndroid Build Coastguard Worker     // Allows V4L2 types to be read from/written to a descriptor chain.
136*1b4853f5SAndroid Build Coastguard Worker 
137*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for () {}
138*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for u32 {}
139*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for i32 {}
140*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_buffer {}
141*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_standard {}
142*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_input {}
143*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_control {}
144*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_std_id {}
145*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_tuner {}
146*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_audio {}
147*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_plane {}
148*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_format {}
149*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_enc_idx {}
150*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_output {}
151*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_audioout {}
152*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_modulator {}
153*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_frequency {}
154*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_frmsizeenum {}
155*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_frmivalenum {}
156*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_encoder_cmd {}
157*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_decoder_cmd {}
158*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_dv_timings {}
159*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_event_subscription {}
160*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_create_buffers {}
161*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_selection {}
162*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_enum_dv_timings {}
163*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_dv_timings_cap {}
164*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_frequency_band {}
165*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_query_ext_ctrl {}
166*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_queryctrl {}
167*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_querymenu {}
168*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_ext_control {}
169*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_ext_controls {}
170*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_fmtdesc {}
171*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_requestbuffers {}
172*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for bindings::v4l2_streamparm {}
173*1b4853f5SAndroid Build Coastguard Worker 
174*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for crate::protocol::DequeueBufferEvent {}
175*1b4853f5SAndroid Build Coastguard Worker     unsafe impl ForceZeroCopy for crate::protocol::SessionEvent {}
176*1b4853f5SAndroid Build Coastguard Worker }
177*1b4853f5SAndroid Build Coastguard Worker 
178*1b4853f5SAndroid Build Coastguard Worker /// Returns `ENOTTY` to signal that an ioctl is not handled by this device.
179*1b4853f5SAndroid Build Coastguard Worker macro_rules! unhandled_ioctl {
180*1b4853f5SAndroid Build Coastguard Worker     () => {
181*1b4853f5SAndroid Build Coastguard Worker         Err(libc::ENOTTY)
182*1b4853f5SAndroid Build Coastguard Worker     };
183*1b4853f5SAndroid Build Coastguard Worker }
184*1b4853f5SAndroid Build Coastguard Worker 
185*1b4853f5SAndroid Build Coastguard Worker pub type IoctlResult<T> = Result<T, i32>;
186*1b4853f5SAndroid Build Coastguard Worker 
187*1b4853f5SAndroid Build Coastguard Worker /// Trait for implementing ioctls supported by a device.
188*1b4853f5SAndroid Build Coastguard Worker ///
189*1b4853f5SAndroid Build Coastguard Worker /// It provides a default implementation for all ioctls that returns the error code for an
190*1b4853f5SAndroid Build Coastguard Worker /// unsupported ioctl (`ENOTTY`) to the driver. This means that a device just needs to implement
191*1b4853f5SAndroid Build Coastguard Worker /// this trait and override the ioctls it supports in order to provide the expected behavior. All
192*1b4853f5SAndroid Build Coastguard Worker /// parsing and input validation is done by the companion function [`virtio_media_dispatch_ioctl`].
193*1b4853f5SAndroid Build Coastguard Worker #[allow(unused_variables)]
194*1b4853f5SAndroid Build Coastguard Worker pub trait VirtioMediaIoctlHandler {
195*1b4853f5SAndroid Build Coastguard Worker     type Session;
196*1b4853f5SAndroid Build Coastguard Worker 
enum_fmt( &mut self, session: &Self::Session, queue: QueueType, index: u32, ) -> IoctlResult<v4l2_fmtdesc>197*1b4853f5SAndroid Build Coastguard Worker     fn enum_fmt(
198*1b4853f5SAndroid Build Coastguard Worker         &mut self,
199*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
200*1b4853f5SAndroid Build Coastguard Worker         queue: QueueType,
201*1b4853f5SAndroid Build Coastguard Worker         index: u32,
202*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_fmtdesc> {
203*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
204*1b4853f5SAndroid Build Coastguard Worker     }
g_fmt(&mut self, session: &Self::Session, queue: QueueType) -> IoctlResult<v4l2_format>205*1b4853f5SAndroid Build Coastguard Worker     fn g_fmt(&mut self, session: &Self::Session, queue: QueueType) -> IoctlResult<v4l2_format> {
206*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
207*1b4853f5SAndroid Build Coastguard Worker     }
208*1b4853f5SAndroid Build Coastguard Worker     /// Hook for the `VIDIOC_S_FMT` ioctl.
209*1b4853f5SAndroid Build Coastguard Worker     ///
210*1b4853f5SAndroid Build Coastguard Worker     /// `queue` is guaranteed to match `format.type_`.
s_fmt( &mut self, session: &mut Self::Session, queue: QueueType, format: v4l2_format, ) -> IoctlResult<v4l2_format>211*1b4853f5SAndroid Build Coastguard Worker     fn s_fmt(
212*1b4853f5SAndroid Build Coastguard Worker         &mut self,
213*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
214*1b4853f5SAndroid Build Coastguard Worker         queue: QueueType,
215*1b4853f5SAndroid Build Coastguard Worker         format: v4l2_format,
216*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_format> {
217*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
218*1b4853f5SAndroid Build Coastguard Worker     }
reqbufs( &mut self, session: &mut Self::Session, queue: QueueType, memory: MemoryType, count: u32, ) -> IoctlResult<v4l2_requestbuffers>219*1b4853f5SAndroid Build Coastguard Worker     fn reqbufs(
220*1b4853f5SAndroid Build Coastguard Worker         &mut self,
221*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
222*1b4853f5SAndroid Build Coastguard Worker         queue: QueueType,
223*1b4853f5SAndroid Build Coastguard Worker         memory: MemoryType,
224*1b4853f5SAndroid Build Coastguard Worker         count: u32,
225*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_requestbuffers> {
226*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
227*1b4853f5SAndroid Build Coastguard Worker     }
querybuf( &mut self, session: &Self::Session, queue: QueueType, index: u32, ) -> IoctlResult<V4l2Buffer>228*1b4853f5SAndroid Build Coastguard Worker     fn querybuf(
229*1b4853f5SAndroid Build Coastguard Worker         &mut self,
230*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
231*1b4853f5SAndroid Build Coastguard Worker         queue: QueueType,
232*1b4853f5SAndroid Build Coastguard Worker         index: u32,
233*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<V4l2Buffer> {
234*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
235*1b4853f5SAndroid Build Coastguard Worker     }
236*1b4853f5SAndroid Build Coastguard Worker 
237*1b4853f5SAndroid Build Coastguard Worker     // TODO qbuf needs a better structure to represent a buffer and its potential guest buffers.
qbuf( &mut self, session: &mut Self::Session, buffer: V4l2Buffer, guest_regions: Vec<Vec<SgEntry>>, ) -> IoctlResult<V4l2Buffer>238*1b4853f5SAndroid Build Coastguard Worker     fn qbuf(
239*1b4853f5SAndroid Build Coastguard Worker         &mut self,
240*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
241*1b4853f5SAndroid Build Coastguard Worker         buffer: V4l2Buffer,
242*1b4853f5SAndroid Build Coastguard Worker         guest_regions: Vec<Vec<SgEntry>>,
243*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<V4l2Buffer> {
244*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
245*1b4853f5SAndroid Build Coastguard Worker     }
246*1b4853f5SAndroid Build Coastguard Worker 
247*1b4853f5SAndroid Build Coastguard Worker     // TODO expbuf
248*1b4853f5SAndroid Build Coastguard Worker 
streamon(&mut self, session: &mut Self::Session, queue: QueueType) -> IoctlResult<()>249*1b4853f5SAndroid Build Coastguard Worker     fn streamon(&mut self, session: &mut Self::Session, queue: QueueType) -> IoctlResult<()> {
250*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
251*1b4853f5SAndroid Build Coastguard Worker     }
streamoff(&mut self, session: &mut Self::Session, queue: QueueType) -> IoctlResult<()>252*1b4853f5SAndroid Build Coastguard Worker     fn streamoff(&mut self, session: &mut Self::Session, queue: QueueType) -> IoctlResult<()> {
253*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
254*1b4853f5SAndroid Build Coastguard Worker     }
255*1b4853f5SAndroid Build Coastguard Worker 
g_parm( &mut self, session: &Self::Session, queue: QueueType, ) -> IoctlResult<v4l2_streamparm>256*1b4853f5SAndroid Build Coastguard Worker     fn g_parm(
257*1b4853f5SAndroid Build Coastguard Worker         &mut self,
258*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
259*1b4853f5SAndroid Build Coastguard Worker         queue: QueueType,
260*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_streamparm> {
261*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
262*1b4853f5SAndroid Build Coastguard Worker     }
s_parm( &mut self, session: &mut Self::Session, parm: v4l2_streamparm, ) -> IoctlResult<v4l2_streamparm>263*1b4853f5SAndroid Build Coastguard Worker     fn s_parm(
264*1b4853f5SAndroid Build Coastguard Worker         &mut self,
265*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
266*1b4853f5SAndroid Build Coastguard Worker         parm: v4l2_streamparm,
267*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_streamparm> {
268*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
269*1b4853f5SAndroid Build Coastguard Worker     }
270*1b4853f5SAndroid Build Coastguard Worker 
g_std(&mut self, session: &Self::Session) -> IoctlResult<v4l2_std_id>271*1b4853f5SAndroid Build Coastguard Worker     fn g_std(&mut self, session: &Self::Session) -> IoctlResult<v4l2_std_id> {
272*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
273*1b4853f5SAndroid Build Coastguard Worker     }
274*1b4853f5SAndroid Build Coastguard Worker 
s_std(&mut self, session: &mut Self::Session, std: v4l2_std_id) -> IoctlResult<()>275*1b4853f5SAndroid Build Coastguard Worker     fn s_std(&mut self, session: &mut Self::Session, std: v4l2_std_id) -> IoctlResult<()> {
276*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
277*1b4853f5SAndroid Build Coastguard Worker     }
278*1b4853f5SAndroid Build Coastguard Worker 
enumstd(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_standard>279*1b4853f5SAndroid Build Coastguard Worker     fn enumstd(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_standard> {
280*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
281*1b4853f5SAndroid Build Coastguard Worker     }
282*1b4853f5SAndroid Build Coastguard Worker 
enuminput(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_input>283*1b4853f5SAndroid Build Coastguard Worker     fn enuminput(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_input> {
284*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
285*1b4853f5SAndroid Build Coastguard Worker     }
286*1b4853f5SAndroid Build Coastguard Worker 
g_ctrl(&mut self, session: &Self::Session, id: u32) -> IoctlResult<v4l2_control>287*1b4853f5SAndroid Build Coastguard Worker     fn g_ctrl(&mut self, session: &Self::Session, id: u32) -> IoctlResult<v4l2_control> {
288*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
289*1b4853f5SAndroid Build Coastguard Worker     }
290*1b4853f5SAndroid Build Coastguard Worker 
s_ctrl( &mut self, session: &mut Self::Session, id: u32, value: i32, ) -> IoctlResult<v4l2_control>291*1b4853f5SAndroid Build Coastguard Worker     fn s_ctrl(
292*1b4853f5SAndroid Build Coastguard Worker         &mut self,
293*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
294*1b4853f5SAndroid Build Coastguard Worker         id: u32,
295*1b4853f5SAndroid Build Coastguard Worker         value: i32,
296*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_control> {
297*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
298*1b4853f5SAndroid Build Coastguard Worker     }
299*1b4853f5SAndroid Build Coastguard Worker 
g_tuner(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_tuner>300*1b4853f5SAndroid Build Coastguard Worker     fn g_tuner(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_tuner> {
301*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
302*1b4853f5SAndroid Build Coastguard Worker     }
303*1b4853f5SAndroid Build Coastguard Worker 
s_tuner( &mut self, session: &mut Self::Session, index: u32, mode: TunerMode, ) -> IoctlResult<()>304*1b4853f5SAndroid Build Coastguard Worker     fn s_tuner(
305*1b4853f5SAndroid Build Coastguard Worker         &mut self,
306*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
307*1b4853f5SAndroid Build Coastguard Worker         index: u32,
308*1b4853f5SAndroid Build Coastguard Worker         mode: TunerMode,
309*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<()> {
310*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
311*1b4853f5SAndroid Build Coastguard Worker     }
312*1b4853f5SAndroid Build Coastguard Worker 
g_audio(&mut self, session: &Self::Session) -> IoctlResult<v4l2_audio>313*1b4853f5SAndroid Build Coastguard Worker     fn g_audio(&mut self, session: &Self::Session) -> IoctlResult<v4l2_audio> {
314*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
315*1b4853f5SAndroid Build Coastguard Worker     }
316*1b4853f5SAndroid Build Coastguard Worker 
s_audio( &mut self, session: &mut Self::Session, index: u32, mode: Option<AudioMode>, ) -> IoctlResult<()>317*1b4853f5SAndroid Build Coastguard Worker     fn s_audio(
318*1b4853f5SAndroid Build Coastguard Worker         &mut self,
319*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
320*1b4853f5SAndroid Build Coastguard Worker         index: u32,
321*1b4853f5SAndroid Build Coastguard Worker         mode: Option<AudioMode>,
322*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<()> {
323*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
324*1b4853f5SAndroid Build Coastguard Worker     }
325*1b4853f5SAndroid Build Coastguard Worker 
queryctrl( &mut self, session: &Self::Session, id: CtrlId, flags: QueryCtrlFlags, ) -> IoctlResult<v4l2_queryctrl>326*1b4853f5SAndroid Build Coastguard Worker     fn queryctrl(
327*1b4853f5SAndroid Build Coastguard Worker         &mut self,
328*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
329*1b4853f5SAndroid Build Coastguard Worker         id: CtrlId,
330*1b4853f5SAndroid Build Coastguard Worker         flags: QueryCtrlFlags,
331*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_queryctrl> {
332*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
333*1b4853f5SAndroid Build Coastguard Worker     }
334*1b4853f5SAndroid Build Coastguard Worker 
querymenu( &mut self, session: &Self::Session, id: u32, index: u32, ) -> IoctlResult<v4l2_querymenu>335*1b4853f5SAndroid Build Coastguard Worker     fn querymenu(
336*1b4853f5SAndroid Build Coastguard Worker         &mut self,
337*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
338*1b4853f5SAndroid Build Coastguard Worker         id: u32,
339*1b4853f5SAndroid Build Coastguard Worker         index: u32,
340*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_querymenu> {
341*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
342*1b4853f5SAndroid Build Coastguard Worker     }
343*1b4853f5SAndroid Build Coastguard Worker 
g_input(&mut self, session: &Self::Session) -> IoctlResult<i32>344*1b4853f5SAndroid Build Coastguard Worker     fn g_input(&mut self, session: &Self::Session) -> IoctlResult<i32> {
345*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
346*1b4853f5SAndroid Build Coastguard Worker     }
347*1b4853f5SAndroid Build Coastguard Worker 
s_input(&mut self, session: &mut Self::Session, input: i32) -> IoctlResult<i32>348*1b4853f5SAndroid Build Coastguard Worker     fn s_input(&mut self, session: &mut Self::Session, input: i32) -> IoctlResult<i32> {
349*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
350*1b4853f5SAndroid Build Coastguard Worker     }
351*1b4853f5SAndroid Build Coastguard Worker 
g_output(&mut self, session: &Self::Session) -> IoctlResult<i32>352*1b4853f5SAndroid Build Coastguard Worker     fn g_output(&mut self, session: &Self::Session) -> IoctlResult<i32> {
353*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
354*1b4853f5SAndroid Build Coastguard Worker     }
355*1b4853f5SAndroid Build Coastguard Worker 
s_output(&mut self, session: &mut Self::Session, output: i32) -> IoctlResult<i32>356*1b4853f5SAndroid Build Coastguard Worker     fn s_output(&mut self, session: &mut Self::Session, output: i32) -> IoctlResult<i32> {
357*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
358*1b4853f5SAndroid Build Coastguard Worker     }
359*1b4853f5SAndroid Build Coastguard Worker 
enumoutput(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_output>360*1b4853f5SAndroid Build Coastguard Worker     fn enumoutput(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_output> {
361*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
362*1b4853f5SAndroid Build Coastguard Worker     }
363*1b4853f5SAndroid Build Coastguard Worker 
g_audout(&mut self, session: &Self::Session) -> IoctlResult<v4l2_audioout>364*1b4853f5SAndroid Build Coastguard Worker     fn g_audout(&mut self, session: &Self::Session) -> IoctlResult<v4l2_audioout> {
365*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
366*1b4853f5SAndroid Build Coastguard Worker     }
367*1b4853f5SAndroid Build Coastguard Worker 
s_audout(&mut self, session: &mut Self::Session, index: u32) -> IoctlResult<()>368*1b4853f5SAndroid Build Coastguard Worker     fn s_audout(&mut self, session: &mut Self::Session, index: u32) -> IoctlResult<()> {
369*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
370*1b4853f5SAndroid Build Coastguard Worker     }
371*1b4853f5SAndroid Build Coastguard Worker 
g_modulator(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_modulator>372*1b4853f5SAndroid Build Coastguard Worker     fn g_modulator(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_modulator> {
373*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
374*1b4853f5SAndroid Build Coastguard Worker     }
375*1b4853f5SAndroid Build Coastguard Worker 
s_modulator( &mut self, session: &mut Self::Session, index: u32, flags: TunerTransmissionFlags, ) -> IoctlResult<()>376*1b4853f5SAndroid Build Coastguard Worker     fn s_modulator(
377*1b4853f5SAndroid Build Coastguard Worker         &mut self,
378*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
379*1b4853f5SAndroid Build Coastguard Worker         index: u32,
380*1b4853f5SAndroid Build Coastguard Worker         flags: TunerTransmissionFlags,
381*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<()> {
382*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
383*1b4853f5SAndroid Build Coastguard Worker     }
384*1b4853f5SAndroid Build Coastguard Worker 
g_frequency(&mut self, session: &Self::Session, tuner: u32) -> IoctlResult<v4l2_frequency>385*1b4853f5SAndroid Build Coastguard Worker     fn g_frequency(&mut self, session: &Self::Session, tuner: u32) -> IoctlResult<v4l2_frequency> {
386*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
387*1b4853f5SAndroid Build Coastguard Worker     }
388*1b4853f5SAndroid Build Coastguard Worker 
s_frequency( &mut self, session: &mut Self::Session, tuner: u32, type_: TunerType, frequency: u32, ) -> IoctlResult<()>389*1b4853f5SAndroid Build Coastguard Worker     fn s_frequency(
390*1b4853f5SAndroid Build Coastguard Worker         &mut self,
391*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
392*1b4853f5SAndroid Build Coastguard Worker         tuner: u32,
393*1b4853f5SAndroid Build Coastguard Worker         type_: TunerType,
394*1b4853f5SAndroid Build Coastguard Worker         frequency: u32,
395*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<()> {
396*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
397*1b4853f5SAndroid Build Coastguard Worker     }
398*1b4853f5SAndroid Build Coastguard Worker 
querystd(&mut self, session: &Self::Session) -> IoctlResult<v4l2_std_id>399*1b4853f5SAndroid Build Coastguard Worker     fn querystd(&mut self, session: &Self::Session) -> IoctlResult<v4l2_std_id> {
400*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
401*1b4853f5SAndroid Build Coastguard Worker     }
402*1b4853f5SAndroid Build Coastguard Worker 
403*1b4853f5SAndroid Build Coastguard Worker     /// Hook for the `VIDIOC_TRY_FMT` ioctl.
404*1b4853f5SAndroid Build Coastguard Worker     ///
405*1b4853f5SAndroid Build Coastguard Worker     /// `queue` is guaranteed to match `format.type_`.
try_fmt( &mut self, session: &Self::Session, queue: QueueType, format: v4l2_format, ) -> IoctlResult<v4l2_format>406*1b4853f5SAndroid Build Coastguard Worker     fn try_fmt(
407*1b4853f5SAndroid Build Coastguard Worker         &mut self,
408*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
409*1b4853f5SAndroid Build Coastguard Worker         queue: QueueType,
410*1b4853f5SAndroid Build Coastguard Worker         format: v4l2_format,
411*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_format> {
412*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
413*1b4853f5SAndroid Build Coastguard Worker     }
414*1b4853f5SAndroid Build Coastguard Worker 
enumaudio(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_audio>415*1b4853f5SAndroid Build Coastguard Worker     fn enumaudio(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_audio> {
416*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
417*1b4853f5SAndroid Build Coastguard Worker     }
418*1b4853f5SAndroid Build Coastguard Worker 
enumaudout(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_audioout>419*1b4853f5SAndroid Build Coastguard Worker     fn enumaudout(&mut self, session: &Self::Session, index: u32) -> IoctlResult<v4l2_audioout> {
420*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
421*1b4853f5SAndroid Build Coastguard Worker     }
422*1b4853f5SAndroid Build Coastguard Worker 
423*1b4853f5SAndroid Build Coastguard Worker     /// Ext control ioctls modify `ctrls` and `ctrl_array` in place instead of returning them.
g_ext_ctrls( &mut self, session: &Self::Session, which: CtrlWhich, ctrls: &mut v4l2_ext_controls, ctrl_array: &mut Vec<v4l2_ext_control>, user_regions: Vec<Vec<SgEntry>>, ) -> IoctlResult<()>424*1b4853f5SAndroid Build Coastguard Worker     fn g_ext_ctrls(
425*1b4853f5SAndroid Build Coastguard Worker         &mut self,
426*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
427*1b4853f5SAndroid Build Coastguard Worker         which: CtrlWhich,
428*1b4853f5SAndroid Build Coastguard Worker         ctrls: &mut v4l2_ext_controls,
429*1b4853f5SAndroid Build Coastguard Worker         ctrl_array: &mut Vec<v4l2_ext_control>,
430*1b4853f5SAndroid Build Coastguard Worker         user_regions: Vec<Vec<SgEntry>>,
431*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<()> {
432*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
433*1b4853f5SAndroid Build Coastguard Worker     }
434*1b4853f5SAndroid Build Coastguard Worker     /// Ext control ioctls modify `ctrls` and `ctrl_array` in place instead of returning them.
s_ext_ctrls( &mut self, session: &mut Self::Session, which: CtrlWhich, ctrls: &mut v4l2_ext_controls, ctrl_array: &mut Vec<v4l2_ext_control>, user_regions: Vec<Vec<SgEntry>>, ) -> IoctlResult<()>435*1b4853f5SAndroid Build Coastguard Worker     fn s_ext_ctrls(
436*1b4853f5SAndroid Build Coastguard Worker         &mut self,
437*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
438*1b4853f5SAndroid Build Coastguard Worker         which: CtrlWhich,
439*1b4853f5SAndroid Build Coastguard Worker         ctrls: &mut v4l2_ext_controls,
440*1b4853f5SAndroid Build Coastguard Worker         ctrl_array: &mut Vec<v4l2_ext_control>,
441*1b4853f5SAndroid Build Coastguard Worker         user_regions: Vec<Vec<SgEntry>>,
442*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<()> {
443*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
444*1b4853f5SAndroid Build Coastguard Worker     }
445*1b4853f5SAndroid Build Coastguard Worker     /// Ext control ioctls modify `ctrls` and `ctrl_array` in place instead of returning them.
try_ext_ctrls( &mut self, session: &Self::Session, which: CtrlWhich, ctrls: &mut v4l2_ext_controls, ctrl_array: &mut Vec<v4l2_ext_control>, user_regions: Vec<Vec<SgEntry>>, ) -> IoctlResult<()>446*1b4853f5SAndroid Build Coastguard Worker     fn try_ext_ctrls(
447*1b4853f5SAndroid Build Coastguard Worker         &mut self,
448*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
449*1b4853f5SAndroid Build Coastguard Worker         which: CtrlWhich,
450*1b4853f5SAndroid Build Coastguard Worker         ctrls: &mut v4l2_ext_controls,
451*1b4853f5SAndroid Build Coastguard Worker         ctrl_array: &mut Vec<v4l2_ext_control>,
452*1b4853f5SAndroid Build Coastguard Worker         user_regions: Vec<Vec<SgEntry>>,
453*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<()> {
454*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
455*1b4853f5SAndroid Build Coastguard Worker     }
456*1b4853f5SAndroid Build Coastguard Worker 
enum_framesizes( &mut self, session: &Self::Session, index: u32, pixel_format: u32, ) -> IoctlResult<v4l2_frmsizeenum>457*1b4853f5SAndroid Build Coastguard Worker     fn enum_framesizes(
458*1b4853f5SAndroid Build Coastguard Worker         &mut self,
459*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
460*1b4853f5SAndroid Build Coastguard Worker         index: u32,
461*1b4853f5SAndroid Build Coastguard Worker         pixel_format: u32,
462*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_frmsizeenum> {
463*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
464*1b4853f5SAndroid Build Coastguard Worker     }
465*1b4853f5SAndroid Build Coastguard Worker 
enum_frameintervals( &mut self, session: &Self::Session, index: u32, pixel_format: u32, width: u32, height: u32, ) -> IoctlResult<v4l2_frmivalenum>466*1b4853f5SAndroid Build Coastguard Worker     fn enum_frameintervals(
467*1b4853f5SAndroid Build Coastguard Worker         &mut self,
468*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
469*1b4853f5SAndroid Build Coastguard Worker         index: u32,
470*1b4853f5SAndroid Build Coastguard Worker         pixel_format: u32,
471*1b4853f5SAndroid Build Coastguard Worker         width: u32,
472*1b4853f5SAndroid Build Coastguard Worker         height: u32,
473*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_frmivalenum> {
474*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
475*1b4853f5SAndroid Build Coastguard Worker     }
476*1b4853f5SAndroid Build Coastguard Worker 
g_enc_index(&mut self, session: &Self::Session) -> IoctlResult<v4l2_enc_idx>477*1b4853f5SAndroid Build Coastguard Worker     fn g_enc_index(&mut self, session: &Self::Session) -> IoctlResult<v4l2_enc_idx> {
478*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
479*1b4853f5SAndroid Build Coastguard Worker     }
480*1b4853f5SAndroid Build Coastguard Worker 
encoder_cmd( &mut self, session: &mut Self::Session, cmd: v4l2_encoder_cmd, ) -> IoctlResult<v4l2_encoder_cmd>481*1b4853f5SAndroid Build Coastguard Worker     fn encoder_cmd(
482*1b4853f5SAndroid Build Coastguard Worker         &mut self,
483*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
484*1b4853f5SAndroid Build Coastguard Worker         cmd: v4l2_encoder_cmd,
485*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_encoder_cmd> {
486*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
487*1b4853f5SAndroid Build Coastguard Worker     }
488*1b4853f5SAndroid Build Coastguard Worker 
try_encoder_cmd( &mut self, session: &Self::Session, cmd: v4l2_encoder_cmd, ) -> IoctlResult<v4l2_encoder_cmd>489*1b4853f5SAndroid Build Coastguard Worker     fn try_encoder_cmd(
490*1b4853f5SAndroid Build Coastguard Worker         &mut self,
491*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
492*1b4853f5SAndroid Build Coastguard Worker         cmd: v4l2_encoder_cmd,
493*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_encoder_cmd> {
494*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
495*1b4853f5SAndroid Build Coastguard Worker     }
496*1b4853f5SAndroid Build Coastguard Worker 
s_dv_timings( &mut self, session: &mut Self::Session, timings: v4l2_dv_timings, ) -> IoctlResult<v4l2_dv_timings>497*1b4853f5SAndroid Build Coastguard Worker     fn s_dv_timings(
498*1b4853f5SAndroid Build Coastguard Worker         &mut self,
499*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
500*1b4853f5SAndroid Build Coastguard Worker         timings: v4l2_dv_timings,
501*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_dv_timings> {
502*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
503*1b4853f5SAndroid Build Coastguard Worker     }
504*1b4853f5SAndroid Build Coastguard Worker 
g_dv_timings(&mut self, session: &Self::Session) -> IoctlResult<v4l2_dv_timings>505*1b4853f5SAndroid Build Coastguard Worker     fn g_dv_timings(&mut self, session: &Self::Session) -> IoctlResult<v4l2_dv_timings> {
506*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
507*1b4853f5SAndroid Build Coastguard Worker     }
508*1b4853f5SAndroid Build Coastguard Worker 
subscribe_event( &mut self, session: &mut Self::Session, event: V4l2EventType, flags: SubscribeEventFlags, ) -> IoctlResult<()>509*1b4853f5SAndroid Build Coastguard Worker     fn subscribe_event(
510*1b4853f5SAndroid Build Coastguard Worker         &mut self,
511*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
512*1b4853f5SAndroid Build Coastguard Worker         event: V4l2EventType,
513*1b4853f5SAndroid Build Coastguard Worker         flags: SubscribeEventFlags,
514*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<()> {
515*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
516*1b4853f5SAndroid Build Coastguard Worker     }
517*1b4853f5SAndroid Build Coastguard Worker 
unsubscribe_event( &mut self, session: &mut Self::Session, event: v4l2_event_subscription, ) -> IoctlResult<()>518*1b4853f5SAndroid Build Coastguard Worker     fn unsubscribe_event(
519*1b4853f5SAndroid Build Coastguard Worker         &mut self,
520*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
521*1b4853f5SAndroid Build Coastguard Worker         event: v4l2_event_subscription,
522*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<()> {
523*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
524*1b4853f5SAndroid Build Coastguard Worker     }
525*1b4853f5SAndroid Build Coastguard Worker 
526*1b4853f5SAndroid Build Coastguard Worker     /// `queue` and `memory` are validated versions of the information in `create_buffers`.
527*1b4853f5SAndroid Build Coastguard Worker     ///
528*1b4853f5SAndroid Build Coastguard Worker     /// `create_buffers` is modified in place and returned to the guest event in case of error.
create_bufs( &mut self, session: &mut Self::Session, count: u32, queue: QueueType, memory: MemoryType, format: v4l2_format, ) -> IoctlResult<v4l2_create_buffers>529*1b4853f5SAndroid Build Coastguard Worker     fn create_bufs(
530*1b4853f5SAndroid Build Coastguard Worker         &mut self,
531*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
532*1b4853f5SAndroid Build Coastguard Worker         count: u32,
533*1b4853f5SAndroid Build Coastguard Worker         queue: QueueType,
534*1b4853f5SAndroid Build Coastguard Worker         memory: MemoryType,
535*1b4853f5SAndroid Build Coastguard Worker         format: v4l2_format,
536*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_create_buffers> {
537*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
538*1b4853f5SAndroid Build Coastguard Worker     }
539*1b4853f5SAndroid Build Coastguard Worker 
540*1b4853f5SAndroid Build Coastguard Worker     // TODO like qbuf, this needs a better structure to represent a buffer and its potential guest
541*1b4853f5SAndroid Build Coastguard Worker     // buffers.
prepare_buf( &mut self, session: &mut Self::Session, buffer: V4l2Buffer, guest_regions: Vec<Vec<SgEntry>>, ) -> IoctlResult<V4l2Buffer>542*1b4853f5SAndroid Build Coastguard Worker     fn prepare_buf(
543*1b4853f5SAndroid Build Coastguard Worker         &mut self,
544*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
545*1b4853f5SAndroid Build Coastguard Worker         buffer: V4l2Buffer,
546*1b4853f5SAndroid Build Coastguard Worker         guest_regions: Vec<Vec<SgEntry>>,
547*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<V4l2Buffer> {
548*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
549*1b4853f5SAndroid Build Coastguard Worker     }
550*1b4853f5SAndroid Build Coastguard Worker 
g_selection( &mut self, session: &Self::Session, sel_type: SelectionType, sel_target: SelectionTarget, ) -> IoctlResult<v4l2_rect>551*1b4853f5SAndroid Build Coastguard Worker     fn g_selection(
552*1b4853f5SAndroid Build Coastguard Worker         &mut self,
553*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
554*1b4853f5SAndroid Build Coastguard Worker         sel_type: SelectionType,
555*1b4853f5SAndroid Build Coastguard Worker         sel_target: SelectionTarget,
556*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_rect> {
557*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
558*1b4853f5SAndroid Build Coastguard Worker     }
559*1b4853f5SAndroid Build Coastguard Worker 
s_selection( &mut self, session: &mut Self::Session, sel_type: SelectionType, sel_target: SelectionTarget, sel_rect: v4l2_rect, sel_flags: SelectionFlags, ) -> IoctlResult<v4l2_rect>560*1b4853f5SAndroid Build Coastguard Worker     fn s_selection(
561*1b4853f5SAndroid Build Coastguard Worker         &mut self,
562*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
563*1b4853f5SAndroid Build Coastguard Worker         sel_type: SelectionType,
564*1b4853f5SAndroid Build Coastguard Worker         sel_target: SelectionTarget,
565*1b4853f5SAndroid Build Coastguard Worker         sel_rect: v4l2_rect,
566*1b4853f5SAndroid Build Coastguard Worker         sel_flags: SelectionFlags,
567*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_rect> {
568*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
569*1b4853f5SAndroid Build Coastguard Worker     }
570*1b4853f5SAndroid Build Coastguard Worker 
decoder_cmd( &mut self, session: &mut Self::Session, cmd: v4l2_decoder_cmd, ) -> IoctlResult<v4l2_decoder_cmd>571*1b4853f5SAndroid Build Coastguard Worker     fn decoder_cmd(
572*1b4853f5SAndroid Build Coastguard Worker         &mut self,
573*1b4853f5SAndroid Build Coastguard Worker         session: &mut Self::Session,
574*1b4853f5SAndroid Build Coastguard Worker         cmd: v4l2_decoder_cmd,
575*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_decoder_cmd> {
576*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
577*1b4853f5SAndroid Build Coastguard Worker     }
578*1b4853f5SAndroid Build Coastguard Worker 
try_decoder_cmd( &mut self, session: &Self::Session, cmd: v4l2_decoder_cmd, ) -> IoctlResult<v4l2_decoder_cmd>579*1b4853f5SAndroid Build Coastguard Worker     fn try_decoder_cmd(
580*1b4853f5SAndroid Build Coastguard Worker         &mut self,
581*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
582*1b4853f5SAndroid Build Coastguard Worker         cmd: v4l2_decoder_cmd,
583*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_decoder_cmd> {
584*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
585*1b4853f5SAndroid Build Coastguard Worker     }
586*1b4853f5SAndroid Build Coastguard Worker 
enum_dv_timings( &mut self, session: &Self::Session, index: u32, ) -> IoctlResult<v4l2_dv_timings>587*1b4853f5SAndroid Build Coastguard Worker     fn enum_dv_timings(
588*1b4853f5SAndroid Build Coastguard Worker         &mut self,
589*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
590*1b4853f5SAndroid Build Coastguard Worker         index: u32,
591*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_dv_timings> {
592*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
593*1b4853f5SAndroid Build Coastguard Worker     }
594*1b4853f5SAndroid Build Coastguard Worker 
query_dv_timings(&mut self, session: &Self::Session) -> IoctlResult<v4l2_dv_timings>595*1b4853f5SAndroid Build Coastguard Worker     fn query_dv_timings(&mut self, session: &Self::Session) -> IoctlResult<v4l2_dv_timings> {
596*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
597*1b4853f5SAndroid Build Coastguard Worker     }
598*1b4853f5SAndroid Build Coastguard Worker 
dv_timings_cap(&self, session: &Self::Session) -> IoctlResult<v4l2_dv_timings_cap>599*1b4853f5SAndroid Build Coastguard Worker     fn dv_timings_cap(&self, session: &Self::Session) -> IoctlResult<v4l2_dv_timings_cap> {
600*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
601*1b4853f5SAndroid Build Coastguard Worker     }
602*1b4853f5SAndroid Build Coastguard Worker 
enum_freq_bands( &self, session: &Self::Session, tuner: u32, type_: TunerType, index: u32, ) -> IoctlResult<v4l2_frequency_band>603*1b4853f5SAndroid Build Coastguard Worker     fn enum_freq_bands(
604*1b4853f5SAndroid Build Coastguard Worker         &self,
605*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
606*1b4853f5SAndroid Build Coastguard Worker         tuner: u32,
607*1b4853f5SAndroid Build Coastguard Worker         type_: TunerType,
608*1b4853f5SAndroid Build Coastguard Worker         index: u32,
609*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_frequency_band> {
610*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
611*1b4853f5SAndroid Build Coastguard Worker     }
612*1b4853f5SAndroid Build Coastguard Worker 
query_ext_ctrl( &mut self, session: &Self::Session, id: CtrlId, flags: QueryCtrlFlags, ) -> IoctlResult<v4l2_query_ext_ctrl>613*1b4853f5SAndroid Build Coastguard Worker     fn query_ext_ctrl(
614*1b4853f5SAndroid Build Coastguard Worker         &mut self,
615*1b4853f5SAndroid Build Coastguard Worker         session: &Self::Session,
616*1b4853f5SAndroid Build Coastguard Worker         id: CtrlId,
617*1b4853f5SAndroid Build Coastguard Worker         flags: QueryCtrlFlags,
618*1b4853f5SAndroid Build Coastguard Worker     ) -> IoctlResult<v4l2_query_ext_ctrl> {
619*1b4853f5SAndroid Build Coastguard Worker         unhandled_ioctl!()
620*1b4853f5SAndroid Build Coastguard Worker     }
621*1b4853f5SAndroid Build Coastguard Worker }
622*1b4853f5SAndroid Build Coastguard Worker 
623*1b4853f5SAndroid Build Coastguard Worker /// Writes a `ENOTTY` error response into `writer` to signal that an ioctl is not implemented by
624*1b4853f5SAndroid Build Coastguard Worker /// the device.
invalid_ioctl<W: std::io::Write>(code: V4l2Ioctl, writer: &mut W) -> IoResult<()>625*1b4853f5SAndroid Build Coastguard Worker fn invalid_ioctl<W: std::io::Write>(code: V4l2Ioctl, writer: &mut W) -> IoResult<()> {
626*1b4853f5SAndroid Build Coastguard Worker     writer.write_err_response(libc::ENOTTY).map_err(|e| {
627*1b4853f5SAndroid Build Coastguard Worker         log::error!(
628*1b4853f5SAndroid Build Coastguard Worker             "failed to write error response for invalid ioctl {:?}: {:#}",
629*1b4853f5SAndroid Build Coastguard Worker             code,
630*1b4853f5SAndroid Build Coastguard Worker             e
631*1b4853f5SAndroid Build Coastguard Worker         );
632*1b4853f5SAndroid Build Coastguard Worker         e
633*1b4853f5SAndroid Build Coastguard Worker     })
634*1b4853f5SAndroid Build Coastguard Worker }
635*1b4853f5SAndroid Build Coastguard Worker 
636*1b4853f5SAndroid Build Coastguard Worker /// Reads a SG list of guest physical addresses passed from the driver and returns it.
get_userptr_regions<R: std::io::Read>(r: &mut R, size: usize) -> anyhow::Result<Vec<SgEntry>>637*1b4853f5SAndroid Build Coastguard Worker fn get_userptr_regions<R: std::io::Read>(r: &mut R, size: usize) -> anyhow::Result<Vec<SgEntry>> {
638*1b4853f5SAndroid Build Coastguard Worker     let mut bytes_taken = 0;
639*1b4853f5SAndroid Build Coastguard Worker     let mut res = Vec::new();
640*1b4853f5SAndroid Build Coastguard Worker 
641*1b4853f5SAndroid Build Coastguard Worker     while bytes_taken < size {
642*1b4853f5SAndroid Build Coastguard Worker         let sg_entry = r.read_obj::<SgEntry>()?;
643*1b4853f5SAndroid Build Coastguard Worker         bytes_taken += sg_entry.len as usize;
644*1b4853f5SAndroid Build Coastguard Worker         res.push(sg_entry);
645*1b4853f5SAndroid Build Coastguard Worker     }
646*1b4853f5SAndroid Build Coastguard Worker 
647*1b4853f5SAndroid Build Coastguard Worker     Ok(res)
648*1b4853f5SAndroid Build Coastguard Worker }
649*1b4853f5SAndroid Build Coastguard Worker 
650*1b4853f5SAndroid Build Coastguard Worker /// Allows to easily read a `v4l2_buffer` of `USERPTR` memory type and its associated guest-side
651*1b4853f5SAndroid Build Coastguard Worker /// buffers from a descriptor chain.
652*1b4853f5SAndroid Build Coastguard Worker impl FromDescriptorChain for (V4l2Buffer, Vec<Vec<SgEntry>>) {
read_from_chain<R: std::io::Read>(reader: &mut R) -> IoResult<Self> where Self: Sized,653*1b4853f5SAndroid Build Coastguard Worker     fn read_from_chain<R: std::io::Read>(reader: &mut R) -> IoResult<Self>
654*1b4853f5SAndroid Build Coastguard Worker     where
655*1b4853f5SAndroid Build Coastguard Worker         Self: Sized,
656*1b4853f5SAndroid Build Coastguard Worker     {
657*1b4853f5SAndroid Build Coastguard Worker         let v4l2_buffer = v4l2_buffer::read_from_chain(reader)?;
658*1b4853f5SAndroid Build Coastguard Worker         let queue = match QueueType::n(v4l2_buffer.type_) {
659*1b4853f5SAndroid Build Coastguard Worker             Some(queue) => queue,
660*1b4853f5SAndroid Build Coastguard Worker             None => return Err(std::io::ErrorKind::InvalidData.into()),
661*1b4853f5SAndroid Build Coastguard Worker         };
662*1b4853f5SAndroid Build Coastguard Worker 
663*1b4853f5SAndroid Build Coastguard Worker         let v4l2_planes = if queue.is_multiplanar() && v4l2_buffer.length > 0 {
664*1b4853f5SAndroid Build Coastguard Worker             if v4l2_buffer.length > v4l2r::bindings::VIDEO_MAX_PLANES {
665*1b4853f5SAndroid Build Coastguard Worker                 return Err(std::io::ErrorKind::InvalidData.into());
666*1b4853f5SAndroid Build Coastguard Worker             }
667*1b4853f5SAndroid Build Coastguard Worker 
668*1b4853f5SAndroid Build Coastguard Worker             let planes: [v4l2r::bindings::v4l2_plane; v4l2r::bindings::VIDEO_MAX_PLANES as usize] =
669*1b4853f5SAndroid Build Coastguard Worker                 (0..v4l2_buffer.length as usize)
670*1b4853f5SAndroid Build Coastguard Worker                     .map(|_| v4l2_plane::read_from_chain(reader))
671*1b4853f5SAndroid Build Coastguard Worker                     .collect::<IoResult<Vec<_>>>()?
672*1b4853f5SAndroid Build Coastguard Worker                     .into_iter()
673*1b4853f5SAndroid Build Coastguard Worker                     .chain(std::iter::repeat(Default::default()))
674*1b4853f5SAndroid Build Coastguard Worker                     .take(v4l2r::bindings::VIDEO_MAX_PLANES as usize)
675*1b4853f5SAndroid Build Coastguard Worker                     .collect::<Vec<_>>()
676*1b4853f5SAndroid Build Coastguard Worker                     .try_into()
677*1b4853f5SAndroid Build Coastguard Worker                     .map_err(|_| std::io::Error::from(std::io::ErrorKind::InvalidData))?;
678*1b4853f5SAndroid Build Coastguard Worker             Some(planes)
679*1b4853f5SAndroid Build Coastguard Worker         } else {
680*1b4853f5SAndroid Build Coastguard Worker             None
681*1b4853f5SAndroid Build Coastguard Worker         };
682*1b4853f5SAndroid Build Coastguard Worker 
683*1b4853f5SAndroid Build Coastguard Worker         let v4l2_buffer = V4l2Buffer::try_from(UncheckedV4l2Buffer(v4l2_buffer, v4l2_planes))
684*1b4853f5SAndroid Build Coastguard Worker             .map_err(|_| std::io::Error::from(std::io::ErrorKind::InvalidData))?;
685*1b4853f5SAndroid Build Coastguard Worker 
686*1b4853f5SAndroid Build Coastguard Worker         // Read the `MemRegion`s of all planes if the buffer is `USERPTR`.
687*1b4853f5SAndroid Build Coastguard Worker         let guest_regions = if let V4l2PlanesWithBacking::UserPtr(planes) =
688*1b4853f5SAndroid Build Coastguard Worker             v4l2_buffer.planes_with_backing_iter()
689*1b4853f5SAndroid Build Coastguard Worker         {
690*1b4853f5SAndroid Build Coastguard Worker             planes
691*1b4853f5SAndroid Build Coastguard Worker                 .filter(|p| *p.length > 0)
692*1b4853f5SAndroid Build Coastguard Worker                 .map(|p| {
693*1b4853f5SAndroid Build Coastguard Worker                     get_userptr_regions(reader, *p.length as usize)
694*1b4853f5SAndroid Build Coastguard Worker                         .map_err(|_| std::io::ErrorKind::InvalidData.into())
695*1b4853f5SAndroid Build Coastguard Worker                 })
696*1b4853f5SAndroid Build Coastguard Worker                 .collect::<IoResult<Vec<_>>>()?
697*1b4853f5SAndroid Build Coastguard Worker         } else {
698*1b4853f5SAndroid Build Coastguard Worker             vec![]
699*1b4853f5SAndroid Build Coastguard Worker         };
700*1b4853f5SAndroid Build Coastguard Worker 
701*1b4853f5SAndroid Build Coastguard Worker         Ok((v4l2_buffer, guest_regions))
702*1b4853f5SAndroid Build Coastguard Worker     }
703*1b4853f5SAndroid Build Coastguard Worker }
704*1b4853f5SAndroid Build Coastguard Worker 
705*1b4853f5SAndroid Build Coastguard Worker /// Write a `v4l2_buffer` to a descriptor chain, while ensuring the number of planes written is not
706*1b4853f5SAndroid Build Coastguard Worker /// larger than a limit (i.e. the maximum number of planes that the descriptor chain can receive).
707*1b4853f5SAndroid Build Coastguard Worker impl ToDescriptorChain for (V4l2Buffer, usize) {
write_to_chain<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()>708*1b4853f5SAndroid Build Coastguard Worker     fn write_to_chain<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
709*1b4853f5SAndroid Build Coastguard Worker         let mut v4l2_buffer = *self.0.as_v4l2_buffer();
710*1b4853f5SAndroid Build Coastguard Worker         // If the buffer is multiplanar, nullify the `planes` pointer to avoid leaking host
711*1b4853f5SAndroid Build Coastguard Worker         // addresses.
712*1b4853f5SAndroid Build Coastguard Worker         if self.0.queue().is_multiplanar() {
713*1b4853f5SAndroid Build Coastguard Worker             v4l2_buffer.m.planes = std::ptr::null_mut();
714*1b4853f5SAndroid Build Coastguard Worker         }
715*1b4853f5SAndroid Build Coastguard Worker         v4l2_buffer.write_to_chain(writer)?;
716*1b4853f5SAndroid Build Coastguard Worker 
717*1b4853f5SAndroid Build Coastguard Worker         // Write plane information if the buffer is multiplanar. Limit the number of planes to the
718*1b4853f5SAndroid Build Coastguard Worker         // upper bound we were given.
719*1b4853f5SAndroid Build Coastguard Worker         for plane in self.0.as_v4l2_planes().iter().take(self.1) {
720*1b4853f5SAndroid Build Coastguard Worker             plane.write_to_chain(writer)?;
721*1b4853f5SAndroid Build Coastguard Worker         }
722*1b4853f5SAndroid Build Coastguard Worker 
723*1b4853f5SAndroid Build Coastguard Worker         Ok(())
724*1b4853f5SAndroid Build Coastguard Worker     }
725*1b4853f5SAndroid Build Coastguard Worker }
726*1b4853f5SAndroid Build Coastguard Worker 
727*1b4853f5SAndroid Build Coastguard Worker /// Allows to easily read a `v4l2_ext_controls` struct, its array of controls, and the SG list of
728*1b4853f5SAndroid Build Coastguard Worker /// the buffers pointed to by the controls from a descriptor chain.
729*1b4853f5SAndroid Build Coastguard Worker impl FromDescriptorChain for (v4l2_ext_controls, Vec<v4l2_ext_control>, Vec<Vec<SgEntry>>) {
read_from_chain<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> where Self: Sized,730*1b4853f5SAndroid Build Coastguard Worker     fn read_from_chain<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self>
731*1b4853f5SAndroid Build Coastguard Worker     where
732*1b4853f5SAndroid Build Coastguard Worker         Self: Sized,
733*1b4853f5SAndroid Build Coastguard Worker     {
734*1b4853f5SAndroid Build Coastguard Worker         let ctrls = v4l2_ext_controls::read_from_chain(reader)?;
735*1b4853f5SAndroid Build Coastguard Worker 
736*1b4853f5SAndroid Build Coastguard Worker         let ctrl_array = (0..ctrls.count)
737*1b4853f5SAndroid Build Coastguard Worker             .map(|_| v4l2_ext_control::read_from_chain(reader))
738*1b4853f5SAndroid Build Coastguard Worker             .collect::<IoResult<Vec<_>>>()?;
739*1b4853f5SAndroid Build Coastguard Worker 
740*1b4853f5SAndroid Build Coastguard Worker         // Read all the payloads.
741*1b4853f5SAndroid Build Coastguard Worker         let mem_regions = ctrl_array
742*1b4853f5SAndroid Build Coastguard Worker             .iter()
743*1b4853f5SAndroid Build Coastguard Worker             .filter(|ctrl| ctrl.size > 0)
744*1b4853f5SAndroid Build Coastguard Worker             .map(|ctrl| {
745*1b4853f5SAndroid Build Coastguard Worker                 get_userptr_regions(reader, ctrl.size as usize)
746*1b4853f5SAndroid Build Coastguard Worker                     .map_err(|_| std::io::Error::from(std::io::ErrorKind::InvalidData))
747*1b4853f5SAndroid Build Coastguard Worker             })
748*1b4853f5SAndroid Build Coastguard Worker             .collect::<IoResult<Vec<_>>>()?;
749*1b4853f5SAndroid Build Coastguard Worker 
750*1b4853f5SAndroid Build Coastguard Worker         Ok((ctrls, ctrl_array, mem_regions))
751*1b4853f5SAndroid Build Coastguard Worker     }
752*1b4853f5SAndroid Build Coastguard Worker }
753*1b4853f5SAndroid Build Coastguard Worker 
754*1b4853f5SAndroid Build Coastguard Worker /// Allows to easily write a `v4l2_ext_controls` struct and its array of controls to a descriptor
755*1b4853f5SAndroid Build Coastguard Worker /// chain.
756*1b4853f5SAndroid Build Coastguard Worker impl ToDescriptorChain for (v4l2_ext_controls, Vec<v4l2_ext_control>) {
write_to_chain<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()>757*1b4853f5SAndroid Build Coastguard Worker     fn write_to_chain<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
758*1b4853f5SAndroid Build Coastguard Worker         let (ctrls, ctrl_array) = self;
759*1b4853f5SAndroid Build Coastguard Worker         let mut ctrls = *ctrls;
760*1b4853f5SAndroid Build Coastguard Worker 
761*1b4853f5SAndroid Build Coastguard Worker         // Nullify the control pointer to avoid leaking host addresses.
762*1b4853f5SAndroid Build Coastguard Worker         ctrls.controls = std::ptr::null_mut();
763*1b4853f5SAndroid Build Coastguard Worker         ctrls.write_to_chain(writer)?;
764*1b4853f5SAndroid Build Coastguard Worker 
765*1b4853f5SAndroid Build Coastguard Worker         for ctrl in ctrl_array {
766*1b4853f5SAndroid Build Coastguard Worker             ctrl.write_to_chain(writer)?;
767*1b4853f5SAndroid Build Coastguard Worker         }
768*1b4853f5SAndroid Build Coastguard Worker 
769*1b4853f5SAndroid Build Coastguard Worker         Ok(())
770*1b4853f5SAndroid Build Coastguard Worker     }
771*1b4853f5SAndroid Build Coastguard Worker }
772*1b4853f5SAndroid Build Coastguard Worker 
773*1b4853f5SAndroid Build Coastguard Worker /// Implements a `WR` ioctl for which errors may also carry a payload.
774*1b4853f5SAndroid Build Coastguard Worker ///
775*1b4853f5SAndroid Build Coastguard Worker /// * `Reader` is the reader to the device-readable part of the descriptor chain,
776*1b4853f5SAndroid Build Coastguard Worker /// * `Writer` is the writer to the device-writable part of the descriptor chain,
777*1b4853f5SAndroid Build Coastguard Worker /// * `I` is the data to be read from the descriptor chain,
778*1b4853f5SAndroid Build Coastguard Worker /// * `O` is the type of response to be written to the descriptor chain for both success and
779*1b4853f5SAndroid Build Coastguard Worker ///   failure,
780*1b4853f5SAndroid Build Coastguard Worker /// * `X` processes the input and produces a result. In case of failure, an error code and optional
781*1b4853f5SAndroid Build Coastguard Worker ///   payload to write along with it are returned.
wr_ioctl_with_err_payload<Reader, Writer, I, O, X>( ioctl: V4l2Ioctl, reader: &mut Reader, writer: &mut Writer, process: X, ) -> IoResult<()> where Reader: std::io::Read, Writer: std::io::Write, I: FromDescriptorChain, O: ToDescriptorChain, X: FnOnce(I) -> Result<O, (i32, Option<O>)>,782*1b4853f5SAndroid Build Coastguard Worker fn wr_ioctl_with_err_payload<Reader, Writer, I, O, X>(
783*1b4853f5SAndroid Build Coastguard Worker     ioctl: V4l2Ioctl,
784*1b4853f5SAndroid Build Coastguard Worker     reader: &mut Reader,
785*1b4853f5SAndroid Build Coastguard Worker     writer: &mut Writer,
786*1b4853f5SAndroid Build Coastguard Worker     process: X,
787*1b4853f5SAndroid Build Coastguard Worker ) -> IoResult<()>
788*1b4853f5SAndroid Build Coastguard Worker where
789*1b4853f5SAndroid Build Coastguard Worker     Reader: std::io::Read,
790*1b4853f5SAndroid Build Coastguard Worker     Writer: std::io::Write,
791*1b4853f5SAndroid Build Coastguard Worker     I: FromDescriptorChain,
792*1b4853f5SAndroid Build Coastguard Worker     O: ToDescriptorChain,
793*1b4853f5SAndroid Build Coastguard Worker     X: FnOnce(I) -> Result<O, (i32, Option<O>)>,
794*1b4853f5SAndroid Build Coastguard Worker {
795*1b4853f5SAndroid Build Coastguard Worker     let input = match I::read_from_chain(reader) {
796*1b4853f5SAndroid Build Coastguard Worker         Ok(input) => input,
797*1b4853f5SAndroid Build Coastguard Worker         Err(e) => {
798*1b4853f5SAndroid Build Coastguard Worker             log::error!("error while reading input for {:?} ioctl: {:#}", ioctl, e);
799*1b4853f5SAndroid Build Coastguard Worker             return writer.write_err_response(libc::EINVAL);
800*1b4853f5SAndroid Build Coastguard Worker         }
801*1b4853f5SAndroid Build Coastguard Worker     };
802*1b4853f5SAndroid Build Coastguard Worker 
803*1b4853f5SAndroid Build Coastguard Worker     let (resp_header, output) = match process(input) {
804*1b4853f5SAndroid Build Coastguard Worker         Ok(output) => (RespHeader::ok(), Some(output)),
805*1b4853f5SAndroid Build Coastguard Worker         Err((errno, output)) => (RespHeader::err(errno), output),
806*1b4853f5SAndroid Build Coastguard Worker     };
807*1b4853f5SAndroid Build Coastguard Worker 
808*1b4853f5SAndroid Build Coastguard Worker     writer.write_response(resp_header)?;
809*1b4853f5SAndroid Build Coastguard Worker     if let Some(output) = output {
810*1b4853f5SAndroid Build Coastguard Worker         output.write_to_chain(writer)?;
811*1b4853f5SAndroid Build Coastguard Worker     }
812*1b4853f5SAndroid Build Coastguard Worker 
813*1b4853f5SAndroid Build Coastguard Worker     Ok(())
814*1b4853f5SAndroid Build Coastguard Worker }
815*1b4853f5SAndroid Build Coastguard Worker 
816*1b4853f5SAndroid Build Coastguard Worker /// Implements a `WR` ioctl for which errors do not carry a payload.
817*1b4853f5SAndroid Build Coastguard Worker ///
818*1b4853f5SAndroid Build Coastguard Worker /// * `Reader` is the reader to the device-readable part of the descriptor chain,
819*1b4853f5SAndroid Build Coastguard Worker /// * `Writer` is the writer to the device-writable part of the descriptor chain,
820*1b4853f5SAndroid Build Coastguard Worker /// * `I` is the data to be read from the descriptor chain,
821*1b4853f5SAndroid Build Coastguard Worker /// * `O` is the type of response to be written to the descriptor chain in case of success,
822*1b4853f5SAndroid Build Coastguard Worker /// * `X` processes the input and produces a result. In case of failure, an error code to transmit
823*1b4853f5SAndroid Build Coastguard Worker ///   to the guest is returned.
wr_ioctl<Reader, Writer, I, O, X>( ioctl: V4l2Ioctl, reader: &mut Reader, writer: &mut Writer, process: X, ) -> IoResult<()> where Reader: std::io::Read, Writer: std::io::Write, I: FromDescriptorChain, O: ToDescriptorChain, X: FnOnce(I) -> Result<O, i32>,824*1b4853f5SAndroid Build Coastguard Worker fn wr_ioctl<Reader, Writer, I, O, X>(
825*1b4853f5SAndroid Build Coastguard Worker     ioctl: V4l2Ioctl,
826*1b4853f5SAndroid Build Coastguard Worker     reader: &mut Reader,
827*1b4853f5SAndroid Build Coastguard Worker     writer: &mut Writer,
828*1b4853f5SAndroid Build Coastguard Worker     process: X,
829*1b4853f5SAndroid Build Coastguard Worker ) -> IoResult<()>
830*1b4853f5SAndroid Build Coastguard Worker where
831*1b4853f5SAndroid Build Coastguard Worker     Reader: std::io::Read,
832*1b4853f5SAndroid Build Coastguard Worker     Writer: std::io::Write,
833*1b4853f5SAndroid Build Coastguard Worker     I: FromDescriptorChain,
834*1b4853f5SAndroid Build Coastguard Worker     O: ToDescriptorChain,
835*1b4853f5SAndroid Build Coastguard Worker     X: FnOnce(I) -> Result<O, i32>,
836*1b4853f5SAndroid Build Coastguard Worker {
837*1b4853f5SAndroid Build Coastguard Worker     wr_ioctl_with_err_payload(ioctl, reader, writer, |input| {
838*1b4853f5SAndroid Build Coastguard Worker         process(input).map_err(|err| (err, None))
839*1b4853f5SAndroid Build Coastguard Worker     })
840*1b4853f5SAndroid Build Coastguard Worker }
841*1b4853f5SAndroid Build Coastguard Worker 
842*1b4853f5SAndroid Build Coastguard Worker /// Implements a `W` ioctl.
843*1b4853f5SAndroid Build Coastguard Worker ///
844*1b4853f5SAndroid Build Coastguard Worker /// * `Reader` is the reader to the device-readable part of the descriptor chain,
845*1b4853f5SAndroid Build Coastguard Worker /// * `I` is the data to be read from the descriptor chain,
846*1b4853f5SAndroid Build Coastguard Worker /// * `X` processes the input. In case of failure, an error code to transmit to the guest is
847*1b4853f5SAndroid Build Coastguard Worker ///   returned.
w_ioctl<Reader, Writer, I, X>( ioctl: V4l2Ioctl, reader: &mut Reader, writer: &mut Writer, process: X, ) -> IoResult<()> where I: FromDescriptorChain, Reader: std::io::Read, Writer: std::io::Write, X: FnOnce(I) -> Result<(), i32>,848*1b4853f5SAndroid Build Coastguard Worker fn w_ioctl<Reader, Writer, I, X>(
849*1b4853f5SAndroid Build Coastguard Worker     ioctl: V4l2Ioctl,
850*1b4853f5SAndroid Build Coastguard Worker     reader: &mut Reader,
851*1b4853f5SAndroid Build Coastguard Worker     writer: &mut Writer,
852*1b4853f5SAndroid Build Coastguard Worker     process: X,
853*1b4853f5SAndroid Build Coastguard Worker ) -> IoResult<()>
854*1b4853f5SAndroid Build Coastguard Worker where
855*1b4853f5SAndroid Build Coastguard Worker     I: FromDescriptorChain,
856*1b4853f5SAndroid Build Coastguard Worker     Reader: std::io::Read,
857*1b4853f5SAndroid Build Coastguard Worker     Writer: std::io::Write,
858*1b4853f5SAndroid Build Coastguard Worker     X: FnOnce(I) -> Result<(), i32>,
859*1b4853f5SAndroid Build Coastguard Worker {
860*1b4853f5SAndroid Build Coastguard Worker     wr_ioctl(ioctl, reader, writer, process)
861*1b4853f5SAndroid Build Coastguard Worker }
862*1b4853f5SAndroid Build Coastguard Worker 
863*1b4853f5SAndroid Build Coastguard Worker /// Implements a `R` ioctl.
864*1b4853f5SAndroid Build Coastguard Worker ///
865*1b4853f5SAndroid Build Coastguard Worker /// * `Writer` is the writer to the device-writable part of the descriptor chain,
866*1b4853f5SAndroid Build Coastguard Worker /// * `O` is the type of response to be written to the descriptor chain in case of success,
867*1b4853f5SAndroid Build Coastguard Worker /// * `X` runs the ioctl and produces a result. In case of failure, an error code to transmit to
868*1b4853f5SAndroid Build Coastguard Worker ///   the guest is returned.
r_ioctl<Writer, O, X>(ioctl: V4l2Ioctl, writer: &mut Writer, process: X) -> IoResult<()> where Writer: std::io::Write, O: ToDescriptorChain, X: FnOnce() -> Result<O, i32>,869*1b4853f5SAndroid Build Coastguard Worker fn r_ioctl<Writer, O, X>(ioctl: V4l2Ioctl, writer: &mut Writer, process: X) -> IoResult<()>
870*1b4853f5SAndroid Build Coastguard Worker where
871*1b4853f5SAndroid Build Coastguard Worker     Writer: std::io::Write,
872*1b4853f5SAndroid Build Coastguard Worker     O: ToDescriptorChain,
873*1b4853f5SAndroid Build Coastguard Worker     X: FnOnce() -> Result<O, i32>,
874*1b4853f5SAndroid Build Coastguard Worker {
875*1b4853f5SAndroid Build Coastguard Worker     wr_ioctl(ioctl, &mut std::io::empty(), writer, |()| process())
876*1b4853f5SAndroid Build Coastguard Worker }
877*1b4853f5SAndroid Build Coastguard Worker 
878*1b4853f5SAndroid Build Coastguard Worker /// Ensures that the `readbuffers` and `writebuffers` members of a `v4l2_streamparm` are zero since
879*1b4853f5SAndroid Build Coastguard Worker /// we do not expose the `READWRITE` capability.
patch_streamparm(mut parm: v4l2_streamparm) -> v4l2_streamparm880*1b4853f5SAndroid Build Coastguard Worker fn patch_streamparm(mut parm: v4l2_streamparm) -> v4l2_streamparm {
881*1b4853f5SAndroid Build Coastguard Worker     match QueueType::n(parm.type_)
882*1b4853f5SAndroid Build Coastguard Worker         .unwrap_or(QueueType::VideoCapture)
883*1b4853f5SAndroid Build Coastguard Worker         .direction()
884*1b4853f5SAndroid Build Coastguard Worker     {
885*1b4853f5SAndroid Build Coastguard Worker         QueueDirection::Output => parm.parm.output.writebuffers = 0,
886*1b4853f5SAndroid Build Coastguard Worker         QueueDirection::Capture => parm.parm.capture.readbuffers = 0,
887*1b4853f5SAndroid Build Coastguard Worker     }
888*1b4853f5SAndroid Build Coastguard Worker 
889*1b4853f5SAndroid Build Coastguard Worker     parm
890*1b4853f5SAndroid Build Coastguard Worker }
891*1b4853f5SAndroid Build Coastguard Worker 
892*1b4853f5SAndroid Build Coastguard Worker /// IOCTL dispatcher for implementors of [`VirtioMediaIoctlHandler`].
893*1b4853f5SAndroid Build Coastguard Worker ///
894*1b4853f5SAndroid Build Coastguard Worker /// This function takes care of reading and validating IOCTL inputs and writing outputs or errors
895*1b4853f5SAndroid Build Coastguard Worker /// back to the driver, invoking the relevant method of the handler in the middle.
896*1b4853f5SAndroid Build Coastguard Worker ///
897*1b4853f5SAndroid Build Coastguard Worker /// Implementors of [`VirtioMediaIoctlHandler`] can thus just focus on writing the desired behavior
898*1b4853f5SAndroid Build Coastguard Worker /// for their device, and let the more tedious parsing and validation to this function.
virtio_media_dispatch_ioctl<S, H, Reader, Writer>( handler: &mut H, session: &mut S, ioctl: V4l2Ioctl, reader: &mut Reader, writer: &mut Writer, ) -> IoResult<()> where H: VirtioMediaIoctlHandler<Session = S>, Reader: std::io::Read, Writer: std::io::Write,899*1b4853f5SAndroid Build Coastguard Worker pub fn virtio_media_dispatch_ioctl<S, H, Reader, Writer>(
900*1b4853f5SAndroid Build Coastguard Worker     handler: &mut H,
901*1b4853f5SAndroid Build Coastguard Worker     session: &mut S,
902*1b4853f5SAndroid Build Coastguard Worker     ioctl: V4l2Ioctl,
903*1b4853f5SAndroid Build Coastguard Worker     reader: &mut Reader,
904*1b4853f5SAndroid Build Coastguard Worker     writer: &mut Writer,
905*1b4853f5SAndroid Build Coastguard Worker ) -> IoResult<()>
906*1b4853f5SAndroid Build Coastguard Worker where
907*1b4853f5SAndroid Build Coastguard Worker     H: VirtioMediaIoctlHandler<Session = S>,
908*1b4853f5SAndroid Build Coastguard Worker     Reader: std::io::Read,
909*1b4853f5SAndroid Build Coastguard Worker     Writer: std::io::Write,
910*1b4853f5SAndroid Build Coastguard Worker {
911*1b4853f5SAndroid Build Coastguard Worker     use V4l2Ioctl::*;
912*1b4853f5SAndroid Build Coastguard Worker 
913*1b4853f5SAndroid Build Coastguard Worker     match ioctl {
914*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_QUERYCAP => invalid_ioctl(ioctl, writer),
915*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_ENUM_FMT => wr_ioctl(ioctl, reader, writer, |format: v4l2_fmtdesc| {
916*1b4853f5SAndroid Build Coastguard Worker             let queue = QueueType::n(format.type_).ok_or(libc::EINVAL)?;
917*1b4853f5SAndroid Build Coastguard Worker             handler.enum_fmt(session, queue, format.index)
918*1b4853f5SAndroid Build Coastguard Worker         }),
919*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_FMT => wr_ioctl(ioctl, reader, writer, |format: v4l2_format| {
920*1b4853f5SAndroid Build Coastguard Worker             let queue = QueueType::n(format.type_).ok_or(libc::EINVAL)?;
921*1b4853f5SAndroid Build Coastguard Worker             handler.g_fmt(session, queue)
922*1b4853f5SAndroid Build Coastguard Worker         }),
923*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_FMT => wr_ioctl(ioctl, reader, writer, |format: v4l2_format| {
924*1b4853f5SAndroid Build Coastguard Worker             let queue = QueueType::n(format.type_).ok_or(libc::EINVAL)?;
925*1b4853f5SAndroid Build Coastguard Worker             handler.s_fmt(session, queue, format)
926*1b4853f5SAndroid Build Coastguard Worker         }),
927*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_REQBUFS => wr_ioctl(ioctl, reader, writer, |reqbufs: v4l2_requestbuffers| {
928*1b4853f5SAndroid Build Coastguard Worker             let queue = QueueType::n(reqbufs.type_).ok_or(libc::EINVAL)?;
929*1b4853f5SAndroid Build Coastguard Worker             let memory = MemoryType::n(reqbufs.memory).ok_or(libc::EINVAL)?;
930*1b4853f5SAndroid Build Coastguard Worker 
931*1b4853f5SAndroid Build Coastguard Worker             match memory {
932*1b4853f5SAndroid Build Coastguard Worker                 MemoryType::Mmap | MemoryType::UserPtr => (),
933*1b4853f5SAndroid Build Coastguard Worker                 t => {
934*1b4853f5SAndroid Build Coastguard Worker                     log::error!(
935*1b4853f5SAndroid Build Coastguard Worker                         "VIDIOC_REQBUFS: memory type {:?} is currently unsupported",
936*1b4853f5SAndroid Build Coastguard Worker                         t
937*1b4853f5SAndroid Build Coastguard Worker                     );
938*1b4853f5SAndroid Build Coastguard Worker                     return Err(libc::EINVAL);
939*1b4853f5SAndroid Build Coastguard Worker                 }
940*1b4853f5SAndroid Build Coastguard Worker             }
941*1b4853f5SAndroid Build Coastguard Worker 
942*1b4853f5SAndroid Build Coastguard Worker             handler.reqbufs(session, queue, memory, reqbufs.count)
943*1b4853f5SAndroid Build Coastguard Worker         }),
944*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_QUERYBUF => {
945*1b4853f5SAndroid Build Coastguard Worker             wr_ioctl(ioctl, reader, writer, |buffer: v4l2_buffer| {
946*1b4853f5SAndroid Build Coastguard Worker                 let queue = QueueType::n(buffer.type_).ok_or(libc::EINVAL)?;
947*1b4853f5SAndroid Build Coastguard Worker                 // Maximum number of planes we can write back to the driver.
948*1b4853f5SAndroid Build Coastguard Worker                 let num_planes = if queue.is_multiplanar() {
949*1b4853f5SAndroid Build Coastguard Worker                     buffer.length as usize
950*1b4853f5SAndroid Build Coastguard Worker                 } else {
951*1b4853f5SAndroid Build Coastguard Worker                     0
952*1b4853f5SAndroid Build Coastguard Worker                 };
953*1b4853f5SAndroid Build Coastguard Worker 
954*1b4853f5SAndroid Build Coastguard Worker                 handler
955*1b4853f5SAndroid Build Coastguard Worker                     .querybuf(session, queue, buffer.index)
956*1b4853f5SAndroid Build Coastguard Worker                     .map(|guest_buffer| (guest_buffer, num_planes))
957*1b4853f5SAndroid Build Coastguard Worker             })
958*1b4853f5SAndroid Build Coastguard Worker         }
959*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_FBUF => invalid_ioctl(ioctl, writer),
960*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_FBUF => invalid_ioctl(ioctl, writer),
961*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_OVERLAY => invalid_ioctl(ioctl, writer),
962*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_QBUF => wr_ioctl(ioctl, reader, writer, |(guest_buffer, guest_regions)| {
963*1b4853f5SAndroid Build Coastguard Worker             let num_planes = guest_buffer.num_planes();
964*1b4853f5SAndroid Build Coastguard Worker 
965*1b4853f5SAndroid Build Coastguard Worker             handler
966*1b4853f5SAndroid Build Coastguard Worker                 .qbuf(session, guest_buffer, guest_regions)
967*1b4853f5SAndroid Build Coastguard Worker                 .map(|guest_buffer| (guest_buffer, num_planes))
968*1b4853f5SAndroid Build Coastguard Worker         }),
969*1b4853f5SAndroid Build Coastguard Worker         // TODO implement EXPBUF.
970*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_EXPBUF => invalid_ioctl(ioctl, writer),
971*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_DQBUF => invalid_ioctl(ioctl, writer),
972*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_STREAMON => w_ioctl(ioctl, reader, writer, |input: u32| {
973*1b4853f5SAndroid Build Coastguard Worker             let queue = QueueType::n(input).ok_or(libc::EINVAL)?;
974*1b4853f5SAndroid Build Coastguard Worker 
975*1b4853f5SAndroid Build Coastguard Worker             handler.streamon(session, queue)
976*1b4853f5SAndroid Build Coastguard Worker         }),
977*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_STREAMOFF => w_ioctl(ioctl, reader, writer, |input: u32| {
978*1b4853f5SAndroid Build Coastguard Worker             let queue = QueueType::n(input).ok_or(libc::EINVAL)?;
979*1b4853f5SAndroid Build Coastguard Worker 
980*1b4853f5SAndroid Build Coastguard Worker             handler.streamoff(session, queue)
981*1b4853f5SAndroid Build Coastguard Worker         }),
982*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_PARM => wr_ioctl(ioctl, reader, writer, |parm: v4l2_streamparm| {
983*1b4853f5SAndroid Build Coastguard Worker             let queue = QueueType::n(parm.type_).ok_or(libc::EINVAL)?;
984*1b4853f5SAndroid Build Coastguard Worker 
985*1b4853f5SAndroid Build Coastguard Worker             handler.g_parm(session, queue).map(patch_streamparm)
986*1b4853f5SAndroid Build Coastguard Worker         }),
987*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_PARM => wr_ioctl(ioctl, reader, writer, |parm: v4l2_streamparm| {
988*1b4853f5SAndroid Build Coastguard Worker             handler
989*1b4853f5SAndroid Build Coastguard Worker                 .s_parm(session, patch_streamparm(parm))
990*1b4853f5SAndroid Build Coastguard Worker                 .map(patch_streamparm)
991*1b4853f5SAndroid Build Coastguard Worker         }),
992*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_STD => r_ioctl(ioctl, writer, || handler.g_std(session)),
993*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_STD => w_ioctl(ioctl, reader, writer, |id: v4l2_std_id| {
994*1b4853f5SAndroid Build Coastguard Worker             handler.s_std(session, id)
995*1b4853f5SAndroid Build Coastguard Worker         }),
996*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_ENUMSTD => wr_ioctl(ioctl, reader, writer, |std: v4l2_standard| {
997*1b4853f5SAndroid Build Coastguard Worker             handler.enumstd(session, std.index)
998*1b4853f5SAndroid Build Coastguard Worker         }),
999*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_ENUMINPUT => wr_ioctl(ioctl, reader, writer, |input: v4l2_input| {
1000*1b4853f5SAndroid Build Coastguard Worker             handler.enuminput(session, input.index)
1001*1b4853f5SAndroid Build Coastguard Worker         }),
1002*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_CTRL => wr_ioctl(ioctl, reader, writer, |ctrl: v4l2_control| {
1003*1b4853f5SAndroid Build Coastguard Worker             handler.g_ctrl(session, ctrl.id)
1004*1b4853f5SAndroid Build Coastguard Worker         }),
1005*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_CTRL => wr_ioctl(ioctl, reader, writer, |ctrl: v4l2_control| {
1006*1b4853f5SAndroid Build Coastguard Worker             handler.s_ctrl(session, ctrl.id, ctrl.value)
1007*1b4853f5SAndroid Build Coastguard Worker         }),
1008*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_TUNER => wr_ioctl(ioctl, reader, writer, |tuner: v4l2_tuner| {
1009*1b4853f5SAndroid Build Coastguard Worker             handler.g_tuner(session, tuner.index)
1010*1b4853f5SAndroid Build Coastguard Worker         }),
1011*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_TUNER => w_ioctl(ioctl, reader, writer, |tuner: v4l2_tuner| {
1012*1b4853f5SAndroid Build Coastguard Worker             let mode = TunerMode::n(tuner.audmode).ok_or(libc::EINVAL)?;
1013*1b4853f5SAndroid Build Coastguard Worker             handler.s_tuner(session, tuner.index, mode)
1014*1b4853f5SAndroid Build Coastguard Worker         }),
1015*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_AUDIO => r_ioctl(ioctl, writer, || handler.g_audio(session)),
1016*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_AUDIO => w_ioctl(ioctl, reader, writer, |input: v4l2_audio| {
1017*1b4853f5SAndroid Build Coastguard Worker             handler.s_audio(session, input.index, AudioMode::n(input.mode))
1018*1b4853f5SAndroid Build Coastguard Worker         }),
1019*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_QUERYCTRL => wr_ioctl(ioctl, reader, writer, |input: v4l2_queryctrl| {
1020*1b4853f5SAndroid Build Coastguard Worker             let (id, flags) = v4l2r::ioctl::parse_ctrl_id_and_flags(input.id);
1021*1b4853f5SAndroid Build Coastguard Worker 
1022*1b4853f5SAndroid Build Coastguard Worker             handler.queryctrl(session, id, flags)
1023*1b4853f5SAndroid Build Coastguard Worker         }),
1024*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_QUERYMENU => wr_ioctl(ioctl, reader, writer, |input: v4l2_querymenu| {
1025*1b4853f5SAndroid Build Coastguard Worker             handler.querymenu(session, input.id, input.index)
1026*1b4853f5SAndroid Build Coastguard Worker         }),
1027*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_INPUT => r_ioctl(ioctl, writer, || handler.g_input(session)),
1028*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_INPUT => wr_ioctl(ioctl, reader, writer, |input: i32| {
1029*1b4853f5SAndroid Build Coastguard Worker             handler.s_input(session, input)
1030*1b4853f5SAndroid Build Coastguard Worker         }),
1031*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_EDID => invalid_ioctl(ioctl, writer),
1032*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_EDID => invalid_ioctl(ioctl, writer),
1033*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_OUTPUT => r_ioctl(ioctl, writer, || handler.g_output(session)),
1034*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_OUTPUT => wr_ioctl(ioctl, reader, writer, |output: i32| {
1035*1b4853f5SAndroid Build Coastguard Worker             handler.s_output(session, output)
1036*1b4853f5SAndroid Build Coastguard Worker         }),
1037*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_ENUMOUTPUT => wr_ioctl(ioctl, reader, writer, |output: v4l2_output| {
1038*1b4853f5SAndroid Build Coastguard Worker             handler.enumoutput(session, output.index)
1039*1b4853f5SAndroid Build Coastguard Worker         }),
1040*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_AUDOUT => r_ioctl(ioctl, writer, || handler.g_audout(session)),
1041*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_AUDOUT => w_ioctl(ioctl, reader, writer, |audout: v4l2_audioout| {
1042*1b4853f5SAndroid Build Coastguard Worker             handler.s_audout(session, audout.index)
1043*1b4853f5SAndroid Build Coastguard Worker         }),
1044*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_MODULATOR => wr_ioctl(ioctl, reader, writer, |modulator: v4l2_modulator| {
1045*1b4853f5SAndroid Build Coastguard Worker             handler.g_modulator(session, modulator.index)
1046*1b4853f5SAndroid Build Coastguard Worker         }),
1047*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_MODULATOR => w_ioctl(ioctl, reader, writer, |modulator: v4l2_modulator| {
1048*1b4853f5SAndroid Build Coastguard Worker             let flags =
1049*1b4853f5SAndroid Build Coastguard Worker                 TunerTransmissionFlags::from_bits(modulator.txsubchans).ok_or(libc::EINVAL)?;
1050*1b4853f5SAndroid Build Coastguard Worker             handler.s_modulator(session, modulator.index, flags)
1051*1b4853f5SAndroid Build Coastguard Worker         }),
1052*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_FREQUENCY => wr_ioctl(ioctl, reader, writer, |freq: v4l2_frequency| {
1053*1b4853f5SAndroid Build Coastguard Worker             handler.g_frequency(session, freq.tuner)
1054*1b4853f5SAndroid Build Coastguard Worker         }),
1055*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_FREQUENCY => w_ioctl(ioctl, reader, writer, |freq: v4l2_frequency| {
1056*1b4853f5SAndroid Build Coastguard Worker             let type_ = TunerType::n(freq.type_).ok_or(libc::EINVAL)?;
1057*1b4853f5SAndroid Build Coastguard Worker 
1058*1b4853f5SAndroid Build Coastguard Worker             handler.s_frequency(session, freq.tuner, type_, freq.frequency)
1059*1b4853f5SAndroid Build Coastguard Worker         }),
1060*1b4853f5SAndroid Build Coastguard Worker         // TODO do these 3 need to be supported?
1061*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_CROPCAP => invalid_ioctl(ioctl, writer),
1062*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_CROP => invalid_ioctl(ioctl, writer),
1063*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_CROP => invalid_ioctl(ioctl, writer),
1064*1b4853f5SAndroid Build Coastguard Worker         // Deprecated in V4L2.
1065*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_JPEGCOMP => invalid_ioctl(ioctl, writer),
1066*1b4853f5SAndroid Build Coastguard Worker         // Deprecated in V4L2.
1067*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_JPEGCOMP => invalid_ioctl(ioctl, writer),
1068*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_QUERYSTD => r_ioctl(ioctl, writer, || handler.querystd(session)),
1069*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_TRY_FMT => wr_ioctl(ioctl, reader, writer, |format: v4l2_format| {
1070*1b4853f5SAndroid Build Coastguard Worker             let queue = QueueType::n(format.type_).ok_or(libc::EINVAL)?;
1071*1b4853f5SAndroid Build Coastguard Worker             handler.try_fmt(session, queue, format)
1072*1b4853f5SAndroid Build Coastguard Worker         }),
1073*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_ENUMAUDIO => wr_ioctl(ioctl, reader, writer, |audio: v4l2_audio| {
1074*1b4853f5SAndroid Build Coastguard Worker             handler.enumaudio(session, audio.index)
1075*1b4853f5SAndroid Build Coastguard Worker         }),
1076*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_ENUMAUDOUT => wr_ioctl(ioctl, reader, writer, |audio: v4l2_audioout| {
1077*1b4853f5SAndroid Build Coastguard Worker             handler.enumaudout(session, audio.index)
1078*1b4853f5SAndroid Build Coastguard Worker         }),
1079*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_PRIORITY => invalid_ioctl(ioctl, writer),
1080*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_PRIORITY => invalid_ioctl(ioctl, writer),
1081*1b4853f5SAndroid Build Coastguard Worker         // TODO support this, although it's marginal.
1082*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_SLICED_VBI_CAP => invalid_ioctl(ioctl, writer),
1083*1b4853f5SAndroid Build Coastguard Worker         // Doesn't make sense in a virtual context.
1084*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_LOG_STATUS => invalid_ioctl(ioctl, writer),
1085*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_EXT_CTRLS => wr_ioctl_with_err_payload(
1086*1b4853f5SAndroid Build Coastguard Worker             ioctl,
1087*1b4853f5SAndroid Build Coastguard Worker             reader,
1088*1b4853f5SAndroid Build Coastguard Worker             writer,
1089*1b4853f5SAndroid Build Coastguard Worker             |(mut ctrls, mut ctrl_array, user_regions)| {
1090*1b4853f5SAndroid Build Coastguard Worker                 let which = CtrlWhich::try_from(&ctrls).map_err(|()| (libc::EINVAL, None))?;
1091*1b4853f5SAndroid Build Coastguard Worker 
1092*1b4853f5SAndroid Build Coastguard Worker                 match handler.g_ext_ctrls(session, which, &mut ctrls, &mut ctrl_array, user_regions)
1093*1b4853f5SAndroid Build Coastguard Worker                 {
1094*1b4853f5SAndroid Build Coastguard Worker                     Ok(()) => Ok((ctrls, ctrl_array)),
1095*1b4853f5SAndroid Build Coastguard Worker                     // It is very important what we write back the updated input in case
1096*1b4853f5SAndroid Build Coastguard Worker                     // of error as it contains extra information.
1097*1b4853f5SAndroid Build Coastguard Worker                     Err(e) => Err((e, Some((ctrls, ctrl_array)))),
1098*1b4853f5SAndroid Build Coastguard Worker                 }
1099*1b4853f5SAndroid Build Coastguard Worker             },
1100*1b4853f5SAndroid Build Coastguard Worker         ),
1101*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_EXT_CTRLS => wr_ioctl_with_err_payload(
1102*1b4853f5SAndroid Build Coastguard Worker             ioctl,
1103*1b4853f5SAndroid Build Coastguard Worker             reader,
1104*1b4853f5SAndroid Build Coastguard Worker             writer,
1105*1b4853f5SAndroid Build Coastguard Worker             |(mut ctrls, mut ctrl_array, user_regions)| {
1106*1b4853f5SAndroid Build Coastguard Worker                 let which = CtrlWhich::try_from(&ctrls).map_err(|()| (libc::EINVAL, None))?;
1107*1b4853f5SAndroid Build Coastguard Worker 
1108*1b4853f5SAndroid Build Coastguard Worker                 match handler.s_ext_ctrls(session, which, &mut ctrls, &mut ctrl_array, user_regions)
1109*1b4853f5SAndroid Build Coastguard Worker                 {
1110*1b4853f5SAndroid Build Coastguard Worker                     Ok(()) => Ok((ctrls, ctrl_array)),
1111*1b4853f5SAndroid Build Coastguard Worker                     // It is very important what we write back the updated input in case
1112*1b4853f5SAndroid Build Coastguard Worker                     // of error as it contains extra information.
1113*1b4853f5SAndroid Build Coastguard Worker                     Err(e) => Err((e, Some((ctrls, ctrl_array)))),
1114*1b4853f5SAndroid Build Coastguard Worker                 }
1115*1b4853f5SAndroid Build Coastguard Worker             },
1116*1b4853f5SAndroid Build Coastguard Worker         ),
1117*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_TRY_EXT_CTRLS => wr_ioctl_with_err_payload(
1118*1b4853f5SAndroid Build Coastguard Worker             ioctl,
1119*1b4853f5SAndroid Build Coastguard Worker             reader,
1120*1b4853f5SAndroid Build Coastguard Worker             writer,
1121*1b4853f5SAndroid Build Coastguard Worker             |(mut ctrls, mut ctrl_array, user_regions)| {
1122*1b4853f5SAndroid Build Coastguard Worker                 let which = CtrlWhich::try_from(&ctrls).map_err(|()| (libc::EINVAL, None))?;
1123*1b4853f5SAndroid Build Coastguard Worker 
1124*1b4853f5SAndroid Build Coastguard Worker                 match handler.try_ext_ctrls(
1125*1b4853f5SAndroid Build Coastguard Worker                     session,
1126*1b4853f5SAndroid Build Coastguard Worker                     which,
1127*1b4853f5SAndroid Build Coastguard Worker                     &mut ctrls,
1128*1b4853f5SAndroid Build Coastguard Worker                     &mut ctrl_array,
1129*1b4853f5SAndroid Build Coastguard Worker                     user_regions,
1130*1b4853f5SAndroid Build Coastguard Worker                 ) {
1131*1b4853f5SAndroid Build Coastguard Worker                     Ok(()) => Ok((ctrls, ctrl_array)),
1132*1b4853f5SAndroid Build Coastguard Worker                     // It is very important what we write back the updated input in case
1133*1b4853f5SAndroid Build Coastguard Worker                     // of error as it contains extra information.
1134*1b4853f5SAndroid Build Coastguard Worker                     Err(e) => Err((e, Some((ctrls, ctrl_array)))),
1135*1b4853f5SAndroid Build Coastguard Worker                 }
1136*1b4853f5SAndroid Build Coastguard Worker             },
1137*1b4853f5SAndroid Build Coastguard Worker         ),
1138*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_ENUM_FRAMESIZES => {
1139*1b4853f5SAndroid Build Coastguard Worker             wr_ioctl(ioctl, reader, writer, |frmsizeenum: v4l2_frmsizeenum| {
1140*1b4853f5SAndroid Build Coastguard Worker                 handler.enum_framesizes(session, frmsizeenum.index, frmsizeenum.pixel_format)
1141*1b4853f5SAndroid Build Coastguard Worker             })
1142*1b4853f5SAndroid Build Coastguard Worker         }
1143*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_ENUM_FRAMEINTERVALS => {
1144*1b4853f5SAndroid Build Coastguard Worker             wr_ioctl(ioctl, reader, writer, |frmivalenum: v4l2_frmivalenum| {
1145*1b4853f5SAndroid Build Coastguard Worker                 handler.enum_frameintervals(
1146*1b4853f5SAndroid Build Coastguard Worker                     session,
1147*1b4853f5SAndroid Build Coastguard Worker                     frmivalenum.index,
1148*1b4853f5SAndroid Build Coastguard Worker                     frmivalenum.pixel_format,
1149*1b4853f5SAndroid Build Coastguard Worker                     frmivalenum.width,
1150*1b4853f5SAndroid Build Coastguard Worker                     frmivalenum.height,
1151*1b4853f5SAndroid Build Coastguard Worker                 )
1152*1b4853f5SAndroid Build Coastguard Worker             })
1153*1b4853f5SAndroid Build Coastguard Worker         }
1154*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_ENC_INDEX => r_ioctl(ioctl, writer, || handler.g_enc_index(session)),
1155*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_ENCODER_CMD => wr_ioctl(ioctl, reader, writer, |cmd: v4l2_encoder_cmd| {
1156*1b4853f5SAndroid Build Coastguard Worker             handler.encoder_cmd(session, cmd)
1157*1b4853f5SAndroid Build Coastguard Worker         }),
1158*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_TRY_ENCODER_CMD => wr_ioctl(ioctl, reader, writer, |cmd: v4l2_encoder_cmd| {
1159*1b4853f5SAndroid Build Coastguard Worker             handler.try_encoder_cmd(session, cmd)
1160*1b4853f5SAndroid Build Coastguard Worker         }),
1161*1b4853f5SAndroid Build Coastguard Worker         // Doesn't make sense in a virtual context.
1162*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_DBG_G_REGISTER => invalid_ioctl(ioctl, writer),
1163*1b4853f5SAndroid Build Coastguard Worker         // Doesn't make sense in a virtual context.
1164*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_DBG_S_REGISTER => invalid_ioctl(ioctl, writer),
1165*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_HW_FREQ_SEEK => invalid_ioctl(ioctl, writer),
1166*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_DV_TIMINGS => wr_ioctl(ioctl, reader, writer, |timings: v4l2_dv_timings| {
1167*1b4853f5SAndroid Build Coastguard Worker             handler.s_dv_timings(session, timings)
1168*1b4853f5SAndroid Build Coastguard Worker         }),
1169*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_DV_TIMINGS => wr_ioctl(
1170*1b4853f5SAndroid Build Coastguard Worker             ioctl,
1171*1b4853f5SAndroid Build Coastguard Worker             reader,
1172*1b4853f5SAndroid Build Coastguard Worker             writer,
1173*1b4853f5SAndroid Build Coastguard Worker             // We are not using the input - this should probably have been a R ioctl?
1174*1b4853f5SAndroid Build Coastguard Worker             |_: v4l2_dv_timings| handler.g_dv_timings(session),
1175*1b4853f5SAndroid Build Coastguard Worker         ),
1176*1b4853f5SAndroid Build Coastguard Worker         // Supported by an event.
1177*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_DQEVENT => invalid_ioctl(ioctl, writer),
1178*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_SUBSCRIBE_EVENT => {
1179*1b4853f5SAndroid Build Coastguard Worker             w_ioctl(ioctl, reader, writer, |input: v4l2_event_subscription| {
1180*1b4853f5SAndroid Build Coastguard Worker                 let event = V4l2EventType::try_from(&input).unwrap();
1181*1b4853f5SAndroid Build Coastguard Worker                 let flags = SubscribeEventFlags::from_bits(input.flags).unwrap();
1182*1b4853f5SAndroid Build Coastguard Worker 
1183*1b4853f5SAndroid Build Coastguard Worker                 handler.subscribe_event(session, event, flags)
1184*1b4853f5SAndroid Build Coastguard Worker             })?;
1185*1b4853f5SAndroid Build Coastguard Worker 
1186*1b4853f5SAndroid Build Coastguard Worker             Ok(())
1187*1b4853f5SAndroid Build Coastguard Worker         }
1188*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_UNSUBSCRIBE_EVENT => {
1189*1b4853f5SAndroid Build Coastguard Worker             w_ioctl(ioctl, reader, writer, |event: v4l2_event_subscription| {
1190*1b4853f5SAndroid Build Coastguard Worker                 handler.unsubscribe_event(session, event)
1191*1b4853f5SAndroid Build Coastguard Worker             })
1192*1b4853f5SAndroid Build Coastguard Worker         }
1193*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_CREATE_BUFS => wr_ioctl(ioctl, reader, writer, |input: v4l2_create_buffers| {
1194*1b4853f5SAndroid Build Coastguard Worker             let queue = QueueType::n(input.format.type_).ok_or(libc::EINVAL)?;
1195*1b4853f5SAndroid Build Coastguard Worker             let memory = MemoryType::n(input.memory).ok_or(libc::EINVAL)?;
1196*1b4853f5SAndroid Build Coastguard Worker 
1197*1b4853f5SAndroid Build Coastguard Worker             handler.create_bufs(session, input.count, queue, memory, input.format)
1198*1b4853f5SAndroid Build Coastguard Worker         }),
1199*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_PREPARE_BUF => wr_ioctl(ioctl, reader, writer, |(guest_buffer, guest_regions)| {
1200*1b4853f5SAndroid Build Coastguard Worker             let num_planes = guest_buffer.num_planes();
1201*1b4853f5SAndroid Build Coastguard Worker 
1202*1b4853f5SAndroid Build Coastguard Worker             handler
1203*1b4853f5SAndroid Build Coastguard Worker                 .prepare_buf(session, guest_buffer, guest_regions)
1204*1b4853f5SAndroid Build Coastguard Worker                 .map(|out_buffer| (out_buffer, num_planes))
1205*1b4853f5SAndroid Build Coastguard Worker         }),
1206*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_G_SELECTION => wr_ioctl(ioctl, reader, writer, |mut selection: v4l2_selection| {
1207*1b4853f5SAndroid Build Coastguard Worker             let sel_type = SelectionType::n(selection.type_).ok_or(libc::EINVAL)?;
1208*1b4853f5SAndroid Build Coastguard Worker             let sel_target = SelectionTarget::n(selection.target).ok_or(libc::EINVAL)?;
1209*1b4853f5SAndroid Build Coastguard Worker 
1210*1b4853f5SAndroid Build Coastguard Worker             handler
1211*1b4853f5SAndroid Build Coastguard Worker                 .g_selection(session, sel_type, sel_target)
1212*1b4853f5SAndroid Build Coastguard Worker                 .map(|rect| {
1213*1b4853f5SAndroid Build Coastguard Worker                     selection.r = rect;
1214*1b4853f5SAndroid Build Coastguard Worker                     selection
1215*1b4853f5SAndroid Build Coastguard Worker                 })
1216*1b4853f5SAndroid Build Coastguard Worker         }),
1217*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_S_SELECTION => wr_ioctl(ioctl, reader, writer, |mut selection: v4l2_selection| {
1218*1b4853f5SAndroid Build Coastguard Worker             let sel_type = SelectionType::n(selection.type_).ok_or(libc::EINVAL)?;
1219*1b4853f5SAndroid Build Coastguard Worker             let sel_target = SelectionTarget::n(selection.target).ok_or(libc::EINVAL)?;
1220*1b4853f5SAndroid Build Coastguard Worker             let sel_flags = SelectionFlags::from_bits(selection.flags).ok_or(libc::EINVAL)?;
1221*1b4853f5SAndroid Build Coastguard Worker 
1222*1b4853f5SAndroid Build Coastguard Worker             handler
1223*1b4853f5SAndroid Build Coastguard Worker                 .s_selection(session, sel_type, sel_target, selection.r, sel_flags)
1224*1b4853f5SAndroid Build Coastguard Worker                 .map(|rect| {
1225*1b4853f5SAndroid Build Coastguard Worker                     selection.r = rect;
1226*1b4853f5SAndroid Build Coastguard Worker                     selection
1227*1b4853f5SAndroid Build Coastguard Worker                 })
1228*1b4853f5SAndroid Build Coastguard Worker         }),
1229*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_DECODER_CMD => wr_ioctl(ioctl, reader, writer, |cmd: v4l2_decoder_cmd| {
1230*1b4853f5SAndroid Build Coastguard Worker             handler.decoder_cmd(session, cmd)
1231*1b4853f5SAndroid Build Coastguard Worker         }),
1232*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_TRY_DECODER_CMD => wr_ioctl(ioctl, reader, writer, |cmd: v4l2_decoder_cmd| {
1233*1b4853f5SAndroid Build Coastguard Worker             handler.try_decoder_cmd(session, cmd)
1234*1b4853f5SAndroid Build Coastguard Worker         }),
1235*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_ENUM_DV_TIMINGS => wr_ioctl(
1236*1b4853f5SAndroid Build Coastguard Worker             ioctl,
1237*1b4853f5SAndroid Build Coastguard Worker             reader,
1238*1b4853f5SAndroid Build Coastguard Worker             writer,
1239*1b4853f5SAndroid Build Coastguard Worker             |mut enum_timings: v4l2_enum_dv_timings| {
1240*1b4853f5SAndroid Build Coastguard Worker                 handler
1241*1b4853f5SAndroid Build Coastguard Worker                     .enum_dv_timings(session, enum_timings.index)
1242*1b4853f5SAndroid Build Coastguard Worker                     .map(|timings| {
1243*1b4853f5SAndroid Build Coastguard Worker                         enum_timings.timings = timings;
1244*1b4853f5SAndroid Build Coastguard Worker                         enum_timings
1245*1b4853f5SAndroid Build Coastguard Worker                     })
1246*1b4853f5SAndroid Build Coastguard Worker             },
1247*1b4853f5SAndroid Build Coastguard Worker         ),
1248*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_QUERY_DV_TIMINGS => r_ioctl(ioctl, writer, || handler.query_dv_timings(session)),
1249*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_DV_TIMINGS_CAP => wr_ioctl(ioctl, reader, writer, |_: v4l2_dv_timings_cap| {
1250*1b4853f5SAndroid Build Coastguard Worker             handler.dv_timings_cap(session)
1251*1b4853f5SAndroid Build Coastguard Worker         }),
1252*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_ENUM_FREQ_BANDS => {
1253*1b4853f5SAndroid Build Coastguard Worker             wr_ioctl(ioctl, reader, writer, |freq_band: v4l2_frequency_band| {
1254*1b4853f5SAndroid Build Coastguard Worker                 let type_ = TunerType::n(freq_band.type_).ok_or(libc::EINVAL)?;
1255*1b4853f5SAndroid Build Coastguard Worker 
1256*1b4853f5SAndroid Build Coastguard Worker                 handler.enum_freq_bands(session, freq_band.tuner, type_, freq_band.index)
1257*1b4853f5SAndroid Build Coastguard Worker             })
1258*1b4853f5SAndroid Build Coastguard Worker         }
1259*1b4853f5SAndroid Build Coastguard Worker         // Doesn't make sense in a virtual context.
1260*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_DBG_G_CHIP_INFO => invalid_ioctl(ioctl, writer),
1261*1b4853f5SAndroid Build Coastguard Worker         VIDIOC_QUERY_EXT_CTRL => wr_ioctl(ioctl, reader, writer, |ctrl: v4l2_query_ext_ctrl| {
1262*1b4853f5SAndroid Build Coastguard Worker             let (id, flags) = v4l2r::ioctl::parse_ctrl_id_and_flags(ctrl.id);
1263*1b4853f5SAndroid Build Coastguard Worker             handler.query_ext_ctrl(session, id, flags)
1264*1b4853f5SAndroid Build Coastguard Worker         }),
1265*1b4853f5SAndroid Build Coastguard Worker     }
1266*1b4853f5SAndroid Build Coastguard Worker }
1267