1 // SPDX-License-Identifier: GPL-2.0 OR MIT 2 3 //! DRM IOCTL definitions. 4 //! 5 //! C header: [`include/drm/drm_ioctl.h`](srctree/include/drm/drm_ioctl.h) 6 7 use crate::ioctl; 8 9 const BASE: u32 = uapi::DRM_IOCTL_BASE as u32; 10 11 /// Construct a DRM ioctl number with no argument. 12 #[allow(non_snake_case)] 13 #[inline(always)] 14 pub const fn IO(nr: u32) -> u32 { 15 ioctl::_IO(BASE, nr) 16 } 17 18 /// Construct a DRM ioctl number with a read-only argument. 19 #[allow(non_snake_case)] 20 #[inline(always)] 21 pub const fn IOR<T>(nr: u32) -> u32 { 22 ioctl::_IOR::<T>(BASE, nr) 23 } 24 25 /// Construct a DRM ioctl number with a write-only argument. 26 #[allow(non_snake_case)] 27 #[inline(always)] 28 pub const fn IOW<T>(nr: u32) -> u32 { 29 ioctl::_IOW::<T>(BASE, nr) 30 } 31 32 /// Construct a DRM ioctl number with a read-write argument. 33 #[allow(non_snake_case)] 34 #[inline(always)] 35 pub const fn IOWR<T>(nr: u32) -> u32 { 36 ioctl::_IOWR::<T>(BASE, nr) 37 } 38 39 /// Descriptor type for DRM ioctls. Use the `declare_drm_ioctls!{}` macro to construct them. 40 pub type DrmIoctlDescriptor = bindings::drm_ioctl_desc; 41 42 /// This is for ioctl which are used for rendering, and require that the file descriptor is either 43 /// for a render node, or if it’s a legacy/primary node, then it must be authenticated. 44 pub const AUTH: u32 = bindings::drm_ioctl_flags_DRM_AUTH; 45 46 /// This must be set for any ioctl which can change the modeset or display state. Userspace must 47 /// call the ioctl through a primary node, while it is the active master. 48 /// 49 /// Note that read-only modeset ioctl can also be called by unauthenticated clients, or when a 50 /// master is not the currently active one. 51 pub const MASTER: u32 = bindings::drm_ioctl_flags_DRM_MASTER; 52 53 /// Anything that could potentially wreak a master file descriptor needs to have this flag set. 54 /// 55 /// Current that’s only for the SETMASTER and DROPMASTER ioctl, which e.g. logind can call to 56 /// force a non-behaving master (display compositor) into compliance. 57 /// 58 /// This is equivalent to callers with the SYSADMIN capability. 59 pub const ROOT_ONLY: u32 = bindings::drm_ioctl_flags_DRM_ROOT_ONLY; 60 61 /// This is used for all ioctl needed for rendering only, for drivers which support render nodes. 62 /// This should be all new render drivers, and hence it should be always set for any ioctl with 63 /// `AUTH` set. Note though that read-only query ioctl might have this set, but have not set 64 /// DRM_AUTH because they do not require authentication. 65 pub const RENDER_ALLOW: u32 = bindings::drm_ioctl_flags_DRM_RENDER_ALLOW; 66 67 /// Internal structures used by the `declare_drm_ioctls!{}` macro. Do not use directly. 68 #[doc(hidden)] 69 pub mod internal { 70 pub use bindings::drm_device; 71 pub use bindings::drm_file; 72 pub use bindings::drm_ioctl_desc; 73 74 /// Cast an [`Ioctl`] DRM device pointer to [`Registered`], preserving the driver type 75 /// parameter `T`. 76 /// 77 /// Used by [`declare_drm_ioctls!`] to anchor type inference. 78 #[doc(hidden)] 79 #[inline] 80 pub const fn __dev_ctx_cast<T: crate::drm::Driver>( 81 ptr: *const crate::drm::Device<T, crate::drm::Ioctl>, 82 ) -> *const crate::drm::Device<T, crate::drm::Registered> { 83 ptr.cast() 84 } 85 } 86 87 /// Declare the DRM ioctls for a driver. 88 /// 89 /// Each entry in the list should have the form: 90 /// 91 /// `(ioctl_number, argument_type, flags, user_callback),` 92 /// 93 /// `argument_type` is the type name within the `bindings` crate. 94 /// `user_callback` should have the following prototype: 95 /// 96 /// ```ignore 97 /// fn foo(device: &kernel::drm::Device<Self, kernel::drm::Registered>, 98 /// reg_data: &Self::RegistrationData<'_>, 99 /// data: &mut uapi::argument_type, 100 /// file: &kernel::drm::File<Self::File>, 101 /// ) -> Result<u32> 102 /// ``` 103 /// where `Self` is the drm::drv::Driver implementation these ioctls are being declared within. 104 /// 105 /// # Examples 106 /// 107 /// ```ignore 108 /// kernel::declare_drm_ioctls! { 109 /// (FOO_GET_PARAM, drm_foo_get_param, ioctl::RENDER_ALLOW, my_get_param_handler), 110 /// } 111 /// ``` 112 /// 113 #[macro_export] 114 macro_rules! declare_drm_ioctls { 115 ( $(($cmd:ident, $struct:ident, $flags:expr, $func:expr)),* $(,)? ) => { 116 const IOCTLS: &'static [$crate::drm::ioctl::DrmIoctlDescriptor] = { 117 use $crate::uapi::*; 118 const _:() = { 119 let i: u32 = $crate::uapi::DRM_COMMAND_BASE; 120 // Assert that all the IOCTLs are in the right order and there are no gaps, 121 // and that the size of the specified type is correct. 122 $( 123 let cmd: u32 = $crate::macros::concat_idents!(DRM_IOCTL_, $cmd); 124 ::core::assert!(i == $crate::ioctl::_IOC_NR(cmd)); 125 ::core::assert!(core::mem::size_of::<$crate::uapi::$struct>() == 126 $crate::ioctl::_IOC_SIZE(cmd)); 127 let i: u32 = i + 1; 128 )* 129 }; 130 131 let ioctls = &[$( 132 $crate::drm::ioctl::internal::drm_ioctl_desc { 133 cmd: $crate::macros::concat_idents!(DRM_IOCTL_, $cmd) as u32, 134 func: { 135 #[allow(non_snake_case)] 136 unsafe extern "C" fn $cmd( 137 raw_dev: *mut $crate::drm::ioctl::internal::drm_device, 138 raw_data: *mut ::core::ffi::c_void, 139 raw_file: *mut $crate::drm::ioctl::internal::drm_file, 140 ) -> core::ffi::c_int { 141 // SAFETY: 142 // - The DRM core ensures the device lives while callbacks are being 143 // called. 144 // - The DRM device must have been registered when we're called through 145 // an IOCTL. 146 // 147 // INVARIANT: The `Ioctl` context requires that the device has been 148 // registered via `drm_dev_register()` at some point; the DRM core 149 // guarantees this for ioctl dispatch callbacks. 150 // 151 // FIXME: Currently there is nothing enforcing that the types of the 152 // dev/file match the current driver these ioctls are being declared 153 // for, and it's not clear how to enforce this within the type system. 154 let dev: &$crate::drm::device::Device<_, $crate::drm::Ioctl> = 155 $crate::drm::device::Device::from_raw(raw_dev); 156 157 // Type-inference anchor: the closure is never called but ties `dev`'s 158 // type to `$func`'s first parameter, which the compiler cannot infer 159 // through method resolution and associated-type projections alone. 160 #[allow(unreachable_code)] 161 let _ = || { 162 let __ptr = $crate::drm::ioctl::internal::__dev_ctx_cast( 163 ::core::ptr::from_ref(dev), 164 ); 165 166 $func( 167 // SAFETY: This closure is never executed; the dereference 168 // exists purely to unify the type parameter with `$func`. 169 // The pointer is valid regardless. 170 unsafe { &*__ptr }, 171 unreachable!(), 172 unreachable!(), 173 unreachable!(), 174 ) 175 }; 176 177 // Enforce that the handler accepts higher-ranked 178 // lifetimes, preventing it from requiring 'static 179 // references that could escape this scope. 180 let _: for<'a> fn(&'a _, &'a _, &'a mut _, &'a _) -> _ = $func; 181 182 let Some(guard) = dev.registration_guard() else { 183 return $crate::error::code::ENODEV.to_errno(); 184 }; 185 186 // SAFETY: The ioctl argument has size `_IOC_SIZE(cmd)`, which we 187 // asserted above matches the size of this type, and all bit patterns of 188 // UAPI structs must be valid. 189 // The `ioctl` argument is exclusively owned by the handler 190 // and guaranteed by the C implementation (`drm_ioctl()`) to remain 191 // valid for the entire lifetime of the reference taken here. 192 // There is no concurrent access or aliasing; no other references 193 // to this object exist during this call. 194 let data = unsafe { &mut *(raw_data.cast::<$crate::uapi::$struct>()) }; 195 // SAFETY: This is just the DRM file structure 196 let file = unsafe { $crate::drm::File::from_raw(raw_file) }; 197 198 match guard.registration_data_with(|reg_data| { 199 $func(&*guard, reg_data, data, file) 200 }) { 201 Err(e) => e.to_errno(), 202 Ok(i) => i.try_into() 203 .unwrap_or($crate::error::code::ERANGE.to_errno()), 204 } 205 } 206 Some($cmd) 207 }, 208 flags: $flags, 209 name: $crate::str::as_char_ptr_in_const_context( 210 $crate::c_str!(::core::stringify!($cmd)), 211 ), 212 } 213 ),*]; 214 ioctls 215 }; 216 }; 217 } 218