xref: /linux/rust/kernel/drm/ioctl.rs (revision 917b10d90990fd2138b5dbc2d22cfa428c070ade)
19a695706SAsahi Lina // SPDX-License-Identifier: GPL-2.0 OR MIT
29a695706SAsahi Lina 
39a695706SAsahi Lina //! DRM IOCTL definitions.
49a695706SAsahi Lina //!
59a695706SAsahi Lina //! C header: [`include/linux/drm/drm_ioctl.h`](srctree/include/linux/drm/drm_ioctl.h)
69a695706SAsahi Lina 
79a695706SAsahi Lina use crate::ioctl;
89a695706SAsahi Lina 
99a695706SAsahi Lina const BASE: u32 = uapi::DRM_IOCTL_BASE as u32;
109a695706SAsahi Lina 
119a695706SAsahi Lina /// Construct a DRM ioctl number with no argument.
129a695706SAsahi Lina #[allow(non_snake_case)]
139a695706SAsahi Lina #[inline(always)]
149a695706SAsahi Lina pub const fn IO(nr: u32) -> u32 {
159a695706SAsahi Lina     ioctl::_IO(BASE, nr)
169a695706SAsahi Lina }
179a695706SAsahi Lina 
189a695706SAsahi Lina /// Construct a DRM ioctl number with a read-only argument.
199a695706SAsahi Lina #[allow(non_snake_case)]
209a695706SAsahi Lina #[inline(always)]
219a695706SAsahi Lina pub const fn IOR<T>(nr: u32) -> u32 {
229a695706SAsahi Lina     ioctl::_IOR::<T>(BASE, nr)
239a695706SAsahi Lina }
249a695706SAsahi Lina 
259a695706SAsahi Lina /// Construct a DRM ioctl number with a write-only argument.
269a695706SAsahi Lina #[allow(non_snake_case)]
279a695706SAsahi Lina #[inline(always)]
289a695706SAsahi Lina pub const fn IOW<T>(nr: u32) -> u32 {
299a695706SAsahi Lina     ioctl::_IOW::<T>(BASE, nr)
309a695706SAsahi Lina }
319a695706SAsahi Lina 
329a695706SAsahi Lina /// Construct a DRM ioctl number with a read-write argument.
339a695706SAsahi Lina #[allow(non_snake_case)]
349a695706SAsahi Lina #[inline(always)]
359a695706SAsahi Lina pub const fn IOWR<T>(nr: u32) -> u32 {
369a695706SAsahi Lina     ioctl::_IOWR::<T>(BASE, nr)
379a695706SAsahi Lina }
389a695706SAsahi Lina 
399a695706SAsahi Lina /// Descriptor type for DRM ioctls. Use the `declare_drm_ioctls!{}` macro to construct them.
409a695706SAsahi Lina pub type DrmIoctlDescriptor = bindings::drm_ioctl_desc;
419a695706SAsahi Lina 
429a695706SAsahi Lina /// This is for ioctl which are used for rendering, and require that the file descriptor is either
439a695706SAsahi Lina /// for a render node, or if it’s a legacy/primary node, then it must be authenticated.
449a695706SAsahi Lina pub const AUTH: u32 = bindings::drm_ioctl_flags_DRM_AUTH;
459a695706SAsahi Lina 
469a695706SAsahi Lina /// This must be set for any ioctl which can change the modeset or display state. Userspace must
479a695706SAsahi Lina /// call the ioctl through a primary node, while it is the active master.
489a695706SAsahi Lina ///
499a695706SAsahi Lina /// Note that read-only modeset ioctl can also be called by unauthenticated clients, or when a
509a695706SAsahi Lina /// master is not the currently active one.
519a695706SAsahi Lina pub const MASTER: u32 = bindings::drm_ioctl_flags_DRM_MASTER;
529a695706SAsahi Lina 
539a695706SAsahi Lina /// Anything that could potentially wreak a master file descriptor needs to have this flag set.
549a695706SAsahi Lina ///
559a695706SAsahi Lina /// Current that’s only for the SETMASTER and DROPMASTER ioctl, which e.g. logind can call to
569a695706SAsahi Lina /// force a non-behaving master (display compositor) into compliance.
579a695706SAsahi Lina ///
589a695706SAsahi Lina /// This is equivalent to callers with the SYSADMIN capability.
599a695706SAsahi Lina pub const ROOT_ONLY: u32 = bindings::drm_ioctl_flags_DRM_ROOT_ONLY;
609a695706SAsahi Lina 
619a695706SAsahi Lina /// This is used for all ioctl needed for rendering only, for drivers which support render nodes.
629a695706SAsahi Lina /// This should be all new render drivers, and hence it should be always set for any ioctl with
639a695706SAsahi Lina /// `AUTH` set. Note though that read-only query ioctl might have this set, but have not set
649a695706SAsahi Lina /// DRM_AUTH because they do not require authentication.
659a695706SAsahi Lina pub const RENDER_ALLOW: u32 = bindings::drm_ioctl_flags_DRM_RENDER_ALLOW;
669a695706SAsahi Lina 
679a695706SAsahi Lina /// Internal structures used by the `declare_drm_ioctls!{}` macro. Do not use directly.
689a695706SAsahi Lina #[doc(hidden)]
699a695706SAsahi Lina pub mod internal {
709a695706SAsahi Lina     pub use bindings::drm_device;
719a695706SAsahi Lina     pub use bindings::drm_file;
729a695706SAsahi Lina     pub use bindings::drm_ioctl_desc;
739a695706SAsahi Lina }
749a695706SAsahi Lina 
759a695706SAsahi Lina /// Declare the DRM ioctls for a driver.
769a695706SAsahi Lina ///
779a695706SAsahi Lina /// Each entry in the list should have the form:
789a695706SAsahi Lina ///
799a695706SAsahi Lina /// `(ioctl_number, argument_type, flags, user_callback),`
809a695706SAsahi Lina ///
819a695706SAsahi Lina /// `argument_type` is the type name within the `bindings` crate.
829a695706SAsahi Lina /// `user_callback` should have the following prototype:
839a695706SAsahi Lina ///
849a695706SAsahi Lina /// ```ignore
859a695706SAsahi Lina /// fn foo(device: &kernel::drm::Device<Self>,
869a695706SAsahi Lina ///        data: &Opaque<uapi::argument_type>,
879a695706SAsahi Lina ///        file: &kernel::drm::File<Self::File>,
889a695706SAsahi Lina /// ) -> Result<u32>
899a695706SAsahi Lina /// ```
909a695706SAsahi Lina /// where `Self` is the drm::drv::Driver implementation these ioctls are being declared within.
919a695706SAsahi Lina ///
929a695706SAsahi Lina /// # Examples
939a695706SAsahi Lina ///
949a695706SAsahi Lina /// ```ignore
959a695706SAsahi Lina /// kernel::declare_drm_ioctls! {
969a695706SAsahi Lina ///     (FOO_GET_PARAM, drm_foo_get_param, ioctl::RENDER_ALLOW, my_get_param_handler),
979a695706SAsahi Lina /// }
989a695706SAsahi Lina /// ```
999a695706SAsahi Lina ///
1009a695706SAsahi Lina #[macro_export]
1019a695706SAsahi Lina macro_rules! declare_drm_ioctls {
1029a695706SAsahi Lina     ( $(($cmd:ident, $struct:ident, $flags:expr, $func:expr)),* $(,)? ) => {
1039a695706SAsahi Lina         const IOCTLS: &'static [$crate::drm::ioctl::DrmIoctlDescriptor] = {
1049a695706SAsahi Lina             use $crate::uapi::*;
1059a695706SAsahi Lina             const _:() = {
1069a695706SAsahi Lina                 let i: u32 = $crate::uapi::DRM_COMMAND_BASE;
1079a695706SAsahi Lina                 // Assert that all the IOCTLs are in the right order and there are no gaps,
1089a695706SAsahi Lina                 // and that the size of the specified type is correct.
1099a695706SAsahi Lina                 $(
1109a695706SAsahi Lina                     let cmd: u32 = $crate::macros::concat_idents!(DRM_IOCTL_, $cmd);
1119a695706SAsahi Lina                     ::core::assert!(i == $crate::ioctl::_IOC_NR(cmd));
1129a695706SAsahi Lina                     ::core::assert!(core::mem::size_of::<$crate::uapi::$struct>() ==
1139a695706SAsahi Lina                                     $crate::ioctl::_IOC_SIZE(cmd));
1149a695706SAsahi Lina                     let i: u32 = i + 1;
1159a695706SAsahi Lina                 )*
1169a695706SAsahi Lina             };
1179a695706SAsahi Lina 
1189a695706SAsahi Lina             let ioctls = &[$(
1199a695706SAsahi Lina                 $crate::drm::ioctl::internal::drm_ioctl_desc {
1209a695706SAsahi Lina                     cmd: $crate::macros::concat_idents!(DRM_IOCTL_, $cmd) as u32,
1219a695706SAsahi Lina                     func: {
1229a695706SAsahi Lina                         #[allow(non_snake_case)]
1239a695706SAsahi Lina                         unsafe extern "C" fn $cmd(
1249a695706SAsahi Lina                                 raw_dev: *mut $crate::drm::ioctl::internal::drm_device,
1259a695706SAsahi Lina                                 raw_data: *mut ::core::ffi::c_void,
1269a695706SAsahi Lina                                 raw_file: *mut $crate::drm::ioctl::internal::drm_file,
1279a695706SAsahi Lina                         ) -> core::ffi::c_int {
1289a695706SAsahi Lina                             // SAFETY:
1299a695706SAsahi Lina                             // - The DRM core ensures the device lives while callbacks are being
1309a695706SAsahi Lina                             //   called.
1319a695706SAsahi Lina                             // - The DRM device must have been registered when we're called through
1329a695706SAsahi Lina                             //   an IOCTL.
1339a695706SAsahi Lina                             //
1349a695706SAsahi Lina                             // FIXME: Currently there is nothing enforcing that the types of the
1359a695706SAsahi Lina                             // dev/file match the current driver these ioctls are being declared
1369a695706SAsahi Lina                             // for, and it's not clear how to enforce this within the type system.
137*917b10d9SAlice Ryhl                             let dev = $crate::drm::device::Device::from_raw(raw_dev);
1389a695706SAsahi Lina                             // SAFETY: The ioctl argument has size `_IOC_SIZE(cmd)`, which we
1399a695706SAsahi Lina                             // asserted above matches the size of this type, and all bit patterns of
1409a695706SAsahi Lina                             // UAPI structs must be valid.
1419a695706SAsahi Lina                             let data = unsafe {
1429a695706SAsahi Lina                                 &*(raw_data as *const $crate::types::Opaque<$crate::uapi::$struct>)
1439a695706SAsahi Lina                             };
1449a695706SAsahi Lina                             // SAFETY: This is just the DRM file structure
145*917b10d9SAlice Ryhl                             let file = unsafe { $crate::drm::File::from_raw(raw_file) };
1469a695706SAsahi Lina 
1479a695706SAsahi Lina                             match $func(dev, data, file) {
1489a695706SAsahi Lina                                 Err(e) => e.to_errno(),
1499a695706SAsahi Lina                                 Ok(i) => i.try_into()
1509a695706SAsahi Lina                                             .unwrap_or($crate::error::code::ERANGE.to_errno()),
1519a695706SAsahi Lina                             }
1529a695706SAsahi Lina                         }
1539a695706SAsahi Lina                         Some($cmd)
1549a695706SAsahi Lina                     },
1559a695706SAsahi Lina                     flags: $flags,
1569a695706SAsahi Lina                     name: $crate::c_str!(::core::stringify!($cmd)).as_char_ptr(),
1579a695706SAsahi Lina                 }
1589a695706SAsahi Lina             ),*];
1599a695706SAsahi Lina             ioctls
1609a695706SAsahi Lina         };
1619a695706SAsahi Lina     };
1629a695706SAsahi Lina }
163