1 use std::{ffi::c_uint, io, os::unix::io::BorrowedFd}; 2 3 use drm_sys::*; 4 use rustix::ioctl::{ 5 ioctl, Getter, NoArg, NoneOpcode, ReadOpcode, ReadWriteOpcode, Setter, Updater, WriteOpcode, 6 }; 7 8 macro_rules! ioctl_readwrite { 9 ($name:ident, $ioty:expr, $nr:expr, $ty:ty) => { 10 pub unsafe fn $name(fd: BorrowedFd, data: &mut $ty) -> io::Result<()> { 11 type Opcode = ReadWriteOpcode<$ioty, $nr, $ty>; 12 Ok(ioctl(fd, Updater::<Opcode, $ty>::new(data))?) 13 } 14 }; 15 } 16 17 macro_rules! ioctl_read { 18 ($name:ident, $ioty:expr, $nr:expr, $ty:ty) => { 19 pub unsafe fn $name(fd: BorrowedFd) -> io::Result<$ty> { 20 type Opcode = ReadOpcode<$ioty, $nr, $ty>; 21 Ok(ioctl(fd, Getter::<Opcode, $ty>::new())?) 22 } 23 }; 24 } 25 26 macro_rules! ioctl_write_ptr { 27 ($name:ident, $ioty:expr, $nr:expr, $ty:ty) => { 28 pub unsafe fn $name(fd: BorrowedFd, data: &$ty) -> io::Result<()> { 29 type Opcode = WriteOpcode<$ioty, $nr, $ty>; 30 Ok(ioctl(fd, Setter::<Opcode, $ty>::new(*data))?) 31 } 32 }; 33 } 34 35 macro_rules! ioctl_none { 36 ($name:ident, $ioty:expr, $nr:expr) => { 37 pub unsafe fn $name(fd: BorrowedFd) -> io::Result<()> { 38 type Opcode = NoneOpcode<$ioty, $nr, ()>; 39 Ok(ioctl(fd, NoArg::<Opcode>::new())?) 40 } 41 }; 42 } 43 44 /// Gets the bus ID of the device 45 /// 46 /// # Locks DRM mutex: Yes 47 /// # Permissions: None 48 /// # Nodes: Primary 49 ioctl_readwrite!(get_bus_id, DRM_IOCTL_BASE, 0x01, drm_unique); 50 51 /// Get information about the client 52 /// 53 /// # Locks DRM mutex: No 54 /// # Permissions: None 55 /// # Nodes: Primary 56 ioctl_readwrite!(get_client, DRM_IOCTL_BASE, 0x05, drm_client); 57 58 /// Get capabilities of the device. 59 /// 60 /// # Locks DRM mutex: No 61 /// # Permissions: None 62 /// # Nodes: Primary, Render 63 ioctl_readwrite!(get_cap, DRM_IOCTL_BASE, 0x0c, drm_get_cap); 64 65 /// Tells the device we understand a capability 66 /// 67 /// # Locks DRM mutex: Yes 68 /// # Permissions: None 69 /// # Nodes: Primary 70 ioctl_write_ptr!(set_cap, DRM_IOCTL_BASE, 0x0d, drm_set_client_cap); 71 72 /// Sets the requested interface version 73 /// 74 /// # Locks DRM mutex: Yes 75 /// # Permissions: Master 76 /// # Nodes: Primary, control 77 ioctl_readwrite!(set_version, DRM_IOCTL_BASE, 0x07, drm_set_version); 78 79 /// Gets the current interface version 80 /// 81 /// # Locks DRM mutex: No 82 /// # Permissions: None 83 /// # Nodes: All 84 ioctl_readwrite!(get_version, DRM_IOCTL_BASE, 0x00, drm_version); 85 86 /// Generates the client's authentication token 87 /// 88 /// # Locks DRM mutex: No 89 /// # Permissions: None 90 /// # Nodes: Primary 91 ioctl_read!(get_token, DRM_IOCTL_BASE, 0x02, drm_auth); 92 93 /// Authenticates a client via their authentication token 94 /// 95 /// # Locks DRM mutex: No 96 /// # Permissions: Auth, Master 97 /// # Nodes: Primary 98 ioctl_write_ptr!(auth_token, DRM_IOCTL_BASE, 0x11, drm_auth); 99 100 /// Acquires the DRM Master lock 101 /// 102 /// # Locks DRM mutex: No 103 /// # Permissions: Root 104 /// # Nodes: Primary 105 ioctl_none!(acquire_master, DRM_IOCTL_BASE, 0x1e); 106 107 /// Drops the DRM Master lock 108 /// 109 /// # Locks DRM mutex: No 110 /// # Permissions: Root 111 /// # Nodes: Primary 112 ioctl_none!(release_master, DRM_IOCTL_BASE, 0x1f); 113 114 /// Gets the IRQ number 115 /// 116 /// # Locks DRM mutex: No 117 /// # Permissions: None 118 /// # Nodes: Primary 119 ioctl_readwrite!(get_irq_from_bus_id, DRM_IOCTL_BASE, 0x03, drm_irq_busid); 120 121 /// Enable the vblank interrupt and sleep until the requested sequence occurs 122 /// 123 /// # Locks DRM mutex: No 124 /// # Permissions: None 125 /// # Nodes: Primary 126 ioctl_readwrite!(wait_vblank, DRM_IOCTL_BASE, 0x3a, drm_wait_vblank); 127 128 pub(crate) mod mode { 129 use super::*; 130 131 /// Modesetting resources 132 ioctl_readwrite!(get_resources, DRM_IOCTL_BASE, 0xA0, drm_mode_card_res); 133 134 ioctl_readwrite!( 135 get_plane_resources, 136 DRM_IOCTL_BASE, 137 0xB5, 138 drm_mode_get_plane_res 139 ); 140 141 /// Connector related functions 142 ioctl_readwrite!(get_connector, DRM_IOCTL_BASE, 0xA7, drm_mode_get_connector); 143 144 /// Encoder related functions 145 ioctl_readwrite!(get_encoder, DRM_IOCTL_BASE, 0xA6, drm_mode_get_encoder); 146 147 /// CRTC related functions 148 ioctl_readwrite!(get_crtc, DRM_IOCTL_BASE, 0xA1, drm_mode_crtc); 149 ioctl_readwrite!(set_crtc, DRM_IOCTL_BASE, 0xA2, drm_mode_crtc); 150 151 /// Gamma related functions 152 ioctl_readwrite!(get_gamma, DRM_IOCTL_BASE, 0xA4, drm_mode_crtc_lut); 153 ioctl_readwrite!(set_gamma, DRM_IOCTL_BASE, 0xA5, drm_mode_crtc_lut); 154 155 // TODO: Figure out GAMMA LUT arrays 156 157 /// FB related functions 158 ioctl_readwrite!(get_fb, DRM_IOCTL_BASE, 0xAD, drm_mode_fb_cmd); 159 ioctl_readwrite!(get_fb2, DRM_IOCTL_BASE, 0xCE, drm_mode_fb_cmd2); 160 ioctl_readwrite!(add_fb, DRM_IOCTL_BASE, 0xAE, drm_mode_fb_cmd); 161 ioctl_readwrite!(add_fb2, DRM_IOCTL_BASE, 0xB8, drm_mode_fb_cmd2); 162 ioctl_readwrite!(rm_fb, DRM_IOCTL_BASE, 0xAF, c_uint); 163 164 /// Plane related functions 165 ioctl_readwrite!(get_plane, DRM_IOCTL_BASE, 0xB6, drm_mode_get_plane); 166 167 ioctl_readwrite!(set_plane, DRM_IOCTL_BASE, 0xB7, drm_mode_set_plane); 168 169 /// Dumbbuffer related functions 170 ioctl_readwrite!(create_dumb, DRM_IOCTL_BASE, 0xB2, drm_mode_create_dumb); 171 172 ioctl_readwrite!(map_dumb, DRM_IOCTL_BASE, 0xB3, drm_mode_map_dumb); 173 174 ioctl_readwrite!(destroy_dumb, DRM_IOCTL_BASE, 0xB4, drm_mode_destroy_dumb); 175 176 /// Cursor related functions 177 ioctl_readwrite!(cursor, DRM_IOCTL_BASE, 0xA3, drm_mode_cursor); 178 ioctl_readwrite!(cursor2, DRM_IOCTL_BASE, 0xBB, drm_mode_cursor2); 179 180 /// Property related functions 181 ioctl_readwrite!(get_property, DRM_IOCTL_BASE, 0xAA, drm_mode_get_property); 182 183 ioctl_readwrite!( 184 connector_set_property, 185 DRM_IOCTL_BASE, 186 0xAB, 187 drm_mode_connector_set_property 188 ); 189 190 ioctl_readwrite!( 191 obj_get_properties, 192 DRM_IOCTL_BASE, 193 0xB9, 194 drm_mode_obj_get_properties 195 ); 196 197 ioctl_readwrite!( 198 obj_set_property, 199 DRM_IOCTL_BASE, 200 0xBA, 201 drm_mode_obj_set_property 202 ); 203 204 /// Property blobs 205 ioctl_readwrite!(get_blob, DRM_IOCTL_BASE, 0xAC, drm_mode_get_blob); 206 207 // TODO: Property blobs probably require a large buffer 208 209 ioctl_readwrite!(create_blob, DRM_IOCTL_BASE, 0xBD, drm_mode_create_blob); 210 211 ioctl_readwrite!(destroy_blob, DRM_IOCTL_BASE, 0xBE, drm_mode_destroy_blob); 212 213 /// Atomic modesetting related functions 214 ioctl_readwrite!( 215 crtc_page_flip, 216 DRM_IOCTL_BASE, 217 0xB0, 218 drm_mode_crtc_page_flip 219 ); 220 221 ioctl_readwrite!(dirty_fb, DRM_IOCTL_BASE, 0xB1, drm_mode_fb_dirty_cmd); 222 223 ioctl_readwrite!(atomic, DRM_IOCTL_BASE, 0xBC, drm_mode_atomic); 224 225 ioctl_readwrite!(create_lease, DRM_IOCTL_BASE, 0xC6, drm_mode_create_lease); 226 ioctl_readwrite!(list_lessees, DRM_IOCTL_BASE, 0xC7, drm_mode_list_lessees); 227 ioctl_readwrite!(get_lease, DRM_IOCTL_BASE, 0xC8, drm_mode_get_lease); 228 ioctl_readwrite!(revoke_lease, DRM_IOCTL_BASE, 0xC9, drm_mode_revoke_lease); 229 } 230 231 pub(crate) mod gem { 232 use super::*; 233 234 /// GEM related functions 235 ioctl_readwrite!(open, DRM_IOCTL_BASE, 0x0b, drm_gem_open); 236 ioctl_write_ptr!(close, DRM_IOCTL_BASE, 0x09, drm_gem_close); 237 238 /// Converts a buffer handle into a dma-buf file descriptor. 239 ioctl_readwrite!(prime_handle_to_fd, DRM_IOCTL_BASE, 0x2d, drm_prime_handle); 240 241 /// Converts a dma-buf file descriptor into a buffer handle. 242 ioctl_readwrite!(prime_fd_to_handle, DRM_IOCTL_BASE, 0x2e, drm_prime_handle); 243 } 244 245 pub(crate) mod syncobj { 246 use super::*; 247 248 /// Creates a syncobj. 249 ioctl_readwrite!(create, DRM_IOCTL_BASE, 0xBF, drm_syncobj_create); 250 /// Destroys a syncobj. 251 ioctl_readwrite!(destroy, DRM_IOCTL_BASE, 0xC0, drm_syncobj_destroy); 252 /// Exports a syncobj as an inter-process file descriptor or as a poll()-able sync file. 253 ioctl_readwrite!(handle_to_fd, DRM_IOCTL_BASE, 0xC1, drm_syncobj_handle); 254 /// Imports a file descriptor exported by [`handle_to_fd`] back into a process-local handle. 255 ioctl_readwrite!(fd_to_handle, DRM_IOCTL_BASE, 0xC2, drm_syncobj_handle); 256 /// Waits for one or more syncobjs to become signalled. 257 ioctl_readwrite!(wait, DRM_IOCTL_BASE, 0xC3, drm_syncobj_wait); 258 /// Resets (un-signals) one or more syncobjs. 259 ioctl_readwrite!(reset, DRM_IOCTL_BASE, 0xC4, drm_syncobj_array); 260 /// Signals one or more syncobjs. 261 ioctl_readwrite!(signal, DRM_IOCTL_BASE, 0xC5, drm_syncobj_array); 262 263 /// Waits for one or more specific timeline syncobj points. 264 ioctl_readwrite!( 265 timeline_wait, 266 DRM_IOCTL_BASE, 267 0xCA, 268 drm_syncobj_timeline_wait 269 ); 270 /// Queries for state of one or more timeline syncobjs. 271 ioctl_readwrite!(query, DRM_IOCTL_BASE, 0xCB, drm_syncobj_timeline_array); 272 /// Transfers one timeline syncobj point to another. 273 ioctl_readwrite!(transfer, DRM_IOCTL_BASE, 0xCC, drm_syncobj_transfer); 274 /// Signals one or more specific timeline syncobj points. 275 ioctl_readwrite!( 276 timeline_signal, 277 DRM_IOCTL_BASE, 278 0xCD, 279 drm_syncobj_timeline_array 280 ); 281 /// Register an eventfd to be signalled by a syncobj. 282 ioctl_readwrite!(eventfd, DRM_IOCTL_BASE, 0xCF, drm_syncobj_eventfd); 283 } 284